]>
Commit | Line | Data |
---|---|---|
064af421 BP |
1 | /* |
2 | * Distributed under the terms of the GNU GPL version 2. | |
f632c8fc | 3 | * Copyright (c) 2007, 2008, 2009, 2010, 2011 Nicira Networks. |
a14bc59f BP |
4 | * |
5 | * Significant portions of this file may be copied from parts of the Linux | |
6 | * kernel, by Linus Torvalds and others. | |
064af421 BP |
7 | */ |
8 | ||
9 | #include "flow.h" | |
f5e86186 | 10 | #include "datapath.h" |
36956a7d | 11 | #include <asm/uaccess.h> |
064af421 BP |
12 | #include <linux/netdevice.h> |
13 | #include <linux/etherdevice.h> | |
14 | #include <linux/if_ether.h> | |
15 | #include <linux/if_vlan.h> | |
16 | #include <net/llc_pdu.h> | |
17 | #include <linux/kernel.h> | |
8d5ebd83 | 18 | #include <linux/jhash.h> |
064af421 BP |
19 | #include <linux/jiffies.h> |
20 | #include <linux/llc.h> | |
21 | #include <linux/module.h> | |
22 | #include <linux/in.h> | |
23 | #include <linux/rcupdate.h> | |
a26ef517 | 24 | #include <linux/if_arp.h> |
064af421 BP |
25 | #include <linux/if_ether.h> |
26 | #include <linux/ip.h> | |
27 | #include <linux/tcp.h> | |
28 | #include <linux/udp.h> | |
29 | #include <linux/icmp.h> | |
3c5f6de3 | 30 | #include <net/inet_ecn.h> |
064af421 BP |
31 | #include <net/ip.h> |
32 | ||
33b38b63 | 33 | static struct kmem_cache *flow_cache; |
83e3e75b | 34 | static unsigned int hash_seed __read_mostly; |
064af421 | 35 | |
e819fb47 | 36 | static inline bool arphdr_ok(struct sk_buff *skb) |
a26ef517 | 37 | { |
7d0ab001 | 38 | return skb->len >= skb_network_offset(skb) + sizeof(struct arp_eth_header); |
a26ef517 JP |
39 | } |
40 | ||
4c1ad233 | 41 | static inline int check_iphdr(struct sk_buff *skb) |
064af421 | 42 | { |
4c1ad233 BP |
43 | unsigned int nh_ofs = skb_network_offset(skb); |
44 | unsigned int ip_len; | |
45 | ||
46 | if (skb->len < nh_ofs + sizeof(struct iphdr)) | |
47 | return -EINVAL; | |
48 | ||
49 | ip_len = ip_hdrlen(skb); | |
50 | if (ip_len < sizeof(struct iphdr) || skb->len < nh_ofs + ip_len) | |
51 | return -EINVAL; | |
52 | ||
53 | /* | |
54 | * Pull enough header bytes to account for the IP header plus the | |
55 | * longest transport header that we parse, currently 20 bytes for TCP. | |
56 | */ | |
57 | if (!pskb_may_pull(skb, min(nh_ofs + ip_len + 20, skb->len))) | |
58 | return -ENOMEM; | |
59 | ||
60 | skb_set_transport_header(skb, nh_ofs + ip_len); | |
61 | return 0; | |
064af421 BP |
62 | } |
63 | ||
e819fb47 | 64 | static inline bool tcphdr_ok(struct sk_buff *skb) |
064af421 BP |
65 | { |
66 | int th_ofs = skb_transport_offset(skb); | |
7d0ab001 | 67 | if (skb->len >= th_ofs + sizeof(struct tcphdr)) { |
064af421 BP |
68 | int tcp_len = tcp_hdrlen(skb); |
69 | return (tcp_len >= sizeof(struct tcphdr) | |
70 | && skb->len >= th_ofs + tcp_len); | |
71 | } | |
e819fb47 | 72 | return false; |
064af421 BP |
73 | } |
74 | ||
e819fb47 | 75 | static inline bool udphdr_ok(struct sk_buff *skb) |
064af421 | 76 | { |
7d0ab001 | 77 | return skb->len >= skb_transport_offset(skb) + sizeof(struct udphdr); |
064af421 BP |
78 | } |
79 | ||
e819fb47 | 80 | static inline bool icmphdr_ok(struct sk_buff *skb) |
064af421 | 81 | { |
7d0ab001 | 82 | return skb->len >= skb_transport_offset(skb) + sizeof(struct icmphdr); |
064af421 BP |
83 | } |
84 | ||
85 | #define TCP_FLAGS_OFFSET 13 | |
86 | #define TCP_FLAG_MASK 0x3f | |
87 | ||
064af421 BP |
88 | void flow_used(struct sw_flow *flow, struct sk_buff *skb) |
89 | { | |
064af421 BP |
90 | u8 tcp_flags = 0; |
91 | ||
abfec865 BP |
92 | if (flow->key.dl_type == htons(ETH_P_IP) && |
93 | flow->key.nw_proto == IPPROTO_TCP) { | |
94 | u8 *tcp = (u8 *)tcp_hdr(skb); | |
95 | tcp_flags = *(tcp + TCP_FLAGS_OFFSET) & TCP_FLAG_MASK; | |
064af421 BP |
96 | } |
97 | ||
f2459fe7 | 98 | spin_lock_bh(&flow->lock); |
6bfafa55 | 99 | flow->used = jiffies; |
064af421 BP |
100 | flow->packet_count++; |
101 | flow->byte_count += skb->len; | |
102 | flow->tcp_flags |= tcp_flags; | |
f2459fe7 | 103 | spin_unlock_bh(&flow->lock); |
064af421 BP |
104 | } |
105 | ||
37a1300c | 106 | struct sw_flow_actions *flow_actions_alloc(const struct nlattr *actions) |
064af421 | 107 | { |
37a1300c | 108 | int actions_len = nla_len(actions); |
064af421 BP |
109 | struct sw_flow_actions *sfa; |
110 | ||
722d19c5 BP |
111 | /* At least DP_MAX_PORTS actions are required to be able to flood a |
112 | * packet to every port. Factor of 2 allows for setting VLAN tags, | |
113 | * etc. */ | |
cdee00fd | 114 | if (actions_len > 2 * DP_MAX_PORTS * nla_total_size(4)) |
064af421 BP |
115 | return ERR_PTR(-EINVAL); |
116 | ||
84c17d98 | 117 | sfa = kmalloc(sizeof(*sfa) + actions_len, GFP_KERNEL); |
064af421 BP |
118 | if (!sfa) |
119 | return ERR_PTR(-ENOMEM); | |
120 | ||
cdee00fd | 121 | sfa->actions_len = actions_len; |
37a1300c | 122 | memcpy(sfa->actions, nla_data(actions), actions_len); |
064af421 BP |
123 | return sfa; |
124 | } | |
125 | ||
560e8022 JG |
126 | struct sw_flow *flow_alloc(void) |
127 | { | |
128 | struct sw_flow *flow; | |
129 | ||
130 | flow = kmem_cache_alloc(flow_cache, GFP_KERNEL); | |
131 | if (!flow) | |
132 | return ERR_PTR(-ENOMEM); | |
133 | ||
134 | spin_lock_init(&flow->lock); | |
fb8c9347 JG |
135 | atomic_set(&flow->refcnt, 1); |
136 | flow->dead = false; | |
064af421 | 137 | |
560e8022 JG |
138 | return flow; |
139 | } | |
140 | ||
8d5ebd83 JG |
141 | void flow_free_tbl(struct tbl_node *node) |
142 | { | |
143 | struct sw_flow *flow = flow_cast(node); | |
fb8c9347 JG |
144 | |
145 | flow->dead = true; | |
146 | flow_put(flow); | |
8d5ebd83 JG |
147 | } |
148 | ||
064af421 BP |
149 | /* RCU callback used by flow_deferred_free. */ |
150 | static void rcu_free_flow_callback(struct rcu_head *rcu) | |
151 | { | |
152 | struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu); | |
fb8c9347 JG |
153 | |
154 | flow->dead = true; | |
155 | flow_put(flow); | |
064af421 BP |
156 | } |
157 | ||
158 | /* Schedules 'flow' to be freed after the next RCU grace period. | |
159 | * The caller must hold rcu_read_lock for this to be sensible. */ | |
160 | void flow_deferred_free(struct sw_flow *flow) | |
161 | { | |
162 | call_rcu(&flow->rcu, rcu_free_flow_callback); | |
163 | } | |
164 | ||
fb8c9347 JG |
165 | void flow_hold(struct sw_flow *flow) |
166 | { | |
167 | atomic_inc(&flow->refcnt); | |
168 | } | |
169 | ||
170 | void flow_put(struct sw_flow *flow) | |
171 | { | |
172 | if (unlikely(!flow)) | |
173 | return; | |
174 | ||
175 | if (atomic_dec_and_test(&flow->refcnt)) { | |
39872c70 | 176 | kfree((struct sf_flow_acts __force *)flow->sf_acts); |
fb8c9347 JG |
177 | kmem_cache_free(flow_cache, flow); |
178 | } | |
179 | } | |
180 | ||
064af421 BP |
181 | /* RCU callback used by flow_deferred_free_acts. */ |
182 | static void rcu_free_acts_callback(struct rcu_head *rcu) | |
183 | { | |
d295e8e9 | 184 | struct sw_flow_actions *sf_acts = container_of(rcu, |
064af421 BP |
185 | struct sw_flow_actions, rcu); |
186 | kfree(sf_acts); | |
187 | } | |
188 | ||
189 | /* Schedules 'sf_acts' to be freed after the next RCU grace period. | |
190 | * The caller must hold rcu_read_lock for this to be sensible. */ | |
191 | void flow_deferred_free_acts(struct sw_flow_actions *sf_acts) | |
192 | { | |
193 | call_rcu(&sf_acts->rcu, rcu_free_acts_callback); | |
194 | } | |
195 | ||
36956a7d | 196 | static void parse_vlan(struct sk_buff *skb, struct sw_flow_key *key) |
064af421 | 197 | { |
50f06e16 BP |
198 | struct qtag_prefix { |
199 | __be16 eth_type; /* ETH_P_8021Q */ | |
200 | __be16 tci; | |
201 | }; | |
202 | struct qtag_prefix *qp; | |
203 | ||
204 | if (skb->len < sizeof(struct qtag_prefix) + sizeof(__be16)) | |
205 | return; | |
206 | ||
207 | qp = (struct qtag_prefix *) skb->data; | |
36956a7d | 208 | key->dl_tci = qp->tci | htons(VLAN_TAG_PRESENT); |
50f06e16 BP |
209 | __skb_pull(skb, sizeof(struct qtag_prefix)); |
210 | } | |
211 | ||
212 | static __be16 parse_ethertype(struct sk_buff *skb) | |
064af421 | 213 | { |
50f06e16 BP |
214 | struct llc_snap_hdr { |
215 | u8 dsap; /* Always 0xAA */ | |
216 | u8 ssap; /* Always 0xAA */ | |
217 | u8 ctrl; | |
218 | u8 oui[3]; | |
8dda8c9b | 219 | __be16 ethertype; |
50f06e16 BP |
220 | }; |
221 | struct llc_snap_hdr *llc; | |
222 | __be16 proto; | |
223 | ||
224 | proto = *(__be16 *) skb->data; | |
225 | __skb_pull(skb, sizeof(__be16)); | |
226 | ||
36956a7d | 227 | if (ntohs(proto) >= 1536) |
50f06e16 BP |
228 | return proto; |
229 | ||
230 | if (unlikely(skb->len < sizeof(struct llc_snap_hdr))) | |
36956a7d | 231 | return htons(ETH_P_802_2); |
50f06e16 BP |
232 | |
233 | llc = (struct llc_snap_hdr *) skb->data; | |
234 | if (llc->dsap != LLC_SAP_SNAP || | |
235 | llc->ssap != LLC_SAP_SNAP || | |
236 | (llc->oui[0] | llc->oui[1] | llc->oui[2]) != 0) | |
36956a7d | 237 | return htons(ETH_P_802_2); |
50f06e16 BP |
238 | |
239 | __skb_pull(skb, sizeof(struct llc_snap_hdr)); | |
240 | return llc->ethertype; | |
064af421 BP |
241 | } |
242 | ||
a31e0e31 BP |
243 | /** |
244 | * flow_extract - extracts a flow key from an Ethernet frame. | |
245 | * @skb: sk_buff that contains the frame, with skb->data pointing to the | |
246 | * Ethernet header | |
247 | * @in_port: port number on which @skb was received. | |
248 | * @key: output flow key | |
26233bb4 BP |
249 | * @is_frag: set to 1 if @skb contains an IPv4 fragment, or to 0 if @skb does |
250 | * not contain an IPv4 packet or if it is not a fragment. | |
a31e0e31 BP |
251 | * |
252 | * The caller must ensure that skb->len >= ETH_HLEN. | |
253 | * | |
4c1ad233 BP |
254 | * Returns 0 if successful, otherwise a negative errno value. |
255 | * | |
59a18f80 BP |
256 | * Initializes @skb header pointers as follows: |
257 | * | |
258 | * - skb->mac_header: the Ethernet header. | |
259 | * | |
260 | * - skb->network_header: just past the Ethernet header, or just past the | |
261 | * VLAN header, to the first byte of the Ethernet payload. | |
262 | * | |
263 | * - skb->transport_header: If key->dl_type is ETH_P_IP on output, then just | |
264 | * past the IPv4 header, if one is present and of a correct length, | |
265 | * otherwise the same as skb->network_header. For other key->dl_type | |
266 | * values it is left untouched. | |
a31e0e31 | 267 | */ |
36956a7d | 268 | int flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key, |
b7a31ec1 | 269 | bool *is_frag) |
064af421 BP |
270 | { |
271 | struct ethhdr *eth; | |
064af421 | 272 | |
84c17d98 | 273 | memset(key, 0, sizeof(*key)); |
659586ef | 274 | key->tun_id = OVS_CB(skb)->tun_id; |
064af421 | 275 | key->in_port = in_port; |
b7a31ec1 | 276 | *is_frag = false; |
064af421 | 277 | |
4c1ad233 BP |
278 | /* |
279 | * We would really like to pull as many bytes as we could possibly | |
280 | * want to parse into the linear data area. Currently that is: | |
281 | * | |
282 | * 14 Ethernet header | |
283 | * 4 VLAN header | |
284 | * 60 max IP header with options | |
285 | * 20 max TCP/UDP/ICMP header (don't care about options) | |
286 | * -- | |
287 | * 98 | |
288 | * | |
289 | * But Xen only allocates 64 or 72 bytes for the linear data area in | |
290 | * netback, which means that we would reallocate and copy the skb's | |
291 | * linear data on every packet if we did that. So instead just pull 64 | |
292 | * bytes, which is always sufficient without IP options, and then check | |
293 | * whether we need to pull more later when we look at the IP header. | |
294 | */ | |
d9fce1ca | 295 | if (!pskb_may_pull(skb, min(skb->len, 64u))) |
4c1ad233 | 296 | return -ENOMEM; |
064af421 BP |
297 | |
298 | skb_reset_mac_header(skb); | |
064af421 | 299 | |
50f06e16 BP |
300 | /* Link layer. */ |
301 | eth = eth_hdr(skb); | |
064af421 BP |
302 | memcpy(key->dl_src, eth->h_source, ETH_ALEN); |
303 | memcpy(key->dl_dst, eth->h_dest, ETH_ALEN); | |
50f06e16 BP |
304 | |
305 | /* dl_type, dl_vlan, dl_vlan_pcp. */ | |
306 | __skb_pull(skb, 2 * ETH_ALEN); | |
307 | if (eth->h_proto == htons(ETH_P_8021Q)) | |
308 | parse_vlan(skb, key); | |
309 | key->dl_type = parse_ethertype(skb); | |
310 | skb_reset_network_header(skb); | |
311 | __skb_push(skb, skb->data - (unsigned char *)eth); | |
064af421 BP |
312 | |
313 | /* Network layer. */ | |
4c1ad233 BP |
314 | if (key->dl_type == htons(ETH_P_IP)) { |
315 | struct iphdr *nh; | |
316 | int error; | |
317 | ||
318 | error = check_iphdr(skb); | |
319 | if (unlikely(error)) { | |
320 | if (error == -EINVAL) { | |
321 | skb->transport_header = skb->network_header; | |
322 | return 0; | |
323 | } | |
324 | return error; | |
325 | } | |
326 | ||
327 | nh = ip_hdr(skb); | |
064af421 BP |
328 | key->nw_src = nh->saddr; |
329 | key->nw_dst = nh->daddr; | |
f5e86186 | 330 | key->nw_tos = nh->tos & ~INET_ECN_MASK; |
064af421 | 331 | key->nw_proto = nh->protocol; |
064af421 BP |
332 | |
333 | /* Transport layer. */ | |
875244c7 SH |
334 | if (!(nh->frag_off & htons(IP_MF | IP_OFFSET)) && |
335 | !(skb_shinfo(skb)->gso_type & SKB_GSO_UDP)) { | |
064af421 BP |
336 | if (key->nw_proto == IPPROTO_TCP) { |
337 | if (tcphdr_ok(skb)) { | |
338 | struct tcphdr *tcp = tcp_hdr(skb); | |
339 | key->tp_src = tcp->source; | |
340 | key->tp_dst = tcp->dest; | |
064af421 BP |
341 | } |
342 | } else if (key->nw_proto == IPPROTO_UDP) { | |
343 | if (udphdr_ok(skb)) { | |
344 | struct udphdr *udp = udp_hdr(skb); | |
345 | key->tp_src = udp->source; | |
346 | key->tp_dst = udp->dest; | |
064af421 BP |
347 | } |
348 | } else if (key->nw_proto == IPPROTO_ICMP) { | |
349 | if (icmphdr_ok(skb)) { | |
350 | struct icmphdr *icmp = icmp_hdr(skb); | |
351 | /* The ICMP type and code fields use the 16-bit | |
352 | * transport port fields, so we need to store them | |
353 | * in 16-bit network byte order. */ | |
354 | key->tp_src = htons(icmp->type); | |
355 | key->tp_dst = htons(icmp->code); | |
064af421 BP |
356 | } |
357 | } | |
b7a31ec1 JG |
358 | } else |
359 | *is_frag = true; | |
360 | ||
a26ef517 JP |
361 | } else if (key->dl_type == htons(ETH_P_ARP) && arphdr_ok(skb)) { |
362 | struct arp_eth_header *arp; | |
363 | ||
364 | arp = (struct arp_eth_header *)skb_network_header(skb); | |
365 | ||
f5e86186 | 366 | if (arp->ar_hrd == htons(ARPHRD_ETHER) |
de3f65ea JP |
367 | && arp->ar_pro == htons(ETH_P_IP) |
368 | && arp->ar_hln == ETH_ALEN | |
369 | && arp->ar_pln == 4) { | |
370 | ||
371 | /* We only match on the lower 8 bits of the opcode. */ | |
b7a31ec1 | 372 | if (ntohs(arp->ar_op) <= 0xff) |
de3f65ea | 373 | key->nw_proto = ntohs(arp->ar_op); |
de3f65ea | 374 | |
d295e8e9 | 375 | if (key->nw_proto == ARPOP_REQUEST |
de3f65ea JP |
376 | || key->nw_proto == ARPOP_REPLY) { |
377 | memcpy(&key->nw_src, arp->ar_sip, sizeof(key->nw_src)); | |
378 | memcpy(&key->nw_dst, arp->ar_tip, sizeof(key->nw_dst)); | |
379 | } | |
380 | } | |
064af421 | 381 | } |
769f8ccd | 382 | return 0; |
064af421 BP |
383 | } |
384 | ||
36956a7d | 385 | u32 flow_hash(const struct sw_flow_key *key) |
8d5ebd83 | 386 | { |
84c17d98 | 387 | return jhash2((u32*)key, sizeof(*key) / sizeof(u32), hash_seed); |
8d5ebd83 JG |
388 | } |
389 | ||
390 | int flow_cmp(const struct tbl_node *node, void *key2_) | |
391 | { | |
36956a7d BP |
392 | const struct sw_flow_key *key1 = &flow_cast(node)->key; |
393 | const struct sw_flow_key *key2 = key2_; | |
8d5ebd83 | 394 | |
36956a7d BP |
395 | return !memcmp(key1, key2, sizeof(struct sw_flow_key)); |
396 | } | |
397 | ||
398 | /** | |
399 | * flow_from_nlattrs - parses Netlink attributes into a flow key. | |
400 | * @swkey: receives the extracted flow key. | |
d6569377 BP |
401 | * @key: Netlink attribute holding nested %ODP_KEY_ATTR_* Netlink attribute |
402 | * sequence. | |
36956a7d BP |
403 | * |
404 | * This state machine accepts the following forms, with [] for optional | |
405 | * elements and | for alternatives: | |
406 | * | |
407 | * [tun_id] in_port ethernet [8021q] [ethertype [IP [TCP|UDP|ICMP] | ARP] | |
408 | */ | |
d6569377 | 409 | int flow_from_nlattrs(struct sw_flow_key *swkey, const struct nlattr *attr) |
36956a7d BP |
410 | { |
411 | const struct nlattr *nla; | |
412 | u16 prev_type; | |
413 | int rem; | |
414 | ||
415 | memset(swkey, 0, sizeof(*swkey)); | |
416 | swkey->dl_type = htons(ETH_P_802_2); | |
417 | ||
418 | prev_type = ODP_KEY_ATTR_UNSPEC; | |
d6569377 | 419 | nla_for_each_nested(nla, attr, rem) { |
36956a7d BP |
420 | static const u32 key_lens[ODP_KEY_ATTR_MAX + 1] = { |
421 | [ODP_KEY_ATTR_TUN_ID] = 8, | |
422 | [ODP_KEY_ATTR_IN_PORT] = 4, | |
423 | [ODP_KEY_ATTR_ETHERNET] = sizeof(struct odp_key_ethernet), | |
424 | [ODP_KEY_ATTR_8021Q] = sizeof(struct odp_key_8021q), | |
425 | [ODP_KEY_ATTR_ETHERTYPE] = 2, | |
426 | [ODP_KEY_ATTR_IPV4] = sizeof(struct odp_key_ipv4), | |
427 | [ODP_KEY_ATTR_TCP] = sizeof(struct odp_key_tcp), | |
428 | [ODP_KEY_ATTR_UDP] = sizeof(struct odp_key_udp), | |
429 | [ODP_KEY_ATTR_ICMP] = sizeof(struct odp_key_icmp), | |
430 | [ODP_KEY_ATTR_ARP] = sizeof(struct odp_key_arp), | |
431 | }; | |
432 | ||
433 | const struct odp_key_ethernet *eth_key; | |
434 | const struct odp_key_8021q *q_key; | |
435 | const struct odp_key_ipv4 *ipv4_key; | |
436 | const struct odp_key_tcp *tcp_key; | |
437 | const struct odp_key_udp *udp_key; | |
438 | const struct odp_key_icmp *icmp_key; | |
439 | const struct odp_key_arp *arp_key; | |
440 | ||
441 | int type = nla_type(nla); | |
442 | ||
443 | if (type > ODP_KEY_ATTR_MAX || nla_len(nla) != key_lens[type]) | |
444 | return -EINVAL; | |
445 | ||
446 | #define TRANSITION(PREV_TYPE, TYPE) (((PREV_TYPE) << 16) | (TYPE)) | |
447 | switch (TRANSITION(prev_type, type)) { | |
448 | case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_TUN_ID): | |
449 | swkey->tun_id = nla_get_be64(nla); | |
450 | break; | |
451 | ||
452 | case TRANSITION(ODP_KEY_ATTR_UNSPEC, ODP_KEY_ATTR_IN_PORT): | |
453 | case TRANSITION(ODP_KEY_ATTR_TUN_ID, ODP_KEY_ATTR_IN_PORT): | |
454 | if (nla_get_u32(nla) >= DP_MAX_PORTS) | |
455 | return -EINVAL; | |
456 | swkey->in_port = nla_get_u32(nla); | |
457 | break; | |
458 | ||
459 | case TRANSITION(ODP_KEY_ATTR_IN_PORT, ODP_KEY_ATTR_ETHERNET): | |
460 | eth_key = nla_data(nla); | |
461 | memcpy(swkey->dl_src, eth_key->eth_src, ETH_ALEN); | |
462 | memcpy(swkey->dl_dst, eth_key->eth_dst, ETH_ALEN); | |
463 | break; | |
464 | ||
465 | case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_8021Q): | |
466 | q_key = nla_data(nla); | |
467 | /* Only standard 0x8100 VLANs currently supported. */ | |
468 | if (q_key->q_tpid != htons(ETH_P_8021Q)) | |
469 | return -EINVAL; | |
470 | if (q_key->q_tci & htons(VLAN_TAG_PRESENT)) | |
471 | return -EINVAL; | |
472 | swkey->dl_tci = q_key->q_tci | htons(VLAN_TAG_PRESENT); | |
473 | break; | |
474 | ||
475 | case TRANSITION(ODP_KEY_ATTR_8021Q, ODP_KEY_ATTR_ETHERTYPE): | |
476 | case TRANSITION(ODP_KEY_ATTR_ETHERNET, ODP_KEY_ATTR_ETHERTYPE): | |
477 | swkey->dl_type = nla_get_be16(nla); | |
478 | if (ntohs(swkey->dl_type) < 1536) | |
479 | return -EINVAL; | |
480 | break; | |
481 | ||
482 | case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_IPV4): | |
483 | if (swkey->dl_type != htons(ETH_P_IP)) | |
484 | return -EINVAL; | |
485 | ipv4_key = nla_data(nla); | |
486 | swkey->nw_src = ipv4_key->ipv4_src; | |
487 | swkey->nw_dst = ipv4_key->ipv4_dst; | |
488 | swkey->nw_proto = ipv4_key->ipv4_proto; | |
489 | swkey->nw_tos = ipv4_key->ipv4_tos; | |
490 | if (swkey->nw_tos & INET_ECN_MASK) | |
491 | return -EINVAL; | |
492 | break; | |
493 | ||
494 | case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_TCP): | |
495 | if (swkey->nw_proto != IPPROTO_TCP) | |
496 | return -EINVAL; | |
497 | tcp_key = nla_data(nla); | |
498 | swkey->tp_src = tcp_key->tcp_src; | |
499 | swkey->tp_dst = tcp_key->tcp_dst; | |
500 | break; | |
501 | ||
502 | case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_UDP): | |
503 | if (swkey->nw_proto != IPPROTO_UDP) | |
504 | return -EINVAL; | |
505 | udp_key = nla_data(nla); | |
506 | swkey->tp_src = udp_key->udp_src; | |
507 | swkey->tp_dst = udp_key->udp_dst; | |
508 | break; | |
509 | ||
510 | case TRANSITION(ODP_KEY_ATTR_IPV4, ODP_KEY_ATTR_ICMP): | |
511 | if (swkey->nw_proto != IPPROTO_ICMP) | |
512 | return -EINVAL; | |
513 | icmp_key = nla_data(nla); | |
514 | swkey->tp_src = htons(icmp_key->icmp_type); | |
515 | swkey->tp_dst = htons(icmp_key->icmp_code); | |
516 | break; | |
517 | ||
518 | case TRANSITION(ODP_KEY_ATTR_ETHERTYPE, ODP_KEY_ATTR_ARP): | |
519 | if (swkey->dl_type != htons(ETH_P_ARP)) | |
520 | return -EINVAL; | |
521 | arp_key = nla_data(nla); | |
522 | swkey->nw_src = arp_key->arp_sip; | |
523 | swkey->nw_dst = arp_key->arp_tip; | |
524 | if (arp_key->arp_op & htons(0xff00)) | |
525 | return -EINVAL; | |
526 | swkey->nw_proto = ntohs(arp_key->arp_op); | |
527 | break; | |
528 | ||
529 | default: | |
530 | return -EINVAL; | |
531 | } | |
532 | ||
533 | prev_type = type; | |
534 | } | |
535 | if (rem) | |
536 | return -EINVAL; | |
537 | ||
538 | switch (prev_type) { | |
539 | case ODP_KEY_ATTR_UNSPEC: | |
540 | return -EINVAL; | |
541 | ||
542 | case ODP_KEY_ATTR_TUN_ID: | |
543 | case ODP_KEY_ATTR_IN_PORT: | |
544 | return -EINVAL; | |
545 | ||
546 | case ODP_KEY_ATTR_ETHERNET: | |
547 | case ODP_KEY_ATTR_8021Q: | |
548 | return 0; | |
549 | ||
550 | case ODP_KEY_ATTR_ETHERTYPE: | |
551 | if (swkey->dl_type == htons(ETH_P_IP) || | |
552 | swkey->dl_type == htons(ETH_P_ARP)) | |
553 | return -EINVAL; | |
554 | return 0; | |
555 | ||
556 | case ODP_KEY_ATTR_IPV4: | |
557 | if (swkey->nw_proto == IPPROTO_TCP || | |
558 | swkey->nw_proto == IPPROTO_UDP || | |
559 | swkey->nw_proto == IPPROTO_ICMP) | |
560 | return -EINVAL; | |
561 | return 0; | |
562 | ||
563 | case ODP_KEY_ATTR_TCP: | |
564 | case ODP_KEY_ATTR_UDP: | |
565 | case ODP_KEY_ATTR_ICMP: | |
566 | case ODP_KEY_ATTR_ARP: | |
567 | return 0; | |
568 | } | |
569 | ||
570 | WARN_ON_ONCE(1); | |
571 | return -EINVAL; | |
572 | } | |
573 | ||
d6569377 | 574 | int flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb) |
36956a7d BP |
575 | { |
576 | struct odp_key_ethernet *eth_key; | |
d6569377 | 577 | struct nlattr *nla; |
36956a7d BP |
578 | |
579 | if (swkey->tun_id != cpu_to_be64(0)) | |
d6569377 | 580 | NLA_PUT_BE64(skb, ODP_KEY_ATTR_TUN_ID, swkey->tun_id); |
36956a7d | 581 | |
d6569377 | 582 | NLA_PUT_U32(skb, ODP_KEY_ATTR_IN_PORT, swkey->in_port); |
36956a7d | 583 | |
d6569377 BP |
584 | nla = nla_reserve(skb, ODP_KEY_ATTR_ETHERNET, sizeof(*eth_key)); |
585 | if (!nla) | |
586 | goto nla_put_failure; | |
587 | eth_key = nla_data(nla); | |
36956a7d BP |
588 | memcpy(eth_key->eth_src, swkey->dl_src, ETH_ALEN); |
589 | memcpy(eth_key->eth_dst, swkey->dl_dst, ETH_ALEN); | |
590 | ||
591 | if (swkey->dl_tci != htons(0)) { | |
d6569377 | 592 | struct odp_key_8021q q_key; |
36956a7d | 593 | |
d6569377 BP |
594 | q_key.q_tpid = htons(ETH_P_8021Q); |
595 | q_key.q_tci = swkey->dl_tci & ~htons(VLAN_TAG_PRESENT); | |
596 | NLA_PUT(skb, ODP_KEY_ATTR_8021Q, sizeof(q_key), &q_key); | |
36956a7d BP |
597 | } |
598 | ||
599 | if (swkey->dl_type == htons(ETH_P_802_2)) | |
d6569377 | 600 | return 0; |
36956a7d | 601 | |
d6569377 | 602 | NLA_PUT_BE16(skb, ODP_KEY_ATTR_ETHERTYPE, swkey->dl_type); |
36956a7d BP |
603 | |
604 | if (swkey->dl_type == htons(ETH_P_IP)) { | |
605 | struct odp_key_ipv4 *ipv4_key; | |
606 | ||
d6569377 BP |
607 | nla = nla_reserve(skb, ODP_KEY_ATTR_IPV4, sizeof(*ipv4_key)); |
608 | if (!nla) | |
609 | goto nla_put_failure; | |
610 | ipv4_key = nla_data(nla); | |
36956a7d BP |
611 | ipv4_key->ipv4_src = swkey->nw_src; |
612 | ipv4_key->ipv4_dst = swkey->nw_dst; | |
613 | ipv4_key->ipv4_proto = swkey->nw_proto; | |
614 | ipv4_key->ipv4_tos = swkey->nw_tos; | |
615 | ||
616 | if (swkey->nw_proto == IPPROTO_TCP) { | |
617 | struct odp_key_tcp *tcp_key; | |
618 | ||
d6569377 BP |
619 | nla = nla_reserve(skb, ODP_KEY_ATTR_TCP, sizeof(*tcp_key)); |
620 | if (!nla) | |
621 | goto nla_put_failure; | |
622 | tcp_key = nla_data(nla); | |
36956a7d BP |
623 | tcp_key->tcp_src = swkey->tp_src; |
624 | tcp_key->tcp_dst = swkey->tp_dst; | |
625 | } else if (swkey->nw_proto == IPPROTO_UDP) { | |
626 | struct odp_key_udp *udp_key; | |
627 | ||
d6569377 BP |
628 | nla = nla_reserve(skb, ODP_KEY_ATTR_UDP, sizeof(*udp_key)); |
629 | if (!nla) | |
630 | goto nla_put_failure; | |
631 | udp_key = nla_data(nla); | |
36956a7d BP |
632 | udp_key->udp_src = swkey->tp_src; |
633 | udp_key->udp_dst = swkey->tp_dst; | |
634 | } else if (swkey->nw_proto == IPPROTO_ICMP) { | |
635 | struct odp_key_icmp *icmp_key; | |
636 | ||
d6569377 BP |
637 | nla = nla_reserve(skb, ODP_KEY_ATTR_ICMP, sizeof(*icmp_key)); |
638 | if (!nla) | |
639 | goto nla_put_failure; | |
640 | icmp_key = nla_data(nla); | |
36956a7d BP |
641 | icmp_key->icmp_type = ntohs(swkey->tp_src); |
642 | icmp_key->icmp_code = ntohs(swkey->tp_dst); | |
643 | } | |
644 | } else if (swkey->dl_type == htons(ETH_P_ARP)) { | |
645 | struct odp_key_arp *arp_key; | |
646 | ||
d6569377 BP |
647 | nla = nla_reserve(skb, ODP_KEY_ATTR_ARP, sizeof(*arp_key)); |
648 | if (!nla) | |
649 | goto nla_put_failure; | |
650 | arp_key = nla_data(nla); | |
36956a7d BP |
651 | arp_key->arp_sip = swkey->nw_src; |
652 | arp_key->arp_tip = swkey->nw_dst; | |
653 | arp_key->arp_op = htons(swkey->nw_proto); | |
654 | } | |
655 | ||
d6569377 | 656 | return 0; |
36956a7d | 657 | |
d6569377 BP |
658 | nla_put_failure: |
659 | return -EMSGSIZE; | |
8d5ebd83 JG |
660 | } |
661 | ||
064af421 BP |
662 | /* Initializes the flow module. |
663 | * Returns zero if successful or a negative error code. */ | |
664 | int flow_init(void) | |
665 | { | |
666 | flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow), 0, | |
667 | 0, NULL); | |
668 | if (flow_cache == NULL) | |
669 | return -ENOMEM; | |
670 | ||
84c17d98 | 671 | get_random_bytes(&hash_seed, sizeof(hash_seed)); |
8d5ebd83 | 672 | |
064af421 BP |
673 | return 0; |
674 | } | |
675 | ||
676 | /* Uninitializes the flow module. */ | |
677 | void flow_exit(void) | |
678 | { | |
679 | kmem_cache_destroy(flow_cache); | |
680 | } |