2 * net/ife/ife.c - Inter-FE protocol based on ForCES WG InterFE LFB
3 * Copyright (c) 2015 Jamal Hadi Salim <jhs@mojatatu.com>
4 * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
6 * Refer to: draft-ietf-forces-interfelfb-03 and netdev01 paper:
7 * "Distributing Linux Traffic Control Classifier-Action Subsystem"
8 * Authors: Jamal Hadi Salim and Damascene M. Joachimpillai
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation.
15 #include <linux/types.h>
16 #include <linux/kernel.h>
17 #include <linux/string.h>
18 #include <linux/errno.h>
19 #include <linux/skbuff.h>
20 #include <linux/rtnetlink.h>
21 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <net/net_namespace.h>
24 #include <net/netlink.h>
25 #include <net/pkt_sched.h>
26 #include <linux/etherdevice.h>
34 void *ife_encode(struct sk_buff
*skb
, u16 metalen
)
36 /* OUTERHDR:TOTMETALEN:{TLVHDR:Metadatum:TLVHDR..}:ORIGDATA
37 * where ORIGDATA = original ethernet header ...
39 int hdrm
= metalen
+ IFE_METAHDRLEN
;
40 int total_push
= hdrm
+ skb
->dev
->hard_header_len
;
41 struct ifeheadr
*ifehdr
;
42 struct ethhdr
*iethh
; /* inner ether header */
46 err
= skb_cow_head(skb
, total_push
);
50 iethh
= (struct ethhdr
*) skb
->data
;
52 __skb_push(skb
, total_push
);
53 memcpy(skb
->data
, iethh
, skb
->dev
->hard_header_len
);
54 skb_reset_mac_header(skb
);
55 skboff
+= skb
->dev
->hard_header_len
;
57 /* total metadata length */
58 ifehdr
= (struct ifeheadr
*) (skb
->data
+ skboff
);
59 metalen
+= IFE_METAHDRLEN
;
60 ifehdr
->metalen
= htons(metalen
);
62 return ifehdr
->tlv_data
;
64 EXPORT_SYMBOL_GPL(ife_encode
);
66 void *ife_decode(struct sk_buff
*skb
, u16
*metalen
)
68 struct ifeheadr
*ifehdr
;
72 ifehdr
= (struct ifeheadr
*) (skb
->data
+ skb
->dev
->hard_header_len
);
73 ifehdrln
= ntohs(ifehdr
->metalen
);
74 total_pull
= skb
->dev
->hard_header_len
+ ifehdrln
;
76 if (unlikely(ifehdrln
< 2))
79 if (unlikely(!pskb_may_pull(skb
, total_pull
)))
82 skb_set_mac_header(skb
, total_pull
);
83 __skb_pull(skb
, total_pull
);
84 *metalen
= ifehdrln
- IFE_METAHDRLEN
;
86 return &ifehdr
->tlv_data
;
88 EXPORT_SYMBOL_GPL(ife_decode
);
95 /* Caller takes care of presenting data in network order
97 void *ife_tlv_meta_decode(void *skbdata
, u16
*attrtype
, u16
*dlen
, u16
*totlen
)
99 struct meta_tlvhdr
*tlv
= (struct meta_tlvhdr
*) skbdata
;
101 *dlen
= ntohs(tlv
->len
) - NLA_HDRLEN
;
102 *attrtype
= ntohs(tlv
->type
);
105 *totlen
= nla_total_size(*dlen
);
107 return skbdata
+ sizeof(struct meta_tlvhdr
);
109 EXPORT_SYMBOL_GPL(ife_tlv_meta_decode
);
111 void *ife_tlv_meta_next(void *skbdata
)
113 struct meta_tlvhdr
*tlv
= (struct meta_tlvhdr
*) skbdata
;
114 u16 tlvlen
= ntohs(tlv
->len
);
116 tlvlen
= NLA_ALIGN(tlvlen
);
118 return skbdata
+ tlvlen
;
120 EXPORT_SYMBOL_GPL(ife_tlv_meta_next
);
122 /* Caller takes care of presenting data in network order
124 int ife_tlv_meta_encode(void *skbdata
, u16 attrtype
, u16 dlen
, const void *dval
)
126 __be32
*tlv
= (__be32
*) (skbdata
);
127 u16 totlen
= nla_total_size(dlen
); /*alignment + hdr */
128 char *dptr
= (char *) tlv
+ NLA_HDRLEN
;
129 u32 htlv
= attrtype
<< 16 | (dlen
+ NLA_HDRLEN
);
132 memset(dptr
, 0, totlen
- NLA_HDRLEN
);
133 memcpy(dptr
, dval
, dlen
);
137 EXPORT_SYMBOL_GPL(ife_tlv_meta_encode
);
139 MODULE_AUTHOR("Jamal Hadi Salim <jhs@mojatatu.com>");
140 MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>");
141 MODULE_DESCRIPTION("Inter-FE LFB action");
142 MODULE_LICENSE("GPL");