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 if (!pskb_may_pull(skb
, skb
->dev
->hard_header_len
+ IFE_METAHDRLEN
))
75 ifehdr
= (struct ifeheadr
*) (skb
->data
+ skb
->dev
->hard_header_len
);
76 ifehdrln
= ntohs(ifehdr
->metalen
);
77 total_pull
= skb
->dev
->hard_header_len
+ ifehdrln
;
79 if (unlikely(ifehdrln
< 2))
82 if (unlikely(!pskb_may_pull(skb
, total_pull
)))
85 skb_set_mac_header(skb
, total_pull
);
86 __skb_pull(skb
, total_pull
);
87 *metalen
= ifehdrln
- IFE_METAHDRLEN
;
89 return &ifehdr
->tlv_data
;
91 EXPORT_SYMBOL_GPL(ife_decode
);
98 static bool __ife_tlv_meta_valid(const unsigned char *skbdata
,
99 const unsigned char *ifehdr_end
)
101 const struct meta_tlvhdr
*tlv
;
104 if (unlikely(skbdata
+ sizeof(*tlv
) > ifehdr_end
))
107 tlv
= (const struct meta_tlvhdr
*)skbdata
;
108 tlvlen
= ntohs(tlv
->len
);
110 /* tlv length field is inc header, check on minimum */
111 if (tlvlen
< NLA_HDRLEN
)
114 /* overflow by NLA_ALIGN check */
115 if (NLA_ALIGN(tlvlen
) < tlvlen
)
118 if (unlikely(skbdata
+ NLA_ALIGN(tlvlen
) > ifehdr_end
))
124 /* Caller takes care of presenting data in network order
126 void *ife_tlv_meta_decode(void *skbdata
, const void *ifehdr_end
, u16
*attrtype
,
127 u16
*dlen
, u16
*totlen
)
129 struct meta_tlvhdr
*tlv
;
131 if (!__ife_tlv_meta_valid(skbdata
, ifehdr_end
))
134 tlv
= (struct meta_tlvhdr
*)skbdata
;
135 *dlen
= ntohs(tlv
->len
) - NLA_HDRLEN
;
136 *attrtype
= ntohs(tlv
->type
);
139 *totlen
= nla_total_size(*dlen
);
141 return skbdata
+ sizeof(struct meta_tlvhdr
);
143 EXPORT_SYMBOL_GPL(ife_tlv_meta_decode
);
145 void *ife_tlv_meta_next(void *skbdata
)
147 struct meta_tlvhdr
*tlv
= (struct meta_tlvhdr
*) skbdata
;
148 u16 tlvlen
= ntohs(tlv
->len
);
150 tlvlen
= NLA_ALIGN(tlvlen
);
152 return skbdata
+ tlvlen
;
154 EXPORT_SYMBOL_GPL(ife_tlv_meta_next
);
156 /* Caller takes care of presenting data in network order
158 int ife_tlv_meta_encode(void *skbdata
, u16 attrtype
, u16 dlen
, const void *dval
)
160 __be32
*tlv
= (__be32
*) (skbdata
);
161 u16 totlen
= nla_total_size(dlen
); /*alignment + hdr */
162 char *dptr
= (char *) tlv
+ NLA_HDRLEN
;
163 u32 htlv
= attrtype
<< 16 | (dlen
+ NLA_HDRLEN
);
166 memset(dptr
, 0, totlen
- NLA_HDRLEN
);
167 memcpy(dptr
, dval
, dlen
);
171 EXPORT_SYMBOL_GPL(ife_tlv_meta_encode
);
173 MODULE_AUTHOR("Jamal Hadi Salim <jhs@mojatatu.com>");
174 MODULE_AUTHOR("Yotam Gigi <yotam.gi@gmail.com>");
175 MODULE_DESCRIPTION("Inter-FE LFB action");
176 MODULE_LICENSE("GPL");