Blame view

net/openvswitch/flow.c 54.9 KB
ccb1352e7   Jesse Gross   net: Add Open vSw...
1
  /*
03f0d916a   Andy Zhou   openvswitch: Mega...
2
   * Copyright (c) 2007-2013 Nicira, Inc.
ccb1352e7   Jesse Gross   net: Add Open vSw...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of version 2 of the GNU General Public
   * License as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   * 02110-1301, USA
   */
  
  #include "flow.h"
  #include "datapath.h"
  #include <linux/uaccess.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/if_ether.h>
  #include <linux/if_vlan.h>
  #include <net/llc_pdu.h>
  #include <linux/kernel.h>
  #include <linux/jhash.h>
  #include <linux/jiffies.h>
  #include <linux/llc.h>
  #include <linux/module.h>
  #include <linux/in.h>
  #include <linux/rcupdate.h>
  #include <linux/if_arp.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
35
36
  #include <linux/ip.h>
  #include <linux/ipv6.h>
a175a7233   Joe Stringer   openvswitch: Add ...
37
  #include <linux/sctp.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
38
39
40
41
42
43
  #include <linux/tcp.h>
  #include <linux/udp.h>
  #include <linux/icmp.h>
  #include <linux/icmpv6.h>
  #include <linux/rculist.h>
  #include <net/ip.h>
7d5437c70   Pravin B Shelar   openvswitch: Add ...
44
  #include <net/ip_tunnels.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
45
46
47
48
  #include <net/ipv6.h>
  #include <net/ndisc.h>
  
  static struct kmem_cache *flow_cache;
03f0d916a   Andy Zhou   openvswitch: Mega...
49
50
51
52
53
54
55
  static void ovs_sw_flow_mask_set(struct sw_flow_mask *mask,
  		struct sw_flow_key_range *range, u8 val);
  
  static void update_range__(struct sw_flow_match *match,
  			  size_t offset, size_t size, bool is_mask)
  {
  	struct sw_flow_key_range *range = NULL;
5828cd9a6   Andy Zhou   openvswitch: opti...
56
57
  	size_t start = rounddown(offset, sizeof(long));
  	size_t end = roundup(offset + size, sizeof(long));
03f0d916a   Andy Zhou   openvswitch: Mega...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
  
  	if (!is_mask)
  		range = &match->range;
  	else if (match->mask)
  		range = &match->mask->range;
  
  	if (!range)
  		return;
  
  	if (range->start == range->end) {
  		range->start = start;
  		range->end = end;
  		return;
  	}
  
  	if (range->start > start)
  		range->start = start;
  
  	if (range->end < end)
  		range->end = end;
  }
  
  #define SW_FLOW_KEY_PUT(match, field, value, is_mask) \
  	do { \
  		update_range__(match, offsetof(struct sw_flow_key, field),  \
  				     sizeof((match)->key->field), is_mask); \
  		if (is_mask) {						    \
  			if ((match)->mask)				    \
  				(match)->mask->key.field = value;	    \
  		} else {                                                    \
  			(match)->key->field = value;		            \
  		}                                                           \
  	} while (0)
  
  #define SW_FLOW_KEY_MEMCPY(match, field, value_p, len, is_mask) \
  	do { \
  		update_range__(match, offsetof(struct sw_flow_key, field),  \
  				len, is_mask);                              \
  		if (is_mask) {						    \
  			if ((match)->mask)				    \
  				memcpy(&(match)->mask->key.field, value_p, len);\
  		} else {                                                    \
  			memcpy(&(match)->key->field, value_p, len);         \
  		}                                                           \
  	} while (0)
5828cd9a6   Andy Zhou   openvswitch: opti...
103
104
105
106
  static u16 range_n_bytes(const struct sw_flow_key_range *range)
  {
  	return range->end - range->start;
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  void ovs_match_init(struct sw_flow_match *match,
  		    struct sw_flow_key *key,
  		    struct sw_flow_mask *mask)
  {
  	memset(match, 0, sizeof(*match));
  	match->key = key;
  	match->mask = mask;
  
  	memset(key, 0, sizeof(*key));
  
  	if (mask) {
  		memset(&mask->key, 0, sizeof(mask->key));
  		mask->range.start = mask->range.end = 0;
  	}
  }
  
  static bool ovs_match_validate(const struct sw_flow_match *match,
  		u64 key_attrs, u64 mask_attrs)
  {
  	u64 key_expected = 1 << OVS_KEY_ATTR_ETHERNET;
  	u64 mask_allowed = key_attrs;  /* At most allow all key attributes */
  
  	/* The following mask attributes allowed only if they
  	 * pass the validation tests. */
  	mask_allowed &= ~((1 << OVS_KEY_ATTR_IPV4)
  			| (1 << OVS_KEY_ATTR_IPV6)
  			| (1 << OVS_KEY_ATTR_TCP)
  			| (1 << OVS_KEY_ATTR_UDP)
a175a7233   Joe Stringer   openvswitch: Add ...
135
  			| (1 << OVS_KEY_ATTR_SCTP)
03f0d916a   Andy Zhou   openvswitch: Mega...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  			| (1 << OVS_KEY_ATTR_ICMP)
  			| (1 << OVS_KEY_ATTR_ICMPV6)
  			| (1 << OVS_KEY_ATTR_ARP)
  			| (1 << OVS_KEY_ATTR_ND));
  
  	/* Always allowed mask fields. */
  	mask_allowed |= ((1 << OVS_KEY_ATTR_TUNNEL)
  		       | (1 << OVS_KEY_ATTR_IN_PORT)
  		       | (1 << OVS_KEY_ATTR_ETHERTYPE));
  
  	/* Check key attributes. */
  	if (match->key->eth.type == htons(ETH_P_ARP)
  			|| match->key->eth.type == htons(ETH_P_RARP)) {
  		key_expected |= 1 << OVS_KEY_ATTR_ARP;
  		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
  			mask_allowed |= 1 << OVS_KEY_ATTR_ARP;
  	}
  
  	if (match->key->eth.type == htons(ETH_P_IP)) {
  		key_expected |= 1 << OVS_KEY_ATTR_IPV4;
  		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
  			mask_allowed |= 1 << OVS_KEY_ATTR_IPV4;
  
  		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {
  			if (match->key->ip.proto == IPPROTO_UDP) {
  				key_expected |= 1 << OVS_KEY_ATTR_UDP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
165
166
167
168
169
  			if (match->key->ip.proto == IPPROTO_SCTP) {
  				key_expected |= 1 << OVS_KEY_ATTR_SCTP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;
  			}
03f0d916a   Andy Zhou   openvswitch: Mega...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  			if (match->key->ip.proto == IPPROTO_TCP) {
  				key_expected |= 1 << OVS_KEY_ATTR_TCP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;
  			}
  
  			if (match->key->ip.proto == IPPROTO_ICMP) {
  				key_expected |= 1 << OVS_KEY_ATTR_ICMP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_ICMP;
  			}
  		}
  	}
  
  	if (match->key->eth.type == htons(ETH_P_IPV6)) {
  		key_expected |= 1 << OVS_KEY_ATTR_IPV6;
  		if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
  			mask_allowed |= 1 << OVS_KEY_ATTR_IPV6;
  
  		if (match->key->ip.frag != OVS_FRAG_TYPE_LATER) {
  			if (match->key->ip.proto == IPPROTO_UDP) {
  				key_expected |= 1 << OVS_KEY_ATTR_UDP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_UDP;
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
195
196
197
198
199
  			if (match->key->ip.proto == IPPROTO_SCTP) {
  				key_expected |= 1 << OVS_KEY_ATTR_SCTP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_SCTP;
  			}
03f0d916a   Andy Zhou   openvswitch: Mega...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  			if (match->key->ip.proto == IPPROTO_TCP) {
  				key_expected |= 1 << OVS_KEY_ATTR_TCP;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_TCP;
  			}
  
  			if (match->key->ip.proto == IPPROTO_ICMPV6) {
  				key_expected |= 1 << OVS_KEY_ATTR_ICMPV6;
  				if (match->mask && (match->mask->key.ip.proto == 0xff))
  					mask_allowed |= 1 << OVS_KEY_ATTR_ICMPV6;
  
  				if (match->key->ipv6.tp.src ==
  						htons(NDISC_NEIGHBOUR_SOLICITATION) ||
  				    match->key->ipv6.tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
  					key_expected |= 1 << OVS_KEY_ATTR_ND;
  					if (match->mask && (match->mask->key.ipv6.tp.src == htons(0xffff)))
  						mask_allowed |= 1 << OVS_KEY_ATTR_ND;
  				}
  			}
  		}
  	}
  
  	if ((key_attrs & key_expected) != key_expected) {
  		/* Key attributes check failed. */
  		OVS_NLERR("Missing expected key attributes (key_attrs=%llx, expected=%llx).
  ",
  				key_attrs, key_expected);
  		return false;
  	}
  
  	if ((mask_attrs & mask_allowed) != mask_attrs) {
  		/* Mask attributes check failed. */
  		OVS_NLERR("Contain more than allowed mask fields (mask_attrs=%llx, mask_allowed=%llx).
  ",
  				mask_attrs, mask_allowed);
  		return false;
  	}
  
  	return true;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  static int check_header(struct sk_buff *skb, int len)
  {
  	if (unlikely(skb->len < len))
  		return -EINVAL;
  	if (unlikely(!pskb_may_pull(skb, len)))
  		return -ENOMEM;
  	return 0;
  }
  
  static bool arphdr_ok(struct sk_buff *skb)
  {
  	return pskb_may_pull(skb, skb_network_offset(skb) +
  				  sizeof(struct arp_eth_header));
  }
  
  static int check_iphdr(struct sk_buff *skb)
  {
  	unsigned int nh_ofs = skb_network_offset(skb);
  	unsigned int ip_len;
  	int err;
  
  	err = check_header(skb, nh_ofs + sizeof(struct iphdr));
  	if (unlikely(err))
  		return err;
  
  	ip_len = ip_hdrlen(skb);
  	if (unlikely(ip_len < sizeof(struct iphdr) ||
  		     skb->len < nh_ofs + ip_len))
  		return -EINVAL;
  
  	skb_set_transport_header(skb, nh_ofs + ip_len);
  	return 0;
  }
  
  static bool tcphdr_ok(struct sk_buff *skb)
  {
  	int th_ofs = skb_transport_offset(skb);
  	int tcp_len;
  
  	if (unlikely(!pskb_may_pull(skb, th_ofs + sizeof(struct tcphdr))))
  		return false;
  
  	tcp_len = tcp_hdrlen(skb);
  	if (unlikely(tcp_len < sizeof(struct tcphdr) ||
  		     skb->len < th_ofs + tcp_len))
  		return false;
  
  	return true;
  }
  
  static bool udphdr_ok(struct sk_buff *skb)
  {
  	return pskb_may_pull(skb, skb_transport_offset(skb) +
  				  sizeof(struct udphdr));
  }
a175a7233   Joe Stringer   openvswitch: Add ...
295
296
297
298
299
  static bool sctphdr_ok(struct sk_buff *skb)
  {
  	return pskb_may_pull(skb, skb_transport_offset(skb) +
  				  sizeof(struct sctphdr));
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  static bool icmphdr_ok(struct sk_buff *skb)
  {
  	return pskb_may_pull(skb, skb_transport_offset(skb) +
  				  sizeof(struct icmphdr));
  }
  
  u64 ovs_flow_used_time(unsigned long flow_jiffies)
  {
  	struct timespec cur_ts;
  	u64 cur_ms, idle_ms;
  
  	ktime_get_ts(&cur_ts);
  	idle_ms = jiffies_to_msecs(jiffies - flow_jiffies);
  	cur_ms = (u64)cur_ts.tv_sec * MSEC_PER_SEC +
  		 cur_ts.tv_nsec / NSEC_PER_MSEC;
  
  	return cur_ms - idle_ms;
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
318
  static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
319
320
321
322
323
324
325
326
  {
  	unsigned int nh_ofs = skb_network_offset(skb);
  	unsigned int nh_len;
  	int payload_ofs;
  	struct ipv6hdr *nh;
  	uint8_t nexthdr;
  	__be16 frag_off;
  	int err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
  	err = check_header(skb, nh_ofs + sizeof(*nh));
  	if (unlikely(err))
  		return err;
  
  	nh = ipv6_hdr(skb);
  	nexthdr = nh->nexthdr;
  	payload_ofs = (u8 *)(nh + 1) - skb->data;
  
  	key->ip.proto = NEXTHDR_NONE;
  	key->ip.tos = ipv6_get_dsfield(nh);
  	key->ip.ttl = nh->hop_limit;
  	key->ipv6.label = *(__be32 *)nh & htonl(IPV6_FLOWINFO_FLOWLABEL);
  	key->ipv6.addr.src = nh->saddr;
  	key->ipv6.addr.dst = nh->daddr;
  
  	payload_ofs = ipv6_skip_exthdr(skb, payload_ofs, &nexthdr, &frag_off);
  	if (unlikely(payload_ofs < 0))
  		return -EINVAL;
  
  	if (frag_off) {
  		if (frag_off & htons(~0x7))
  			key->ip.frag = OVS_FRAG_TYPE_LATER;
  		else
  			key->ip.frag = OVS_FRAG_TYPE_FIRST;
  	}
  
  	nh_len = payload_ofs - nh_ofs;
  	skb_set_transport_header(skb, nh_ofs + nh_len);
  	key->ip.proto = nexthdr;
  	return nh_len;
  }
  
  static bool icmp6hdr_ok(struct sk_buff *skb)
  {
  	return pskb_may_pull(skb, skb_transport_offset(skb) +
  				  sizeof(struct icmp6hdr));
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
364
365
366
  void ovs_flow_key_mask(struct sw_flow_key *dst, const struct sw_flow_key *src,
  		       const struct sw_flow_mask *mask)
  {
5828cd9a6   Andy Zhou   openvswitch: opti...
367
368
369
  	const long *m = (long *)((u8 *)&mask->key + mask->range.start);
  	const long *s = (long *)((u8 *)src + mask->range.start);
  	long *d = (long *)((u8 *)dst + mask->range.start);
03f0d916a   Andy Zhou   openvswitch: Mega...
370
  	int i;
5828cd9a6   Andy Zhou   openvswitch: opti...
371
372
373
374
375
376
  	/* The memory outside of the 'mask->range' are not set since
  	 * further operations on 'dst' only uses contents within
  	 * 'mask->range'.
  	 */
  	for (i = 0; i < range_n_bytes(&mask->range); i += sizeof(long))
  		*d++ = *s++ & *m++;
03f0d916a   Andy Zhou   openvswitch: Mega...
377
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
378
379
380
381
382
383
  #define TCP_FLAGS_OFFSET 13
  #define TCP_FLAG_MASK 0x3f
  
  void ovs_flow_used(struct sw_flow *flow, struct sk_buff *skb)
  {
  	u8 tcp_flags = 0;
c55177e3e   Jesse Gross   openvswitch: Enab...
384
385
  	if ((flow->key.eth.type == htons(ETH_P_IP) ||
  	     flow->key.eth.type == htons(ETH_P_IPV6)) &&
bf32fecdc   Jesse Gross   openvswitch: Add ...
386
387
  	    flow->key.ip.proto == IPPROTO_TCP &&
  	    likely(skb->len >= skb_transport_offset(skb) + sizeof(struct tcphdr))) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
388
389
390
391
392
393
394
395
396
397
398
  		u8 *tcp = (u8 *)tcp_hdr(skb);
  		tcp_flags = *(tcp + TCP_FLAGS_OFFSET) & TCP_FLAG_MASK;
  	}
  
  	spin_lock(&flow->lock);
  	flow->used = jiffies;
  	flow->packet_count++;
  	flow->byte_count += skb->len;
  	flow->tcp_flags |= tcp_flags;
  	spin_unlock(&flow->lock);
  }
74f84a572   Pravin B Shelar   openvswitch: Copy...
399
  struct sw_flow_actions *ovs_flow_actions_alloc(int size)
ccb1352e7   Jesse Gross   net: Add Open vSw...
400
  {
ccb1352e7   Jesse Gross   net: Add Open vSw...
401
  	struct sw_flow_actions *sfa;
74f84a572   Pravin B Shelar   openvswitch: Copy...
402
  	if (size > MAX_ACTIONS_BUFSIZE)
ccb1352e7   Jesse Gross   net: Add Open vSw...
403
  		return ERR_PTR(-EINVAL);
74f84a572   Pravin B Shelar   openvswitch: Copy...
404
  	sfa = kmalloc(sizeof(*sfa) + size, GFP_KERNEL);
ccb1352e7   Jesse Gross   net: Add Open vSw...
405
406
  	if (!sfa)
  		return ERR_PTR(-ENOMEM);
74f84a572   Pravin B Shelar   openvswitch: Copy...
407
  	sfa->actions_len = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
408
409
410
411
412
413
414
415
416
417
418
419
420
  	return sfa;
  }
  
  struct sw_flow *ovs_flow_alloc(void)
  {
  	struct sw_flow *flow;
  
  	flow = kmem_cache_alloc(flow_cache, GFP_KERNEL);
  	if (!flow)
  		return ERR_PTR(-ENOMEM);
  
  	spin_lock_init(&flow->lock);
  	flow->sf_acts = NULL;
03f0d916a   Andy Zhou   openvswitch: Mega...
421
  	flow->mask = NULL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
  
  	return flow;
  }
  
  static struct hlist_head *find_bucket(struct flow_table *table, u32 hash)
  {
  	hash = jhash_1word(hash, table->hash_seed);
  	return flex_array_get(table->buckets,
  				(hash & (table->n_buckets - 1)));
  }
  
  static struct flex_array *alloc_buckets(unsigned int n_buckets)
  {
  	struct flex_array *buckets;
  	int i, err;
42415c90c   Pravin B Shelar   openvswitch: Use ...
437
  	buckets = flex_array_alloc(sizeof(struct hlist_head),
ccb1352e7   Jesse Gross   net: Add Open vSw...
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
  				   n_buckets, GFP_KERNEL);
  	if (!buckets)
  		return NULL;
  
  	err = flex_array_prealloc(buckets, 0, n_buckets, GFP_KERNEL);
  	if (err) {
  		flex_array_free(buckets);
  		return NULL;
  	}
  
  	for (i = 0; i < n_buckets; i++)
  		INIT_HLIST_HEAD((struct hlist_head *)
  					flex_array_get(buckets, i));
  
  	return buckets;
  }
  
  static void free_buckets(struct flex_array *buckets)
  {
  	flex_array_free(buckets);
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
459
  static struct flow_table *__flow_tbl_alloc(int new_size)
ccb1352e7   Jesse Gross   net: Add Open vSw...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
  {
  	struct flow_table *table = kmalloc(sizeof(*table), GFP_KERNEL);
  
  	if (!table)
  		return NULL;
  
  	table->buckets = alloc_buckets(new_size);
  
  	if (!table->buckets) {
  		kfree(table);
  		return NULL;
  	}
  	table->n_buckets = new_size;
  	table->count = 0;
  	table->node_ver = 0;
  	table->keep_flows = false;
  	get_random_bytes(&table->hash_seed, sizeof(u32));
03f0d916a   Andy Zhou   openvswitch: Mega...
477
  	table->mask_list = NULL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
478
479
480
  
  	return table;
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
481
  static void __flow_tbl_destroy(struct flow_table *table)
ccb1352e7   Jesse Gross   net: Add Open vSw...
482
483
  {
  	int i;
ccb1352e7   Jesse Gross   net: Add Open vSw...
484
485
486
487
488
489
  	if (table->keep_flows)
  		goto skip_flows;
  
  	for (i = 0; i < table->n_buckets; i++) {
  		struct sw_flow *flow;
  		struct hlist_head *head = flex_array_get(table->buckets, i);
b67bfe0d4   Sasha Levin   hlist: drop the n...
490
  		struct hlist_node *n;
ccb1352e7   Jesse Gross   net: Add Open vSw...
491
  		int ver = table->node_ver;
b67bfe0d4   Sasha Levin   hlist: drop the n...
492
  		hlist_for_each_entry_safe(flow, n, head, hash_node[ver]) {
76a66c7e7   Pravin B Shelar   openvswitch: Use ...
493
  			hlist_del(&flow->hash_node[ver]);
03f0d916a   Andy Zhou   openvswitch: Mega...
494
  			ovs_flow_free(flow, false);
ccb1352e7   Jesse Gross   net: Add Open vSw...
495
496
  		}
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
497
498
  	BUG_ON(!list_empty(table->mask_list));
  	kfree(table->mask_list);
ccb1352e7   Jesse Gross   net: Add Open vSw...
499
500
501
502
  skip_flows:
  	free_buckets(table->buckets);
  	kfree(table);
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
  struct flow_table *ovs_flow_tbl_alloc(int new_size)
  {
  	struct flow_table *table = __flow_tbl_alloc(new_size);
  
  	if (!table)
  		return NULL;
  
  	table->mask_list = kmalloc(sizeof(struct list_head), GFP_KERNEL);
  	if (!table->mask_list) {
  		table->keep_flows = true;
  		__flow_tbl_destroy(table);
  		return NULL;
  	}
  	INIT_LIST_HEAD(table->mask_list);
  
  	return table;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
520
521
522
  static void flow_tbl_destroy_rcu_cb(struct rcu_head *rcu)
  {
  	struct flow_table *table = container_of(rcu, struct flow_table, rcu);
03f0d916a   Andy Zhou   openvswitch: Mega...
523
  	__flow_tbl_destroy(table);
ccb1352e7   Jesse Gross   net: Add Open vSw...
524
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
525
  void ovs_flow_tbl_destroy(struct flow_table *table, bool deferred)
ccb1352e7   Jesse Gross   net: Add Open vSw...
526
527
528
  {
  	if (!table)
  		return;
03f0d916a   Andy Zhou   openvswitch: Mega...
529
530
531
532
  	if (deferred)
  		call_rcu(&table->rcu, flow_tbl_destroy_rcu_cb);
  	else
  		__flow_tbl_destroy(table);
ccb1352e7   Jesse Gross   net: Add Open vSw...
533
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
534
  struct sw_flow *ovs_flow_dump_next(struct flow_table *table, u32 *bucket, u32 *last)
ccb1352e7   Jesse Gross   net: Add Open vSw...
535
536
537
  {
  	struct sw_flow *flow;
  	struct hlist_head *head;
ccb1352e7   Jesse Gross   net: Add Open vSw...
538
539
540
541
542
543
544
  	int ver;
  	int i;
  
  	ver = table->node_ver;
  	while (*bucket < table->n_buckets) {
  		i = 0;
  		head = flex_array_get(table->buckets, *bucket);
b67bfe0d4   Sasha Levin   hlist: drop the n...
545
  		hlist_for_each_entry_rcu(flow, head, hash_node[ver]) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
546
547
548
549
550
551
552
553
554
555
556
557
558
  			if (i < *last) {
  				i++;
  				continue;
  			}
  			*last = i + 1;
  			return flow;
  		}
  		(*bucket)++;
  		*last = 0;
  	}
  
  	return NULL;
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
559
  static void __tbl_insert(struct flow_table *table, struct sw_flow *flow)
a3e82996a   Pravin B Shelar   openvswitch: Opti...
560
561
  {
  	struct hlist_head *head;
03f0d916a   Andy Zhou   openvswitch: Mega...
562

a3e82996a   Pravin B Shelar   openvswitch: Opti...
563
564
  	head = find_bucket(table, flow->hash);
  	hlist_add_head_rcu(&flow->hash_node[table->node_ver], head);
03f0d916a   Andy Zhou   openvswitch: Mega...
565

a3e82996a   Pravin B Shelar   openvswitch: Opti...
566
567
  	table->count++;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
568
569
570
571
572
573
574
575
576
577
578
579
  static void flow_table_copy_flows(struct flow_table *old, struct flow_table *new)
  {
  	int old_ver;
  	int i;
  
  	old_ver = old->node_ver;
  	new->node_ver = !old_ver;
  
  	/* Insert in new table. */
  	for (i = 0; i < old->n_buckets; i++) {
  		struct sw_flow *flow;
  		struct hlist_head *head;
ccb1352e7   Jesse Gross   net: Add Open vSw...
580
581
  
  		head = flex_array_get(old->buckets, i);
b67bfe0d4   Sasha Levin   hlist: drop the n...
582
  		hlist_for_each_entry(flow, head, hash_node[old_ver])
03f0d916a   Andy Zhou   openvswitch: Mega...
583
  			__tbl_insert(new, flow);
ccb1352e7   Jesse Gross   net: Add Open vSw...
584
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
585
586
  
  	new->mask_list = old->mask_list;
ccb1352e7   Jesse Gross   net: Add Open vSw...
587
588
589
590
591
592
  	old->keep_flows = true;
  }
  
  static struct flow_table *__flow_tbl_rehash(struct flow_table *table, int n_buckets)
  {
  	struct flow_table *new_table;
03f0d916a   Andy Zhou   openvswitch: Mega...
593
  	new_table = __flow_tbl_alloc(n_buckets);
ccb1352e7   Jesse Gross   net: Add Open vSw...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  	if (!new_table)
  		return ERR_PTR(-ENOMEM);
  
  	flow_table_copy_flows(table, new_table);
  
  	return new_table;
  }
  
  struct flow_table *ovs_flow_tbl_rehash(struct flow_table *table)
  {
  	return __flow_tbl_rehash(table, table->n_buckets);
  }
  
  struct flow_table *ovs_flow_tbl_expand(struct flow_table *table)
  {
  	return __flow_tbl_rehash(table, table->n_buckets * 2);
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
611
  static void __flow_free(struct sw_flow *flow)
ccb1352e7   Jesse Gross   net: Add Open vSw...
612
  {
ccb1352e7   Jesse Gross   net: Add Open vSw...
613
614
615
  	kfree((struct sf_flow_acts __force *)flow->sf_acts);
  	kmem_cache_free(flow_cache, flow);
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
616
617
618
  static void rcu_free_flow_callback(struct rcu_head *rcu)
  {
  	struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu);
03f0d916a   Andy Zhou   openvswitch: Mega...
619
  	__flow_free(flow);
ccb1352e7   Jesse Gross   net: Add Open vSw...
620
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
621
  void ovs_flow_free(struct sw_flow *flow, bool deferred)
ccb1352e7   Jesse Gross   net: Add Open vSw...
622
  {
03f0d916a   Andy Zhou   openvswitch: Mega...
623
624
625
626
627
628
629
630
631
  	if (!flow)
  		return;
  
  	ovs_sw_flow_mask_del_ref(flow->mask, deferred);
  
  	if (deferred)
  		call_rcu(&flow->rcu, rcu_free_flow_callback);
  	else
  		__flow_free(flow);
ccb1352e7   Jesse Gross   net: Add Open vSw...
632
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
633
634
635
636
  /* Schedules 'sf_acts' to be freed after the next RCU grace period.
   * The caller must hold rcu_read_lock for this to be sensible. */
  void ovs_flow_deferred_free_acts(struct sw_flow_actions *sf_acts)
  {
80f0fd8a7   Wei Yongjun   openvswitch: usin...
637
  	kfree_rcu(sf_acts, rcu);
ccb1352e7   Jesse Gross   net: Add Open vSw...
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
  }
  
  static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
  {
  	struct qtag_prefix {
  		__be16 eth_type; /* ETH_P_8021Q */
  		__be16 tci;
  	};
  	struct qtag_prefix *qp;
  
  	if (unlikely(skb->len < sizeof(struct qtag_prefix) + sizeof(__be16)))
  		return 0;
  
  	if (unlikely(!pskb_may_pull(skb, sizeof(struct qtag_prefix) +
  					 sizeof(__be16))))
  		return -ENOMEM;
  
  	qp = (struct qtag_prefix *) skb->data;
  	key->eth.tci = qp->tci | htons(VLAN_TAG_PRESENT);
  	__skb_pull(skb, sizeof(struct qtag_prefix));
  
  	return 0;
  }
  
  static __be16 parse_ethertype(struct sk_buff *skb)
  {
  	struct llc_snap_hdr {
  		u8  dsap;  /* Always 0xAA */
  		u8  ssap;  /* Always 0xAA */
  		u8  ctrl;
  		u8  oui[3];
  		__be16 ethertype;
  	};
  	struct llc_snap_hdr *llc;
  	__be16 proto;
  
  	proto = *(__be16 *) skb->data;
  	__skb_pull(skb, sizeof(__be16));
e5c5d22e8   Simon Horman   net: add ETH_P_80...
676
  	if (ntohs(proto) >= ETH_P_802_3_MIN)
ccb1352e7   Jesse Gross   net: Add Open vSw...
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  		return proto;
  
  	if (skb->len < sizeof(struct llc_snap_hdr))
  		return htons(ETH_P_802_2);
  
  	if (unlikely(!pskb_may_pull(skb, sizeof(struct llc_snap_hdr))))
  		return htons(0);
  
  	llc = (struct llc_snap_hdr *) skb->data;
  	if (llc->dsap != LLC_SAP_SNAP ||
  	    llc->ssap != LLC_SAP_SNAP ||
  	    (llc->oui[0] | llc->oui[1] | llc->oui[2]) != 0)
  		return htons(ETH_P_802_2);
  
  	__skb_pull(skb, sizeof(struct llc_snap_hdr));
17b682a04   Rich Lane   openvswitch: Fix ...
692

e5c5d22e8   Simon Horman   net: add ETH_P_80...
693
  	if (ntohs(llc->ethertype) >= ETH_P_802_3_MIN)
17b682a04   Rich Lane   openvswitch: Fix ...
694
695
696
  		return llc->ethertype;
  
  	return htons(ETH_P_802_2);
ccb1352e7   Jesse Gross   net: Add Open vSw...
697
698
699
  }
  
  static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
03f0d916a   Andy Zhou   openvswitch: Mega...
700
  			int nh_len)
ccb1352e7   Jesse Gross   net: Add Open vSw...
701
702
  {
  	struct icmp6hdr *icmp = icmp6_hdr(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
703
704
705
706
707
708
  
  	/* The ICMPv6 type and code fields use the 16-bit transport port
  	 * fields, so we need to store them in 16-bit network byte order.
  	 */
  	key->ipv6.tp.src = htons(icmp->icmp6_type);
  	key->ipv6.tp.dst = htons(icmp->icmp6_code);
ccb1352e7   Jesse Gross   net: Add Open vSw...
709
710
711
712
713
714
715
  
  	if (icmp->icmp6_code == 0 &&
  	    (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION ||
  	     icmp->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT)) {
  		int icmp_len = skb->len - skb_transport_offset(skb);
  		struct nd_msg *nd;
  		int offset;
ccb1352e7   Jesse Gross   net: Add Open vSw...
716
717
718
719
  		/* In order to process neighbor discovery options, we need the
  		 * entire packet.
  		 */
  		if (unlikely(icmp_len < sizeof(*nd)))
03f0d916a   Andy Zhou   openvswitch: Mega...
720
721
722
723
  			return 0;
  
  		if (unlikely(skb_linearize(skb)))
  			return -ENOMEM;
ccb1352e7   Jesse Gross   net: Add Open vSw...
724
725
726
  
  		nd = (struct nd_msg *)skb_transport_header(skb);
  		key->ipv6.nd.target = nd->target;
ccb1352e7   Jesse Gross   net: Add Open vSw...
727
728
729
730
731
732
733
734
735
  
  		icmp_len -= sizeof(*nd);
  		offset = 0;
  		while (icmp_len >= 8) {
  			struct nd_opt_hdr *nd_opt =
  				 (struct nd_opt_hdr *)(nd->opt + offset);
  			int opt_len = nd_opt->nd_opt_len * 8;
  
  			if (unlikely(!opt_len || opt_len > icmp_len))
03f0d916a   Andy Zhou   openvswitch: Mega...
736
  				return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
  
  			/* Store the link layer address if the appropriate
  			 * option is provided.  It is considered an error if
  			 * the same link layer option is specified twice.
  			 */
  			if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LL_ADDR
  			    && opt_len == 8) {
  				if (unlikely(!is_zero_ether_addr(key->ipv6.nd.sll)))
  					goto invalid;
  				memcpy(key->ipv6.nd.sll,
  				    &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
  			} else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LL_ADDR
  				   && opt_len == 8) {
  				if (unlikely(!is_zero_ether_addr(key->ipv6.nd.tll)))
  					goto invalid;
  				memcpy(key->ipv6.nd.tll,
  				    &nd->opt[offset+sizeof(*nd_opt)], ETH_ALEN);
  			}
  
  			icmp_len -= opt_len;
  			offset += opt_len;
  		}
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
760
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
761
762
763
764
765
  
  invalid:
  	memset(&key->ipv6.nd.target, 0, sizeof(key->ipv6.nd.target));
  	memset(key->ipv6.nd.sll, 0, sizeof(key->ipv6.nd.sll));
  	memset(key->ipv6.nd.tll, 0, sizeof(key->ipv6.nd.tll));
03f0d916a   Andy Zhou   openvswitch: Mega...
766
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
767
768
769
770
771
772
773
774
  }
  
  /**
   * ovs_flow_extract - extracts a flow key from an Ethernet frame.
   * @skb: sk_buff that contains the frame, with skb->data pointing to the
   * Ethernet header
   * @in_port: port number on which @skb was received.
   * @key: output flow key
ccb1352e7   Jesse Gross   net: Add Open vSw...
775
776
777
778
779
780
781
782
783
784
785
786
   *
   * The caller must ensure that skb->len >= ETH_HLEN.
   *
   * Returns 0 if successful, otherwise a negative errno value.
   *
   * Initializes @skb header pointers as follows:
   *
   *    - skb->mac_header: the Ethernet header.
   *
   *    - skb->network_header: just past the Ethernet header, or just past the
   *      VLAN header, to the first byte of the Ethernet payload.
   *
34d94f210   Lorand Jakab   openvswitch: fix ...
787
   *    - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
ccb1352e7   Jesse Gross   net: Add Open vSw...
788
789
   *      on output, then just past the IP header, if one is present and
   *      of a correct length, otherwise the same as skb->network_header.
34d94f210   Lorand Jakab   openvswitch: fix ...
790
   *      For other key->eth.type values it is left untouched.
ccb1352e7   Jesse Gross   net: Add Open vSw...
791
   */
03f0d916a   Andy Zhou   openvswitch: Mega...
792
  int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
793
  {
03f0d916a   Andy Zhou   openvswitch: Mega...
794
  	int error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
795
796
797
798
799
  	struct ethhdr *eth;
  
  	memset(key, 0, sizeof(*key));
  
  	key->phy.priority = skb->priority;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
800
801
  	if (OVS_CB(skb)->tun_key)
  		memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
ccb1352e7   Jesse Gross   net: Add Open vSw...
802
  	key->phy.in_port = in_port;
39c7caebc   Ansis Atteka   openvswitch: add ...
803
  	key->phy.skb_mark = skb->mark;
ccb1352e7   Jesse Gross   net: Add Open vSw...
804
805
806
807
808
809
810
811
812
813
814
  
  	skb_reset_mac_header(skb);
  
  	/* Link layer.  We are guaranteed to have at least the 14 byte Ethernet
  	 * header in the linear data area.
  	 */
  	eth = eth_hdr(skb);
  	memcpy(key->eth.src, eth->h_source, ETH_ALEN);
  	memcpy(key->eth.dst, eth->h_dest, ETH_ALEN);
  
  	__skb_pull(skb, 2 * ETH_ALEN);
b34df5e80   Pravin B Shelar   openvswitch: make...
815
816
817
  	/* We are going to push all headers that we pull, so no need to
  	 * update skb->csum here.
  	 */
ccb1352e7   Jesse Gross   net: Add Open vSw...
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
  
  	if (vlan_tx_tag_present(skb))
  		key->eth.tci = htons(skb->vlan_tci);
  	else if (eth->h_proto == htons(ETH_P_8021Q))
  		if (unlikely(parse_vlan(skb, key)))
  			return -ENOMEM;
  
  	key->eth.type = parse_ethertype(skb);
  	if (unlikely(key->eth.type == htons(0)))
  		return -ENOMEM;
  
  	skb_reset_network_header(skb);
  	__skb_push(skb, skb->data - skb_mac_header(skb));
  
  	/* Network layer. */
  	if (key->eth.type == htons(ETH_P_IP)) {
  		struct iphdr *nh;
  		__be16 offset;
ccb1352e7   Jesse Gross   net: Add Open vSw...
836
837
838
839
840
841
  		error = check_iphdr(skb);
  		if (unlikely(error)) {
  			if (error == -EINVAL) {
  				skb->transport_header = skb->network_header;
  				error = 0;
  			}
03f0d916a   Andy Zhou   openvswitch: Mega...
842
  			return error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
843
844
845
846
847
848
849
850
851
852
853
854
855
  		}
  
  		nh = ip_hdr(skb);
  		key->ipv4.addr.src = nh->saddr;
  		key->ipv4.addr.dst = nh->daddr;
  
  		key->ip.proto = nh->protocol;
  		key->ip.tos = nh->tos;
  		key->ip.ttl = nh->ttl;
  
  		offset = nh->frag_off & htons(IP_OFFSET);
  		if (offset) {
  			key->ip.frag = OVS_FRAG_TYPE_LATER;
03f0d916a   Andy Zhou   openvswitch: Mega...
856
  			return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
857
858
859
860
861
862
863
  		}
  		if (nh->frag_off & htons(IP_MF) ||
  			 skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
  			key->ip.frag = OVS_FRAG_TYPE_FIRST;
  
  		/* Transport layer. */
  		if (key->ip.proto == IPPROTO_TCP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
864
865
866
867
868
869
  			if (tcphdr_ok(skb)) {
  				struct tcphdr *tcp = tcp_hdr(skb);
  				key->ipv4.tp.src = tcp->source;
  				key->ipv4.tp.dst = tcp->dest;
  			}
  		} else if (key->ip.proto == IPPROTO_UDP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
870
871
872
873
874
  			if (udphdr_ok(skb)) {
  				struct udphdr *udp = udp_hdr(skb);
  				key->ipv4.tp.src = udp->source;
  				key->ipv4.tp.dst = udp->dest;
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
875
876
877
878
879
880
  		} else if (key->ip.proto == IPPROTO_SCTP) {
  			if (sctphdr_ok(skb)) {
  				struct sctphdr *sctp = sctp_hdr(skb);
  				key->ipv4.tp.src = sctp->source;
  				key->ipv4.tp.dst = sctp->dest;
  			}
ccb1352e7   Jesse Gross   net: Add Open vSw...
881
  		} else if (key->ip.proto == IPPROTO_ICMP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
882
883
884
885
886
887
888
889
890
  			if (icmphdr_ok(skb)) {
  				struct icmphdr *icmp = icmp_hdr(skb);
  				/* The ICMP type and code fields use the 16-bit
  				 * transport port fields, so we need to store
  				 * them in 16-bit network byte order. */
  				key->ipv4.tp.src = htons(icmp->type);
  				key->ipv4.tp.dst = htons(icmp->code);
  			}
  		}
c06185338   Mehak Mahajan   openvswitch: Proc...
891
892
  	} else if ((key->eth.type == htons(ETH_P_ARP) ||
  		   key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
893
894
895
896
897
898
899
900
901
902
903
904
  		struct arp_eth_header *arp;
  
  		arp = (struct arp_eth_header *)skb_network_header(skb);
  
  		if (arp->ar_hrd == htons(ARPHRD_ETHER)
  				&& arp->ar_pro == htons(ETH_P_IP)
  				&& arp->ar_hln == ETH_ALEN
  				&& arp->ar_pln == 4) {
  
  			/* We only match on the lower 8 bits of the opcode. */
  			if (ntohs(arp->ar_op) <= 0xff)
  				key->ip.proto = ntohs(arp->ar_op);
d04d38298   Mehak Mahajan   openvswitch: Stor...
905
906
907
908
  			memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
  			memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
  			memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
  			memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
ccb1352e7   Jesse Gross   net: Add Open vSw...
909
910
911
  		}
  	} else if (key->eth.type == htons(ETH_P_IPV6)) {
  		int nh_len;             /* IPv6 Header + Extensions */
03f0d916a   Andy Zhou   openvswitch: Mega...
912
  		nh_len = parse_ipv6hdr(skb, key);
ccb1352e7   Jesse Gross   net: Add Open vSw...
913
  		if (unlikely(nh_len < 0)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
914
  			if (nh_len == -EINVAL) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
915
  				skb->transport_header = skb->network_header;
03f0d916a   Andy Zhou   openvswitch: Mega...
916
917
  				error = 0;
  			} else {
ccb1352e7   Jesse Gross   net: Add Open vSw...
918
  				error = nh_len;
03f0d916a   Andy Zhou   openvswitch: Mega...
919
920
  			}
  			return error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
921
922
923
  		}
  
  		if (key->ip.frag == OVS_FRAG_TYPE_LATER)
03f0d916a   Andy Zhou   openvswitch: Mega...
924
  			return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
925
926
927
928
929
  		if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
  			key->ip.frag = OVS_FRAG_TYPE_FIRST;
  
  		/* Transport layer. */
  		if (key->ip.proto == NEXTHDR_TCP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
930
931
932
933
934
935
  			if (tcphdr_ok(skb)) {
  				struct tcphdr *tcp = tcp_hdr(skb);
  				key->ipv6.tp.src = tcp->source;
  				key->ipv6.tp.dst = tcp->dest;
  			}
  		} else if (key->ip.proto == NEXTHDR_UDP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
936
937
938
939
940
  			if (udphdr_ok(skb)) {
  				struct udphdr *udp = udp_hdr(skb);
  				key->ipv6.tp.src = udp->source;
  				key->ipv6.tp.dst = udp->dest;
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
941
942
943
944
945
946
  		} else if (key->ip.proto == NEXTHDR_SCTP) {
  			if (sctphdr_ok(skb)) {
  				struct sctphdr *sctp = sctp_hdr(skb);
  				key->ipv6.tp.src = sctp->source;
  				key->ipv6.tp.dst = sctp->dest;
  			}
ccb1352e7   Jesse Gross   net: Add Open vSw...
947
  		} else if (key->ip.proto == NEXTHDR_ICMP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
948
  			if (icmp6hdr_ok(skb)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
949
950
951
  				error = parse_icmpv6(skb, key, nh_len);
  				if (error)
  					return error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
952
953
954
  			}
  		}
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
955
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
956
  }
02237373b   Andy Zhou   openvswitch: Rena...
957
958
  static u32 ovs_flow_hash(const struct sw_flow_key *key, int key_start,
  			 int key_end)
a3e82996a   Pravin B Shelar   openvswitch: Opti...
959
  {
5828cd9a6   Andy Zhou   openvswitch: opti...
960
961
962
963
964
965
966
  	u32 *hash_key = (u32 *)((u8 *)key + key_start);
  	int hash_u32s = (key_end - key_start) >> 2;
  
  	/* Make sure number of hash bytes are multiple of u32. */
  	BUILD_BUG_ON(sizeof(long) % sizeof(u32));
  
  	return jhash2(hash_key, hash_u32s, 0);
a3e82996a   Pravin B Shelar   openvswitch: Opti...
967
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
968
  static int flow_key_start(const struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
969
  {
a3e82996a   Pravin B Shelar   openvswitch: Opti...
970
971
972
  	if (key->tun_key.ipv4_dst)
  		return 0;
  	else
5828cd9a6   Andy Zhou   openvswitch: opti...
973
974
  		return rounddown(offsetof(struct sw_flow_key, phy),
  					  sizeof(long));
ccb1352e7   Jesse Gross   net: Add Open vSw...
975
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
976
  static bool __cmp_key(const struct sw_flow_key *key1,
02237373b   Andy Zhou   openvswitch: Rena...
977
  		const struct sw_flow_key *key2,  int key_start, int key_end)
03f0d916a   Andy Zhou   openvswitch: Mega...
978
  {
5828cd9a6   Andy Zhou   openvswitch: opti...
979
980
981
982
983
984
985
986
987
  	const long *cp1 = (long *)((u8 *)key1 + key_start);
  	const long *cp2 = (long *)((u8 *)key2 + key_start);
  	long diffs = 0;
  	int i;
  
  	for (i = key_start; i < key_end;  i += sizeof(long))
  		diffs |= *cp1++ ^ *cp2++;
  
  	return diffs == 0;
03f0d916a   Andy Zhou   openvswitch: Mega...
988
  }
5828cd9a6   Andy Zhou   openvswitch: opti...
989
  static bool __flow_cmp_masked_key(const struct sw_flow *flow,
02237373b   Andy Zhou   openvswitch: Rena...
990
  		const struct sw_flow_key *key, int key_start, int key_end)
03f0d916a   Andy Zhou   openvswitch: Mega...
991
  {
02237373b   Andy Zhou   openvswitch: Rena...
992
  	return __cmp_key(&flow->key, key, key_start, key_end);
03f0d916a   Andy Zhou   openvswitch: Mega...
993
994
995
  }
  
  static bool __flow_cmp_unmasked_key(const struct sw_flow *flow,
02237373b   Andy Zhou   openvswitch: Rena...
996
  		  const struct sw_flow_key *key, int key_start, int key_end)
03f0d916a   Andy Zhou   openvswitch: Mega...
997
  {
02237373b   Andy Zhou   openvswitch: Rena...
998
  	return __cmp_key(&flow->unmasked_key, key, key_start, key_end);
03f0d916a   Andy Zhou   openvswitch: Mega...
999
1000
1001
  }
  
  bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
02237373b   Andy Zhou   openvswitch: Rena...
1002
  		const struct sw_flow_key *key, int key_end)
03f0d916a   Andy Zhou   openvswitch: Mega...
1003
1004
1005
  {
  	int key_start;
  	key_start = flow_key_start(key);
02237373b   Andy Zhou   openvswitch: Rena...
1006
  	return __flow_cmp_unmasked_key(flow, key, key_start, key_end);
03f0d916a   Andy Zhou   openvswitch: Mega...
1007
1008
1009
1010
1011
1012
1013
  
  }
  
  struct sw_flow *ovs_flow_lookup_unmasked_key(struct flow_table *table,
  				       struct sw_flow_match *match)
  {
  	struct sw_flow_key *unmasked = match->key;
02237373b   Andy Zhou   openvswitch: Rena...
1014
  	int key_end = match->range.end;
03f0d916a   Andy Zhou   openvswitch: Mega...
1015
1016
1017
  	struct sw_flow *flow;
  
  	flow = ovs_flow_lookup(table, unmasked);
02237373b   Andy Zhou   openvswitch: Rena...
1018
  	if (flow && (!ovs_flow_cmp_unmasked_key(flow, unmasked, key_end)))
03f0d916a   Andy Zhou   openvswitch: Mega...
1019
1020
1021
1022
1023
1024
  		flow = NULL;
  
  	return flow;
  }
  
  static struct sw_flow *ovs_masked_flow_lookup(struct flow_table *table,
5828cd9a6   Andy Zhou   openvswitch: opti...
1025
  				    const struct sw_flow_key *unmasked,
03f0d916a   Andy Zhou   openvswitch: Mega...
1026
  				    struct sw_flow_mask *mask)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1027
1028
  {
  	struct sw_flow *flow;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1029
  	struct hlist_head *head;
03f0d916a   Andy Zhou   openvswitch: Mega...
1030
  	int key_start = mask->range.start;
02237373b   Andy Zhou   openvswitch: Rena...
1031
  	int key_end = mask->range.end;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1032
  	u32 hash;
03f0d916a   Andy Zhou   openvswitch: Mega...
1033
  	struct sw_flow_key masked_key;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1034

5828cd9a6   Andy Zhou   openvswitch: opti...
1035
  	ovs_flow_key_mask(&masked_key, unmasked, mask);
02237373b   Andy Zhou   openvswitch: Rena...
1036
  	hash = ovs_flow_hash(&masked_key, key_start, key_end);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1037
  	head = find_bucket(table, hash);
b67bfe0d4   Sasha Levin   hlist: drop the n...
1038
  	hlist_for_each_entry_rcu(flow, head, hash_node[table->node_ver]) {
03f0d916a   Andy Zhou   openvswitch: Mega...
1039
  		if (flow->mask == mask &&
5828cd9a6   Andy Zhou   openvswitch: opti...
1040
1041
  		    __flow_cmp_masked_key(flow, &masked_key,
  					  key_start, key_end))
ccb1352e7   Jesse Gross   net: Add Open vSw...
1042
  			return flow;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1043
1044
1045
  	}
  	return NULL;
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
1046
1047
  struct sw_flow *ovs_flow_lookup(struct flow_table *tbl,
  				const struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1048
  {
03f0d916a   Andy Zhou   openvswitch: Mega...
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
  	struct sw_flow *flow = NULL;
  	struct sw_flow_mask *mask;
  
  	list_for_each_entry_rcu(mask, tbl->mask_list, list) {
  		flow = ovs_masked_flow_lookup(tbl, key, mask);
  		if (flow)  /* Found */
  			break;
  	}
  
  	return flow;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1059
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
1060
1061
1062
1063
1064
1065
1066
1067
1068
  
  void ovs_flow_insert(struct flow_table *table, struct sw_flow *flow)
  {
  	flow->hash = ovs_flow_hash(&flow->key, flow->mask->range.start,
  			flow->mask->range.end);
  	__tbl_insert(table, flow);
  }
  
  void ovs_flow_remove(struct flow_table *table, struct sw_flow *flow)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1069
  {
d3e1101c9   Hong Zhiguo   openvswitch: corr...
1070
  	BUG_ON(table->count == 0);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1071
1072
  	hlist_del_rcu(&flow->hash_node[table->node_ver]);
  	table->count--;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1073
1074
1075
1076
1077
1078
1079
  }
  
  /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */
  const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
  	[OVS_KEY_ATTR_ENCAP] = -1,
  	[OVS_KEY_ATTR_PRIORITY] = sizeof(u32),
  	[OVS_KEY_ATTR_IN_PORT] = sizeof(u32),
39c7caebc   Ansis Atteka   openvswitch: add ...
1080
  	[OVS_KEY_ATTR_SKB_MARK] = sizeof(u32),
ccb1352e7   Jesse Gross   net: Add Open vSw...
1081
1082
1083
1084
1085
1086
1087
  	[OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet),
  	[OVS_KEY_ATTR_VLAN] = sizeof(__be16),
  	[OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16),
  	[OVS_KEY_ATTR_IPV4] = sizeof(struct ovs_key_ipv4),
  	[OVS_KEY_ATTR_IPV6] = sizeof(struct ovs_key_ipv6),
  	[OVS_KEY_ATTR_TCP] = sizeof(struct ovs_key_tcp),
  	[OVS_KEY_ATTR_UDP] = sizeof(struct ovs_key_udp),
a175a7233   Joe Stringer   openvswitch: Add ...
1088
  	[OVS_KEY_ATTR_SCTP] = sizeof(struct ovs_key_sctp),
ccb1352e7   Jesse Gross   net: Add Open vSw...
1089
1090
1091
1092
  	[OVS_KEY_ATTR_ICMP] = sizeof(struct ovs_key_icmp),
  	[OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6),
  	[OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp),
  	[OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd),
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1093
  	[OVS_KEY_ATTR_TUNNEL] = -1,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1094
  };
03f0d916a   Andy Zhou   openvswitch: Mega...
1095
  static bool is_all_zero(const u8 *fp, size_t size)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1096
  {
03f0d916a   Andy Zhou   openvswitch: Mega...
1097
  	int i;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1098

03f0d916a   Andy Zhou   openvswitch: Mega...
1099
1100
  	if (!fp)
  		return false;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1101

03f0d916a   Andy Zhou   openvswitch: Mega...
1102
1103
1104
  	for (i = 0; i < size; i++)
  		if (fp[i])
  			return false;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1105

03f0d916a   Andy Zhou   openvswitch: Mega...
1106
  	return true;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1107
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
1108
1109
1110
  static int __parse_flow_nlattrs(const struct nlattr *attr,
  			      const struct nlattr *a[],
  			      u64 *attrsp, bool nz)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1111
1112
1113
1114
  {
  	const struct nlattr *nla;
  	u32 attrs;
  	int rem;
03f0d916a   Andy Zhou   openvswitch: Mega...
1115
  	attrs = *attrsp;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1116
1117
1118
  	nla_for_each_nested(nla, attr, rem) {
  		u16 type = nla_type(nla);
  		int expected_len;
03f0d916a   Andy Zhou   openvswitch: Mega...
1119
1120
1121
1122
  		if (type > OVS_KEY_ATTR_MAX) {
  			OVS_NLERR("Unknown key attribute (type=%d, max=%d).
  ",
  				  type, OVS_KEY_ATTR_MAX);
3bf4b5b11   Daniel Borkmann   net: ovs: flow: f...
1123
  			return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1124
1125
1126
1127
1128
  		}
  
  		if (attrs & (1 << type)) {
  			OVS_NLERR("Duplicate key attribute (type %d).
  ", type);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1129
  			return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1130
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1131
1132
  
  		expected_len = ovs_key_lens[type];
03f0d916a   Andy Zhou   openvswitch: Mega...
1133
1134
1135
1136
1137
  		if (nla_len(nla) != expected_len && expected_len != -1) {
  			OVS_NLERR("Key attribute has unexpected length (type=%d"
  				  ", length=%d, expected=%d).
  ", type,
  				  nla_len(nla), expected_len);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1138
  			return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1139
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1140

03f0d916a   Andy Zhou   openvswitch: Mega...
1141
1142
1143
1144
  		if (!nz || !is_all_zero(nla_data(nla), expected_len)) {
  			attrs |= 1 << type;
  			a[type] = nla;
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1145
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
1146
1147
1148
  	if (rem) {
  		OVS_NLERR("Message has %d unknown bytes.
  ", rem);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1149
  		return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1150
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1151
1152
1153
1154
  
  	*attrsp = attrs;
  	return 0;
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
  static int parse_flow_mask_nlattrs(const struct nlattr *attr,
  			      const struct nlattr *a[], u64 *attrsp)
  {
  	return __parse_flow_nlattrs(attr, a, attrsp, true);
  }
  
  static int parse_flow_nlattrs(const struct nlattr *attr,
  			      const struct nlattr *a[], u64 *attrsp)
  {
  	return __parse_flow_nlattrs(attr, a, attrsp, false);
  }
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1166
  int ovs_ipv4_tun_from_nlattr(const struct nlattr *attr,
03f0d916a   Andy Zhou   openvswitch: Mega...
1167
  			     struct sw_flow_match *match, bool is_mask)
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1168
1169
1170
1171
  {
  	struct nlattr *a;
  	int rem;
  	bool ttl = false;
03f0d916a   Andy Zhou   openvswitch: Mega...
1172
  	__be16 tun_flags = 0;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
  
  	nla_for_each_nested(a, attr, rem) {
  		int type = nla_type(a);
  		static const u32 ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
  			[OVS_TUNNEL_KEY_ATTR_ID] = sizeof(u64),
  			[OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = sizeof(u32),
  			[OVS_TUNNEL_KEY_ATTR_IPV4_DST] = sizeof(u32),
  			[OVS_TUNNEL_KEY_ATTR_TOS] = 1,
  			[OVS_TUNNEL_KEY_ATTR_TTL] = 1,
  			[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0,
  			[OVS_TUNNEL_KEY_ATTR_CSUM] = 0,
  		};
03f0d916a   Andy Zhou   openvswitch: Mega...
1185
1186
1187
1188
  		if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
  			OVS_NLERR("Unknown IPv4 tunnel attribute (type=%d, max=%d).
  ",
  			type, OVS_TUNNEL_KEY_ATTR_MAX);
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1189
  			return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1190
1191
1192
1193
1194
1195
1196
1197
1198
  		}
  
  		if (ovs_tunnel_key_lens[type] != nla_len(a)) {
  			OVS_NLERR("IPv4 tunnel attribute type has unexpected "
  				  " length (type=%d, length=%d, expected=%d).
  ",
  				  type, nla_len(a), ovs_tunnel_key_lens[type]);
  			return -EINVAL;
  		}
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1199
1200
1201
  
  		switch (type) {
  		case OVS_TUNNEL_KEY_ATTR_ID:
03f0d916a   Andy Zhou   openvswitch: Mega...
1202
1203
1204
  			SW_FLOW_KEY_PUT(match, tun_key.tun_id,
  					nla_get_be64(a), is_mask);
  			tun_flags |= TUNNEL_KEY;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1205
1206
  			break;
  		case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
03f0d916a   Andy Zhou   openvswitch: Mega...
1207
1208
  			SW_FLOW_KEY_PUT(match, tun_key.ipv4_src,
  					nla_get_be32(a), is_mask);
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1209
1210
  			break;
  		case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
03f0d916a   Andy Zhou   openvswitch: Mega...
1211
1212
  			SW_FLOW_KEY_PUT(match, tun_key.ipv4_dst,
  					nla_get_be32(a), is_mask);
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1213
1214
  			break;
  		case OVS_TUNNEL_KEY_ATTR_TOS:
03f0d916a   Andy Zhou   openvswitch: Mega...
1215
1216
  			SW_FLOW_KEY_PUT(match, tun_key.ipv4_tos,
  					nla_get_u8(a), is_mask);
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1217
1218
  			break;
  		case OVS_TUNNEL_KEY_ATTR_TTL:
03f0d916a   Andy Zhou   openvswitch: Mega...
1219
1220
  			SW_FLOW_KEY_PUT(match, tun_key.ipv4_ttl,
  					nla_get_u8(a), is_mask);
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1221
1222
1223
  			ttl = true;
  			break;
  		case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT:
03f0d916a   Andy Zhou   openvswitch: Mega...
1224
  			tun_flags |= TUNNEL_DONT_FRAGMENT;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1225
1226
  			break;
  		case OVS_TUNNEL_KEY_ATTR_CSUM:
03f0d916a   Andy Zhou   openvswitch: Mega...
1227
  			tun_flags |= TUNNEL_CSUM;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1228
1229
1230
  			break;
  		default:
  			return -EINVAL;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1231
1232
  		}
  	}
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1233

03f0d916a   Andy Zhou   openvswitch: Mega...
1234
  	SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1235

03f0d916a   Andy Zhou   openvswitch: Mega...
1236
1237
1238
  	if (rem > 0) {
  		OVS_NLERR("IPv4 tunnel attribute has %d unknown bytes.
  ", rem);
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1239
  		return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
  	}
  
  	if (!is_mask) {
  		if (!match->key->tun_key.ipv4_dst) {
  			OVS_NLERR("IPv4 tunnel destination address is zero.
  ");
  			return -EINVAL;
  		}
  
  		if (!ttl) {
  			OVS_NLERR("IPv4 tunnel TTL not specified.
  ");
  			return -EINVAL;
  		}
  	}
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1255
1256
1257
1258
1259
  
  	return 0;
  }
  
  int ovs_ipv4_tun_to_nlattr(struct sk_buff *skb,
03f0d916a   Andy Zhou   openvswitch: Mega...
1260
1261
  			   const struct ovs_key_ipv4_tunnel *tun_key,
  			   const struct ovs_key_ipv4_tunnel *output)
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1262
1263
1264
1265
1266
1267
  {
  	struct nlattr *nla;
  
  	nla = nla_nest_start(skb, OVS_KEY_ATTR_TUNNEL);
  	if (!nla)
  		return -EMSGSIZE;
03f0d916a   Andy Zhou   openvswitch: Mega...
1268
1269
  	if (output->tun_flags & TUNNEL_KEY &&
  	    nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id))
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1270
  		return -EMSGSIZE;
03f0d916a   Andy Zhou   openvswitch: Mega...
1271
1272
  	if (output->ipv4_src &&
  		nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, output->ipv4_src))
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1273
  		return -EMSGSIZE;
03f0d916a   Andy Zhou   openvswitch: Mega...
1274
1275
  	if (output->ipv4_dst &&
  		nla_put_be32(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST, output->ipv4_dst))
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1276
  		return -EMSGSIZE;
03f0d916a   Andy Zhou   openvswitch: Mega...
1277
1278
  	if (output->ipv4_tos &&
  		nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->ipv4_tos))
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1279
  		return -EMSGSIZE;
03f0d916a   Andy Zhou   openvswitch: Mega...
1280
  	if (nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TTL, output->ipv4_ttl))
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1281
  		return -EMSGSIZE;
03f0d916a   Andy Zhou   openvswitch: Mega...
1282
  	if ((output->tun_flags & TUNNEL_DONT_FRAGMENT) &&
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1283
1284
  		nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT))
  		return -EMSGSIZE;
03f0d916a   Andy Zhou   openvswitch: Mega...
1285
  	if ((output->tun_flags & TUNNEL_CSUM) &&
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1286
1287
1288
1289
1290
1291
  		nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
  		return -EMSGSIZE;
  
  	nla_nest_end(skb, nla);
  	return 0;
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
1292
1293
  static int metadata_from_nlattrs(struct sw_flow_match *match,  u64 *attrs,
  		const struct nlattr **a, bool is_mask)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1294
  {
03f0d916a   Andy Zhou   openvswitch: Mega...
1295
1296
1297
1298
1299
  	if (*attrs & (1 << OVS_KEY_ATTR_PRIORITY)) {
  		SW_FLOW_KEY_PUT(match, phy.priority,
  			  nla_get_u32(a[OVS_KEY_ATTR_PRIORITY]), is_mask);
  		*attrs &= ~(1 << OVS_KEY_ATTR_PRIORITY);
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1300

03f0d916a   Andy Zhou   openvswitch: Mega...
1301
1302
  	if (*attrs & (1 << OVS_KEY_ATTR_IN_PORT)) {
  		u32 in_port = nla_get_u32(a[OVS_KEY_ATTR_IN_PORT]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1303

03f0d916a   Andy Zhou   openvswitch: Mega...
1304
1305
1306
1307
  		if (is_mask)
  			in_port = 0xffffffff; /* Always exact match in_port. */
  		else if (in_port >= DP_MAX_PORTS)
  			return -EINVAL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1308

03f0d916a   Andy Zhou   openvswitch: Mega...
1309
1310
1311
1312
  		SW_FLOW_KEY_PUT(match, phy.in_port, in_port, is_mask);
  		*attrs &= ~(1 << OVS_KEY_ATTR_IN_PORT);
  	} else if (!is_mask) {
  		SW_FLOW_KEY_PUT(match, phy.in_port, DP_MAX_PORTS, is_mask);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1313
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
1314
1315
1316
1317
1318
1319
  
  	if (*attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) {
  		uint32_t mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
  
  		SW_FLOW_KEY_PUT(match, phy.skb_mark, mark, is_mask);
  		*attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1320
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
1321
1322
1323
1324
1325
  	if (*attrs & (1 << OVS_KEY_ATTR_TUNNEL)) {
  		if (ovs_ipv4_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match,
  					is_mask))
  			return -EINVAL;
  		*attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
39c7caebc   Ansis Atteka   openvswitch: add ...
1326
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
1327
1328
  	return 0;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
1329

03f0d916a   Andy Zhou   openvswitch: Mega...
1330
1331
1332
1333
1334
  static int ovs_key_from_nlattrs(struct sw_flow_match *match,  u64 attrs,
  		const struct nlattr **a, bool is_mask)
  {
  	int err;
  	u64 orig_attrs = attrs;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1335

03f0d916a   Andy Zhou   openvswitch: Mega...
1336
1337
1338
  	err = metadata_from_nlattrs(match, &attrs, a, is_mask);
  	if (err)
  		return err;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1339

03f0d916a   Andy Zhou   openvswitch: Mega...
1340
1341
  	if (attrs & (1 << OVS_KEY_ATTR_ETHERNET)) {
  		const struct ovs_key_ethernet *eth_key;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1342

03f0d916a   Andy Zhou   openvswitch: Mega...
1343
1344
1345
1346
1347
1348
1349
  		eth_key = nla_data(a[OVS_KEY_ATTR_ETHERNET]);
  		SW_FLOW_KEY_MEMCPY(match, eth.src,
  				eth_key->eth_src, ETH_ALEN, is_mask);
  		SW_FLOW_KEY_MEMCPY(match, eth.dst,
  				eth_key->eth_dst, ETH_ALEN, is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET);
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1350

03f0d916a   Andy Zhou   openvswitch: Mega...
1351
  	if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1352
  		__be16 tci;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1353
  		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
03f0d916a   Andy Zhou   openvswitch: Mega...
1354
1355
1356
1357
1358
1359
1360
  		if (!(tci & htons(VLAN_TAG_PRESENT))) {
  			if (is_mask)
  				OVS_NLERR("VLAN TCI mask does not have exact match for VLAN_TAG_PRESENT bit.
  ");
  			else
  				OVS_NLERR("VLAN TCI does not have VLAN_TAG_PRESENT bit set.
  ");
ccb1352e7   Jesse Gross   net: Add Open vSw...
1361

ccb1352e7   Jesse Gross   net: Add Open vSw...
1362
1363
  			return -EINVAL;
  		}
03f0d916a   Andy Zhou   openvswitch: Mega...
1364
1365
1366
1367
1368
  
  		SW_FLOW_KEY_PUT(match, eth.tci, tci, is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_VLAN);
  	} else if (!is_mask)
  		SW_FLOW_KEY_PUT(match, eth.tci, htons(0xffff), true);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1369
1370
  
  	if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
  		__be16 eth_type;
  
  		eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
  		if (is_mask) {
  			/* Always exact match EtherType. */
  			eth_type = htons(0xffff);
  		} else if (ntohs(eth_type) < ETH_P_802_3_MIN) {
  			OVS_NLERR("EtherType is less than minimum (type=%x, min=%x).
  ",
  					ntohs(eth_type), ETH_P_802_3_MIN);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1381
  			return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1382
1383
1384
  		}
  
  		SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1385
  		attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
03f0d916a   Andy Zhou   openvswitch: Mega...
1386
1387
  	} else if (!is_mask) {
  		SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1388
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
1389
  	if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1390
  		const struct ovs_key_ipv4 *ipv4_key;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1391
  		ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
03f0d916a   Andy Zhou   openvswitch: Mega...
1392
1393
1394
1395
  		if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
  			OVS_NLERR("Unknown IPv4 fragment type (value=%d, max=%d).
  ",
  				ipv4_key->ipv4_frag, OVS_FRAG_TYPE_MAX);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1396
  			return -EINVAL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1397
  		}
03f0d916a   Andy Zhou   openvswitch: Mega...
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
  		SW_FLOW_KEY_PUT(match, ip.proto,
  				ipv4_key->ipv4_proto, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.tos,
  				ipv4_key->ipv4_tos, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.ttl,
  				ipv4_key->ipv4_ttl, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.frag,
  				ipv4_key->ipv4_frag, is_mask);
  		SW_FLOW_KEY_PUT(match, ipv4.addr.src,
  				ipv4_key->ipv4_src, is_mask);
  		SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
  				ipv4_key->ipv4_dst, is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_IPV4);
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1412

03f0d916a   Andy Zhou   openvswitch: Mega...
1413
1414
  	if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
  		const struct ovs_key_ipv6 *ipv6_key;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1415

ccb1352e7   Jesse Gross   net: Add Open vSw...
1416
  		ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
03f0d916a   Andy Zhou   openvswitch: Mega...
1417
1418
1419
1420
  		if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
  			OVS_NLERR("Unknown IPv6 fragment type (value=%d, max=%d).
  ",
  				ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1421
  			return -EINVAL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1422
  		}
03f0d916a   Andy Zhou   openvswitch: Mega...
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
  		SW_FLOW_KEY_PUT(match, ipv6.label,
  				ipv6_key->ipv6_label, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.proto,
  				ipv6_key->ipv6_proto, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.tos,
  				ipv6_key->ipv6_tclass, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.ttl,
  				ipv6_key->ipv6_hlimit, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.frag,
  				ipv6_key->ipv6_frag, is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.addr.src,
  				ipv6_key->ipv6_src,
  				sizeof(match->key->ipv6.addr.src),
  				is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.addr.dst,
  				ipv6_key->ipv6_dst,
  				sizeof(match->key->ipv6.addr.dst),
  				is_mask);
  
  		attrs &= ~(1 << OVS_KEY_ATTR_IPV6);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_ARP)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1446
  		const struct ovs_key_arp *arp_key;
03f0d916a   Andy Zhou   openvswitch: Mega...
1447
1448
1449
1450
1451
  		arp_key = nla_data(a[OVS_KEY_ATTR_ARP]);
  		if (!is_mask && (arp_key->arp_op & htons(0xff00))) {
  			OVS_NLERR("Unknown ARP opcode (opcode=%d).
  ",
  				  arp_key->arp_op);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1452
  			return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
  		}
  
  		SW_FLOW_KEY_PUT(match, ipv4.addr.src,
  				arp_key->arp_sip, is_mask);
  		SW_FLOW_KEY_PUT(match, ipv4.addr.dst,
  			arp_key->arp_tip, is_mask);
  		SW_FLOW_KEY_PUT(match, ip.proto,
  				ntohs(arp_key->arp_op), is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv4.arp.sha,
  				arp_key->arp_sha, ETH_ALEN, is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv4.arp.tha,
  				arp_key->arp_tha, ETH_ALEN, is_mask);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1465
  		attrs &= ~(1 << OVS_KEY_ATTR_ARP);
03f0d916a   Andy Zhou   openvswitch: Mega...
1466
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1467

03f0d916a   Andy Zhou   openvswitch: Mega...
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
  	if (attrs & (1 << OVS_KEY_ATTR_TCP)) {
  		const struct ovs_key_tcp *tcp_key;
  
  		tcp_key = nla_data(a[OVS_KEY_ATTR_TCP]);
  		if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) {
  			SW_FLOW_KEY_PUT(match, ipv4.tp.src,
  					tcp_key->tcp_src, is_mask);
  			SW_FLOW_KEY_PUT(match, ipv4.tp.dst,
  					tcp_key->tcp_dst, is_mask);
  		} else {
  			SW_FLOW_KEY_PUT(match, ipv6.tp.src,
  					tcp_key->tcp_src, is_mask);
  			SW_FLOW_KEY_PUT(match, ipv6.tp.dst,
  					tcp_key->tcp_dst, is_mask);
  		}
  		attrs &= ~(1 << OVS_KEY_ATTR_TCP);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_UDP)) {
  		const struct ovs_key_udp *udp_key;
  
  		udp_key = nla_data(a[OVS_KEY_ATTR_UDP]);
  		if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) {
  			SW_FLOW_KEY_PUT(match, ipv4.tp.src,
  					udp_key->udp_src, is_mask);
  			SW_FLOW_KEY_PUT(match, ipv4.tp.dst,
  					udp_key->udp_dst, is_mask);
  		} else {
  			SW_FLOW_KEY_PUT(match, ipv6.tp.src,
  					udp_key->udp_src, is_mask);
  			SW_FLOW_KEY_PUT(match, ipv6.tp.dst,
  					udp_key->udp_dst, is_mask);
  		}
  		attrs &= ~(1 << OVS_KEY_ATTR_UDP);
  	}
a175a7233   Joe Stringer   openvswitch: Add ...
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
  	if (attrs & (1 << OVS_KEY_ATTR_SCTP)) {
  		const struct ovs_key_sctp *sctp_key;
  
  		sctp_key = nla_data(a[OVS_KEY_ATTR_SCTP]);
  		if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) {
  			SW_FLOW_KEY_PUT(match, ipv4.tp.src,
  					sctp_key->sctp_src, is_mask);
  			SW_FLOW_KEY_PUT(match, ipv4.tp.dst,
  					sctp_key->sctp_dst, is_mask);
  		} else {
  			SW_FLOW_KEY_PUT(match, ipv6.tp.src,
  					sctp_key->sctp_src, is_mask);
  			SW_FLOW_KEY_PUT(match, ipv6.tp.dst,
  					sctp_key->sctp_dst, is_mask);
  		}
  		attrs &= ~(1 << OVS_KEY_ATTR_SCTP);
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
  	if (attrs & (1 << OVS_KEY_ATTR_ICMP)) {
  		const struct ovs_key_icmp *icmp_key;
  
  		icmp_key = nla_data(a[OVS_KEY_ATTR_ICMP]);
  		SW_FLOW_KEY_PUT(match, ipv4.tp.src,
  				htons(icmp_key->icmp_type), is_mask);
  		SW_FLOW_KEY_PUT(match, ipv4.tp.dst,
  				htons(icmp_key->icmp_code), is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_ICMP);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_ICMPV6)) {
  		const struct ovs_key_icmpv6 *icmpv6_key;
  
  		icmpv6_key = nla_data(a[OVS_KEY_ATTR_ICMPV6]);
  		SW_FLOW_KEY_PUT(match, ipv6.tp.src,
  				htons(icmpv6_key->icmpv6_type), is_mask);
  		SW_FLOW_KEY_PUT(match, ipv6.tp.dst,
  				htons(icmpv6_key->icmpv6_code), is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_ICMPV6);
  	}
  
  	if (attrs & (1 << OVS_KEY_ATTR_ND)) {
  		const struct ovs_key_nd *nd_key;
  
  		nd_key = nla_data(a[OVS_KEY_ATTR_ND]);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.target,
  			nd_key->nd_target,
  			sizeof(match->key->ipv6.nd.target),
  			is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.sll,
  			nd_key->nd_sll, ETH_ALEN, is_mask);
  		SW_FLOW_KEY_MEMCPY(match, ipv6.nd.tll,
  				nd_key->nd_tll, ETH_ALEN, is_mask);
  		attrs &= ~(1 << OVS_KEY_ATTR_ND);
  	}
  
  	if (attrs != 0)
  		return -EINVAL;
  
  	return 0;
  }
  
  /**
   * ovs_match_from_nlattrs - parses Netlink attributes into a flow key and
   * mask. In case the 'mask' is NULL, the flow is treated as exact match
   * flow. Otherwise, it is treated as a wildcarded flow, except the mask
   * does not include any don't care bit.
   * @match: receives the extracted flow match information.
   * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
   * sequence. The fields should of the packet that triggered the creation
   * of this flow.
   * @mask: Optional. Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink
   * attribute specifies the mask field of the wildcarded flow.
   */
  int ovs_match_from_nlattrs(struct sw_flow_match *match,
  			   const struct nlattr *key,
  			   const struct nlattr *mask)
  {
  	const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
  	const struct nlattr *encap;
  	u64 key_attrs = 0;
  	u64 mask_attrs = 0;
  	bool encap_valid = false;
  	int err;
  
  	err = parse_flow_nlattrs(key, a, &key_attrs);
  	if (err)
  		return err;
  
  	if ((key_attrs & (1 << OVS_KEY_ATTR_ETHERNET)) &&
  	    (key_attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) &&
  	    (nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]) == htons(ETH_P_8021Q))) {
  		__be16 tci;
  
  		if (!((key_attrs & (1 << OVS_KEY_ATTR_VLAN)) &&
  		      (key_attrs & (1 << OVS_KEY_ATTR_ENCAP)))) {
  			OVS_NLERR("Invalid Vlan frame.
  ");
ccb1352e7   Jesse Gross   net: Add Open vSw...
1599
  			return -EINVAL;
03f0d916a   Andy Zhou   openvswitch: Mega...
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
  		}
  
  		key_attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
  		tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
  		encap = a[OVS_KEY_ATTR_ENCAP];
  		key_attrs &= ~(1 << OVS_KEY_ATTR_ENCAP);
  		encap_valid = true;
  
  		if (tci & htons(VLAN_TAG_PRESENT)) {
  			err = parse_flow_nlattrs(encap, a, &key_attrs);
  			if (err)
  				return err;
  		} else if (!tci) {
  			/* Corner case for truncated 802.1Q header. */
  			if (nla_len(encap)) {
  				OVS_NLERR("Truncated 802.1Q header has non-zero encap attribute.
  ");
  				return -EINVAL;
  			}
  		} else {
  			OVS_NLERR("Encap attribute is set for a non-VLAN frame.
  ");
  			return  -EINVAL;
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1624
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
  	err = ovs_key_from_nlattrs(match, key_attrs, a, false);
  	if (err)
  		return err;
  
  	if (mask) {
  		err = parse_flow_mask_nlattrs(mask, a, &mask_attrs);
  		if (err)
  			return err;
  
  		if (mask_attrs & 1ULL << OVS_KEY_ATTR_ENCAP)  {
  			__be16 eth_type = 0;
  			__be16 tci = 0;
  
  			if (!encap_valid) {
  				OVS_NLERR("Encap mask attribute is set for non-VLAN frame.
  ");
  				return  -EINVAL;
  			}
  
  			mask_attrs &= ~(1 << OVS_KEY_ATTR_ENCAP);
  			if (a[OVS_KEY_ATTR_ETHERTYPE])
  				eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
  
  			if (eth_type == htons(0xffff)) {
  				mask_attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
  				encap = a[OVS_KEY_ATTR_ENCAP];
  				err = parse_flow_mask_nlattrs(encap, a, &mask_attrs);
  			} else {
  				OVS_NLERR("VLAN frames must have an exact match on the TPID (mask=%x).
  ",
  						ntohs(eth_type));
  				return -EINVAL;
  			}
  
  			if (a[OVS_KEY_ATTR_VLAN])
  				tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
  
  			if (!(tci & htons(VLAN_TAG_PRESENT))) {
  				OVS_NLERR("VLAN tag present bit must have an exact match (tci_mask=%x).
  ", ntohs(tci));
  				return -EINVAL;
  			}
  		}
  
  		err = ovs_key_from_nlattrs(match, mask_attrs, a, true);
  		if (err)
  			return err;
  	} else {
  		/* Populate exact match flow's key mask. */
  		if (match->mask)
  			ovs_sw_flow_mask_set(match->mask, &match->range, 0xff);
  	}
  
  	if (!ovs_match_validate(match, key_attrs, mask_attrs))
ccb1352e7   Jesse Gross   net: Add Open vSw...
1679
  		return -EINVAL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1680
1681
1682
1683
1684
1685
  
  	return 0;
  }
  
  /**
   * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key.
93d8fd151   Pravin B Shelar   openvswitch: Simp...
1686
1687
   * @flow: Receives extracted in_port, priority, tun_key and skb_mark.
   * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
ccb1352e7   Jesse Gross   net: Add Open vSw...
1688
1689
1690
1691
1692
1693
1694
   * sequence.
   *
   * This parses a series of Netlink attributes that form a flow key, which must
   * take the same form accepted by flow_from_nlattrs(), but only enough of it to
   * get the metadata, that is, the parts of the flow key that cannot be
   * extracted from the packet itself.
   */
03f0d916a   Andy Zhou   openvswitch: Mega...
1695
1696
1697
  
  int ovs_flow_metadata_from_nlattrs(struct sw_flow *flow,
  		const struct nlattr *attr)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1698
  {
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1699
  	struct ovs_key_ipv4_tunnel *tun_key = &flow->key.tun_key;
03f0d916a   Andy Zhou   openvswitch: Mega...
1700
1701
1702
1703
  	const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
  	u64 attrs = 0;
  	int err;
  	struct sw_flow_match match;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1704

93d8fd151   Pravin B Shelar   openvswitch: Simp...
1705
1706
1707
  	flow->key.phy.in_port = DP_MAX_PORTS;
  	flow->key.phy.priority = 0;
  	flow->key.phy.skb_mark = 0;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1708
  	memset(tun_key, 0, sizeof(flow->key.tun_key));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1709

03f0d916a   Andy Zhou   openvswitch: Mega...
1710
1711
  	err = parse_flow_nlattrs(attr, a, &attrs);
  	if (err)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1712
  		return -EINVAL;
a3e82996a   Pravin B Shelar   openvswitch: Opti...
1713

03f0d916a   Andy Zhou   openvswitch: Mega...
1714
1715
1716
1717
1718
1719
  	memset(&match, 0, sizeof(match));
  	match.key = &flow->key;
  
  	err = metadata_from_nlattrs(&match, &attrs, a, false);
  	if (err)
  		return err;
a3e82996a   Pravin B Shelar   openvswitch: Opti...
1720

ccb1352e7   Jesse Gross   net: Add Open vSw...
1721
1722
  	return 0;
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
1723
1724
  int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey,
  		const struct sw_flow_key *output, struct sk_buff *skb)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1725
1726
1727
  {
  	struct ovs_key_ethernet *eth_key;
  	struct nlattr *nla, *encap;
03f0d916a   Andy Zhou   openvswitch: Mega...
1728
  	bool is_mask = (swkey != output);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1729

03f0d916a   Andy Zhou   openvswitch: Mega...
1730
  	if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
028d6a676   David S. Miller   openvswitch: Stop...
1731
  		goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1732

03f0d916a   Andy Zhou   openvswitch: Mega...
1733
1734
  	if ((swkey->tun_key.ipv4_dst || is_mask) &&
  	    ovs_ipv4_tun_to_nlattr(skb, &swkey->tun_key, &output->tun_key))
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1735
  		goto nla_put_failure;
03f0d916a   Andy Zhou   openvswitch: Mega...
1736
1737
1738
1739
1740
1741
1742
  	if (swkey->phy.in_port == DP_MAX_PORTS) {
  		if (is_mask && (output->phy.in_port == 0xffff))
  			if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, 0xffffffff))
  				goto nla_put_failure;
  	} else {
  		u16 upper_u16;
  		upper_u16 = !is_mask ? 0 : 0xffff;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1743

03f0d916a   Andy Zhou   openvswitch: Mega...
1744
1745
1746
1747
1748
1749
  		if (nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT,
  				(upper_u16 << 16) | output->phy.in_port))
  			goto nla_put_failure;
  	}
  
  	if (nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, output->phy.skb_mark))
39c7caebc   Ansis Atteka   openvswitch: add ...
1750
  		goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1751
1752
1753
  	nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
  	if (!nla)
  		goto nla_put_failure;
03f0d916a   Andy Zhou   openvswitch: Mega...
1754

ccb1352e7   Jesse Gross   net: Add Open vSw...
1755
  	eth_key = nla_data(nla);
03f0d916a   Andy Zhou   openvswitch: Mega...
1756
1757
  	memcpy(eth_key->eth_src, output->eth.src, ETH_ALEN);
  	memcpy(eth_key->eth_dst, output->eth.dst, ETH_ALEN);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1758
1759
  
  	if (swkey->eth.tci || swkey->eth.type == htons(ETH_P_8021Q)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
1760
1761
1762
1763
  		__be16 eth_type;
  		eth_type = !is_mask ? htons(ETH_P_8021Q) : htons(0xffff);
  		if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, eth_type) ||
  		    nla_put_be16(skb, OVS_KEY_ATTR_VLAN, output->eth.tci))
028d6a676   David S. Miller   openvswitch: Stop...
1764
  			goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1765
1766
1767
  		encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
  		if (!swkey->eth.tci)
  			goto unencap;
03f0d916a   Andy Zhou   openvswitch: Mega...
1768
  	} else
ccb1352e7   Jesse Gross   net: Add Open vSw...
1769
  		encap = NULL;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1770

03f0d916a   Andy Zhou   openvswitch: Mega...
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
  	if (swkey->eth.type == htons(ETH_P_802_2)) {
  		/*
  		 * Ethertype 802.2 is represented in the netlink with omitted
  		 * OVS_KEY_ATTR_ETHERTYPE in the flow key attribute, and
  		 * 0xffff in the mask attribute.  Ethertype can also
  		 * be wildcarded.
  		 */
  		if (is_mask && output->eth.type)
  			if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE,
  						output->eth.type))
  				goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1782
  		goto unencap;
03f0d916a   Andy Zhou   openvswitch: Mega...
1783
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1784

03f0d916a   Andy Zhou   openvswitch: Mega...
1785
  	if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type))
028d6a676   David S. Miller   openvswitch: Stop...
1786
  		goto nla_put_failure;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1787
1788
1789
1790
1791
1792
1793
1794
  
  	if (swkey->eth.type == htons(ETH_P_IP)) {
  		struct ovs_key_ipv4 *ipv4_key;
  
  		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV4, sizeof(*ipv4_key));
  		if (!nla)
  			goto nla_put_failure;
  		ipv4_key = nla_data(nla);
03f0d916a   Andy Zhou   openvswitch: Mega...
1795
1796
1797
1798
1799
1800
  		ipv4_key->ipv4_src = output->ipv4.addr.src;
  		ipv4_key->ipv4_dst = output->ipv4.addr.dst;
  		ipv4_key->ipv4_proto = output->ip.proto;
  		ipv4_key->ipv4_tos = output->ip.tos;
  		ipv4_key->ipv4_ttl = output->ip.ttl;
  		ipv4_key->ipv4_frag = output->ip.frag;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1801
1802
1803
1804
1805
1806
1807
  	} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
  		struct ovs_key_ipv6 *ipv6_key;
  
  		nla = nla_reserve(skb, OVS_KEY_ATTR_IPV6, sizeof(*ipv6_key));
  		if (!nla)
  			goto nla_put_failure;
  		ipv6_key = nla_data(nla);
03f0d916a   Andy Zhou   openvswitch: Mega...
1808
  		memcpy(ipv6_key->ipv6_src, &output->ipv6.addr.src,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1809
  				sizeof(ipv6_key->ipv6_src));
03f0d916a   Andy Zhou   openvswitch: Mega...
1810
  		memcpy(ipv6_key->ipv6_dst, &output->ipv6.addr.dst,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1811
  				sizeof(ipv6_key->ipv6_dst));
03f0d916a   Andy Zhou   openvswitch: Mega...
1812
1813
1814
1815
1816
  		ipv6_key->ipv6_label = output->ipv6.label;
  		ipv6_key->ipv6_proto = output->ip.proto;
  		ipv6_key->ipv6_tclass = output->ip.tos;
  		ipv6_key->ipv6_hlimit = output->ip.ttl;
  		ipv6_key->ipv6_frag = output->ip.frag;
c06185338   Mehak Mahajan   openvswitch: Proc...
1817
1818
  	} else if (swkey->eth.type == htons(ETH_P_ARP) ||
  		   swkey->eth.type == htons(ETH_P_RARP)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1819
1820
1821
1822
1823
1824
1825
  		struct ovs_key_arp *arp_key;
  
  		nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));
  		if (!nla)
  			goto nla_put_failure;
  		arp_key = nla_data(nla);
  		memset(arp_key, 0, sizeof(struct ovs_key_arp));
03f0d916a   Andy Zhou   openvswitch: Mega...
1826
1827
1828
1829
1830
  		arp_key->arp_sip = output->ipv4.addr.src;
  		arp_key->arp_tip = output->ipv4.addr.dst;
  		arp_key->arp_op = htons(output->ip.proto);
  		memcpy(arp_key->arp_sha, output->ipv4.arp.sha, ETH_ALEN);
  		memcpy(arp_key->arp_tha, output->ipv4.arp.tha, ETH_ALEN);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
  	}
  
  	if ((swkey->eth.type == htons(ETH_P_IP) ||
  	     swkey->eth.type == htons(ETH_P_IPV6)) &&
  	     swkey->ip.frag != OVS_FRAG_TYPE_LATER) {
  
  		if (swkey->ip.proto == IPPROTO_TCP) {
  			struct ovs_key_tcp *tcp_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_TCP, sizeof(*tcp_key));
  			if (!nla)
  				goto nla_put_failure;
  			tcp_key = nla_data(nla);
  			if (swkey->eth.type == htons(ETH_P_IP)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
1845
1846
  				tcp_key->tcp_src = output->ipv4.tp.src;
  				tcp_key->tcp_dst = output->ipv4.tp.dst;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1847
  			} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
1848
1849
  				tcp_key->tcp_src = output->ipv6.tp.src;
  				tcp_key->tcp_dst = output->ipv6.tp.dst;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1850
1851
1852
1853
1854
1855
1856
1857
1858
  			}
  		} else if (swkey->ip.proto == IPPROTO_UDP) {
  			struct ovs_key_udp *udp_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_UDP, sizeof(*udp_key));
  			if (!nla)
  				goto nla_put_failure;
  			udp_key = nla_data(nla);
  			if (swkey->eth.type == htons(ETH_P_IP)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
1859
1860
  				udp_key->udp_src = output->ipv4.tp.src;
  				udp_key->udp_dst = output->ipv4.tp.dst;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1861
  			} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
1862
1863
  				udp_key->udp_src = output->ipv6.tp.src;
  				udp_key->udp_dst = output->ipv6.tp.dst;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1864
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
  		} else if (swkey->ip.proto == IPPROTO_SCTP) {
  			struct ovs_key_sctp *sctp_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_SCTP, sizeof(*sctp_key));
  			if (!nla)
  				goto nla_put_failure;
  			sctp_key = nla_data(nla);
  			if (swkey->eth.type == htons(ETH_P_IP)) {
  				sctp_key->sctp_src = swkey->ipv4.tp.src;
  				sctp_key->sctp_dst = swkey->ipv4.tp.dst;
  			} else if (swkey->eth.type == htons(ETH_P_IPV6)) {
  				sctp_key->sctp_src = swkey->ipv6.tp.src;
  				sctp_key->sctp_dst = swkey->ipv6.tp.dst;
  			}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1879
1880
1881
1882
1883
1884
1885
1886
  		} else if (swkey->eth.type == htons(ETH_P_IP) &&
  			   swkey->ip.proto == IPPROTO_ICMP) {
  			struct ovs_key_icmp *icmp_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_ICMP, sizeof(*icmp_key));
  			if (!nla)
  				goto nla_put_failure;
  			icmp_key = nla_data(nla);
03f0d916a   Andy Zhou   openvswitch: Mega...
1887
1888
  			icmp_key->icmp_type = ntohs(output->ipv4.tp.src);
  			icmp_key->icmp_code = ntohs(output->ipv4.tp.dst);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1889
1890
1891
1892
1893
1894
1895
1896
1897
  		} else if (swkey->eth.type == htons(ETH_P_IPV6) &&
  			   swkey->ip.proto == IPPROTO_ICMPV6) {
  			struct ovs_key_icmpv6 *icmpv6_key;
  
  			nla = nla_reserve(skb, OVS_KEY_ATTR_ICMPV6,
  						sizeof(*icmpv6_key));
  			if (!nla)
  				goto nla_put_failure;
  			icmpv6_key = nla_data(nla);
03f0d916a   Andy Zhou   openvswitch: Mega...
1898
1899
  			icmpv6_key->icmpv6_type = ntohs(output->ipv6.tp.src);
  			icmpv6_key->icmpv6_code = ntohs(output->ipv6.tp.dst);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1900
1901
1902
1903
1904
1905
1906
1907
1908
  
  			if (icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_SOLICITATION ||
  			    icmpv6_key->icmpv6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
  				struct ovs_key_nd *nd_key;
  
  				nla = nla_reserve(skb, OVS_KEY_ATTR_ND, sizeof(*nd_key));
  				if (!nla)
  					goto nla_put_failure;
  				nd_key = nla_data(nla);
03f0d916a   Andy Zhou   openvswitch: Mega...
1909
  				memcpy(nd_key->nd_target, &output->ipv6.nd.target,
ccb1352e7   Jesse Gross   net: Add Open vSw...
1910
  							sizeof(nd_key->nd_target));
03f0d916a   Andy Zhou   openvswitch: Mega...
1911
1912
  				memcpy(nd_key->nd_sll, output->ipv6.nd.sll, ETH_ALEN);
  				memcpy(nd_key->nd_tll, output->ipv6.nd.tll, ETH_ALEN);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
  			}
  		}
  	}
  
  unencap:
  	if (encap)
  		nla_nest_end(skb, encap);
  
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
  
  /* Initializes the flow module.
   * Returns zero if successful or a negative error code. */
  int ovs_flow_init(void)
  {
0d40f75bd   Jesse Gross   openvswitch: Fix ...
1931
  	BUILD_BUG_ON(__alignof__(struct sw_flow_key) % __alignof__(long));
5828cd9a6   Andy Zhou   openvswitch: opti...
1932
  	BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
  	flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow), 0,
  					0, NULL);
  	if (flow_cache == NULL)
  		return -ENOMEM;
  
  	return 0;
  }
  
  /* Uninitializes the flow module. */
  void ovs_flow_exit(void)
  {
  	kmem_cache_destroy(flow_cache);
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
  
  struct sw_flow_mask *ovs_sw_flow_mask_alloc(void)
  {
  	struct sw_flow_mask *mask;
  
  	mask = kmalloc(sizeof(*mask), GFP_KERNEL);
  	if (mask)
  		mask->ref_count = 0;
  
  	return mask;
  }
  
  void ovs_sw_flow_mask_add_ref(struct sw_flow_mask *mask)
  {
  	mask->ref_count++;
  }
  
  void ovs_sw_flow_mask_del_ref(struct sw_flow_mask *mask, bool deferred)
  {
  	if (!mask)
  		return;
  
  	BUG_ON(!mask->ref_count);
  	mask->ref_count--;
  
  	if (!mask->ref_count) {
  		list_del_rcu(&mask->list);
  		if (deferred)
  			kfree_rcu(mask, rcu);
  		else
  			kfree(mask);
  	}
  }
  
  static bool ovs_sw_flow_mask_equal(const struct sw_flow_mask *a,
  		const struct sw_flow_mask *b)
  {
  	u8 *a_ = (u8 *)&a->key + a->range.start;
  	u8 *b_ = (u8 *)&b->key + b->range.start;
  
  	return  (a->range.end == b->range.end)
  		&& (a->range.start == b->range.start)
5828cd9a6   Andy Zhou   openvswitch: opti...
1988
  		&& (memcmp(a_, b_, range_n_bytes(&a->range)) == 0);
03f0d916a   Andy Zhou   openvswitch: Mega...
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
  }
  
  struct sw_flow_mask *ovs_sw_flow_mask_find(const struct flow_table *tbl,
                                             const struct sw_flow_mask *mask)
  {
  	struct list_head *ml;
  
  	list_for_each(ml, tbl->mask_list) {
  		struct sw_flow_mask *m;
  		m = container_of(ml, struct sw_flow_mask, list);
  		if (ovs_sw_flow_mask_equal(mask, m))
  			return m;
  	}
  
  	return NULL;
  }
  
  /**
   * add a new mask into the mask list.
   * The caller needs to make sure that 'mask' is not the same
   * as any masks that are already on the list.
   */
  void ovs_sw_flow_mask_insert(struct flow_table *tbl, struct sw_flow_mask *mask)
  {
  	list_add_rcu(&mask->list, tbl->mask_list);
  }
  
  /**
   * Set 'range' fields in the mask to the value of 'val'.
   */
  static void ovs_sw_flow_mask_set(struct sw_flow_mask *mask,
  		struct sw_flow_key_range *range, u8 val)
  {
  	u8 *m = (u8 *)&mask->key + range->start;
  
  	mask->range = *range;
5828cd9a6   Andy Zhou   openvswitch: opti...
2025
  	memset(m, val, range_n_bytes(range));
03f0d916a   Andy Zhou   openvswitch: Mega...
2026
  }