Blame view

net/openvswitch/flow.c 18.8 KB
ccb1352e7   Jesse Gross   net: Add Open vSw...
1
  /*
971427f35   Andy Zhou   openvswitch: Add ...
2
   * Copyright (c) 2007-2014 Nicira, Inc.
ccb1352e7   Jesse Gross   net: Add Open vSw...
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   *
   * 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
   */
ccb1352e7   Jesse Gross   net: Add Open vSw...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  #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...
32
33
  #include <linux/ip.h>
  #include <linux/ipv6.h>
25cd9ba0a   Simon Horman   openvswitch: Add ...
34
  #include <linux/mpls.h>
a175a7233   Joe Stringer   openvswitch: Add ...
35
  #include <linux/sctp.h>
e298e5057   Pravin B Shelar   openvswitch: Per ...
36
  #include <linux/smp.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
37
38
39
40
41
42
  #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 ...
43
  #include <net/ip_tunnels.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
44
  #include <net/ipv6.h>
25cd9ba0a   Simon Horman   openvswitch: Add ...
45
  #include <net/mpls.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
46
  #include <net/ndisc.h>
83c8df26a   Pravin B Shelar   openvswitch: refa...
47
48
49
  #include "datapath.h"
  #include "flow.h"
  #include "flow_netlink.h"
e64457191   Pravin B Shelar   openvswitch: Rest...
50
  u64 ovs_flow_used_time(unsigned long flow_jiffies)
03f0d916a   Andy Zhou   openvswitch: Mega...
51
  {
e64457191   Pravin B Shelar   openvswitch: Rest...
52
53
  	struct timespec cur_ts;
  	u64 cur_ms, idle_ms;
03f0d916a   Andy Zhou   openvswitch: Mega...
54

e64457191   Pravin B Shelar   openvswitch: Rest...
55
56
57
58
  	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;
03f0d916a   Andy Zhou   openvswitch: Mega...
59

e64457191   Pravin B Shelar   openvswitch: Rest...
60
  	return cur_ms - idle_ms;
5828cd9a6   Andy Zhou   openvswitch: opti...
61
  }
df23e9f64   Jarno Rajahalme   openvswitch: Wide...
62
  #define TCP_FLAGS_BE16(tp) (*(__be16 *)&tcp_flag_word(tp) & htons(0x0FFF))
03f0d916a   Andy Zhou   openvswitch: Mega...
63

ad5520073   Ben Pfaff   openvswitch: Fix ...
64
  void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
12eb18f71   Thomas Graf   openvswitch: Cons...
65
  			   const struct sk_buff *skb)
03f0d916a   Andy Zhou   openvswitch: Mega...
66
  {
e298e5057   Pravin B Shelar   openvswitch: Per ...
67
  	struct flow_stats *stats;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
68
  	int node = numa_node_id();
df8a39def   Jiri Pirko   net: rename vlan_...
69
  	int len = skb->len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
03f0d916a   Andy Zhou   openvswitch: Mega...
70

63e7959c4   Jarno Rajahalme   openvswitch: Per ...
71
  	stats = rcu_dereference(flow->stats[node]);
e298e5057   Pravin B Shelar   openvswitch: Per ...
72

63e7959c4   Jarno Rajahalme   openvswitch: Per ...
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  	/* Check if already have node-specific stats. */
  	if (likely(stats)) {
  		spin_lock(&stats->lock);
  		/* Mark if we write on the pre-allocated stats. */
  		if (node == 0 && unlikely(flow->stats_last_writer != node))
  			flow->stats_last_writer = node;
  	} else {
  		stats = rcu_dereference(flow->stats[0]); /* Pre-allocated. */
  		spin_lock(&stats->lock);
  
  		/* If the current NUMA-node is the only writer on the
  		 * pre-allocated stats keep using them.
  		 */
  		if (unlikely(flow->stats_last_writer != node)) {
  			/* A previous locker may have already allocated the
  			 * stats, so we need to check again.  If node-specific
  			 * stats were already allocated, we update the pre-
  			 * allocated stats as we have already locked them.
  			 */
  			if (likely(flow->stats_last_writer != NUMA_NO_NODE)
8c6b00c81   Andreea-Cristina Bernat   net/openvswitch/f...
93
  			    && likely(!rcu_access_pointer(flow->stats[node]))) {
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
94
95
96
97
98
  				/* Try to allocate node-specific stats. */
  				struct flow_stats *new_stats;
  
  				new_stats =
  					kmem_cache_alloc_node(flow_stats_cache,
4167e9b2c   David Rientjes   mm: remove GFP_TH...
99
100
101
  							      GFP_NOWAIT |
  							      __GFP_THISNODE |
  							      __GFP_NOWARN |
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
102
103
104
105
106
  							      __GFP_NOMEMALLOC,
  							      node);
  				if (likely(new_stats)) {
  					new_stats->used = jiffies;
  					new_stats->packet_count = 1;
24cc59d1e   Ben Pfaff   openvswitch: Cons...
107
  					new_stats->byte_count = len;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
108
109
110
111
112
113
114
115
116
117
118
  					new_stats->tcp_flags = tcp_flags;
  					spin_lock_init(&new_stats->lock);
  
  					rcu_assign_pointer(flow->stats[node],
  							   new_stats);
  					goto unlock;
  				}
  			}
  			flow->stats_last_writer = node;
  		}
  	}
e298e5057   Pravin B Shelar   openvswitch: Per ...
119
120
  	stats->used = jiffies;
  	stats->packet_count++;
24cc59d1e   Ben Pfaff   openvswitch: Cons...
121
  	stats->byte_count += len;
e298e5057   Pravin B Shelar   openvswitch: Per ...
122
  	stats->tcp_flags |= tcp_flags;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
123
  unlock:
e298e5057   Pravin B Shelar   openvswitch: Per ...
124
125
  	spin_unlock(&stats->lock);
  }
86ec8dbae   Jarno Rajahalme   openvswitch: Fix ...
126
127
128
  /* Must be called with rcu_read_lock or ovs_mutex. */
  void ovs_flow_stats_get(const struct sw_flow *flow,
  			struct ovs_flow_stats *ovs_stats,
e298e5057   Pravin B Shelar   openvswitch: Per ...
129
130
  			unsigned long *used, __be16 *tcp_flags)
  {
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
131
  	int node;
e298e5057   Pravin B Shelar   openvswitch: Per ...
132
133
134
135
  
  	*used = 0;
  	*tcp_flags = 0;
  	memset(ovs_stats, 0, sizeof(*ovs_stats));
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
136
  	for_each_node(node) {
86ec8dbae   Jarno Rajahalme   openvswitch: Fix ...
137
  		struct flow_stats *stats = rcu_dereference_ovsl(flow->stats[node]);
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
138
139
140
141
142
143
144
145
146
147
148
149
150
  
  		if (stats) {
  			/* Local CPU may write on non-local stats, so we must
  			 * block bottom-halves here.
  			 */
  			spin_lock_bh(&stats->lock);
  			if (!*used || time_after(stats->used, *used))
  				*used = stats->used;
  			*tcp_flags |= stats->tcp_flags;
  			ovs_stats->n_packets += stats->packet_count;
  			ovs_stats->n_bytes += stats->byte_count;
  			spin_unlock_bh(&stats->lock);
  		}
e298e5057   Pravin B Shelar   openvswitch: Per ...
151
  	}
e298e5057   Pravin B Shelar   openvswitch: Per ...
152
  }
86ec8dbae   Jarno Rajahalme   openvswitch: Fix ...
153
  /* Called with ovs_mutex. */
e298e5057   Pravin B Shelar   openvswitch: Per ...
154
155
  void ovs_flow_stats_clear(struct sw_flow *flow)
  {
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
156
157
158
  	int node;
  
  	for_each_node(node) {
86ec8dbae   Jarno Rajahalme   openvswitch: Fix ...
159
  		struct flow_stats *stats = ovsl_dereference(flow->stats[node]);
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
160
161
162
163
164
165
166
167
168
169
  
  		if (stats) {
  			spin_lock_bh(&stats->lock);
  			stats->used = 0;
  			stats->packet_count = 0;
  			stats->byte_count = 0;
  			stats->tcp_flags = 0;
  			spin_unlock_bh(&stats->lock);
  		}
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
170
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
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
  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 ...
226
227
228
229
230
  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...
231
232
233
234
235
  static bool icmphdr_ok(struct sk_buff *skb)
  {
  	return pskb_may_pull(skb, skb_transport_offset(skb) +
  				  sizeof(struct icmphdr));
  }
03f0d916a   Andy Zhou   openvswitch: Mega...
236
  static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
237
238
239
240
241
242
243
244
  {
  	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...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
  	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;
25ef1328a   Pravin B Shelar   openvswitch: Set ...
269
270
  	} else {
  		key->ip.frag = OVS_FRAG_TYPE_NONE;
ccb1352e7   Jesse Gross   net: Add Open vSw...
271
272
273
274
275
276
277
278
279
280
281
282
283
  	}
  
  	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));
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
  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...
320
  	if (ntohs(proto) >= ETH_P_802_3_MIN)
ccb1352e7   Jesse Gross   net: Add Open vSw...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
  		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 ...
336

e5c5d22e8   Simon Horman   net: add ETH_P_80...
337
  	if (ntohs(llc->ethertype) >= ETH_P_802_3_MIN)
17b682a04   Rich Lane   openvswitch: Fix ...
338
339
340
  		return llc->ethertype;
  
  	return htons(ETH_P_802_2);
ccb1352e7   Jesse Gross   net: Add Open vSw...
341
342
343
  }
  
  static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
03f0d916a   Andy Zhou   openvswitch: Mega...
344
  			int nh_len)
ccb1352e7   Jesse Gross   net: Add Open vSw...
345
346
  {
  	struct icmp6hdr *icmp = icmp6_hdr(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
347
348
349
350
  
  	/* 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.
  	 */
1139e241e   Jarno Rajahalme   openvswitch: Comp...
351
352
  	key->tp.src = htons(icmp->icmp6_type);
  	key->tp.dst = htons(icmp->icmp6_code);
25ef1328a   Pravin B Shelar   openvswitch: Set ...
353
  	memset(&key->ipv6.nd, 0, sizeof(key->ipv6.nd));
ccb1352e7   Jesse Gross   net: Add Open vSw...
354
355
356
357
358
359
360
  
  	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...
361
362
363
364
  		/* In order to process neighbor discovery options, we need the
  		 * entire packet.
  		 */
  		if (unlikely(icmp_len < sizeof(*nd)))
03f0d916a   Andy Zhou   openvswitch: Mega...
365
366
367
368
  			return 0;
  
  		if (unlikely(skb_linearize(skb)))
  			return -ENOMEM;
ccb1352e7   Jesse Gross   net: Add Open vSw...
369
370
371
  
  		nd = (struct nd_msg *)skb_transport_header(skb);
  		key->ipv6.nd.target = nd->target;
ccb1352e7   Jesse Gross   net: Add Open vSw...
372
373
374
375
376
377
378
379
380
  
  		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...
381
  				return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
382
383
384
385
386
387
388
389
390
  
  			/* 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;
8c63ff09b   Joe Perches   openvswitch: Use ...
391
392
  				ether_addr_copy(key->ipv6.nd.sll,
  						&nd->opt[offset+sizeof(*nd_opt)]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
393
394
395
396
  			} 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;
8c63ff09b   Joe Perches   openvswitch: Use ...
397
398
  				ether_addr_copy(key->ipv6.nd.tll,
  						&nd->opt[offset+sizeof(*nd_opt)]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
399
400
401
402
403
404
  			}
  
  			icmp_len -= opt_len;
  			offset += opt_len;
  		}
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
405
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
406
407
408
409
410
  
  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...
411
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
412
413
414
  }
  
  /**
83c8df26a   Pravin B Shelar   openvswitch: refa...
415
   * key_extract - extracts a flow key from an Ethernet frame.
ccb1352e7   Jesse Gross   net: Add Open vSw...
416
417
   * @skb: sk_buff that contains the frame, with skb->data pointing to the
   * Ethernet header
ccb1352e7   Jesse Gross   net: Add Open vSw...
418
   * @key: output flow key
ccb1352e7   Jesse Gross   net: Add Open vSw...
419
420
421
422
423
424
425
426
427
428
429
430
   *
   * 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 ...
431
   *    - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
ccb1352e7   Jesse Gross   net: Add Open vSw...
432
433
   *      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 ...
434
   *      For other key->eth.type values it is left untouched.
ccb1352e7   Jesse Gross   net: Add Open vSw...
435
   */
83c8df26a   Pravin B Shelar   openvswitch: refa...
436
  static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
437
  {
03f0d916a   Andy Zhou   openvswitch: Mega...
438
  	int error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
439
  	struct ethhdr *eth;
f57966840   Jesse Gross   openvswitch: Add ...
440
441
  	/* Flags are always used as part of stats */
  	key->tp.flags = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
442
443
444
445
446
447
  	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);
8c63ff09b   Joe Perches   openvswitch: Use ...
448
449
  	ether_addr_copy(key->eth.src, eth->h_source);
  	ether_addr_copy(key->eth.dst, eth->h_dest);
ccb1352e7   Jesse Gross   net: Add Open vSw...
450
451
  
  	__skb_pull(skb, 2 * ETH_ALEN);
b34df5e80   Pravin B Shelar   openvswitch: make...
452
453
454
  	/* 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...
455

071481213   Jesse Gross   openvswitch: Elim...
456
  	key->eth.tci = 0;
df8a39def   Jiri Pirko   net: rename vlan_...
457
  	if (skb_vlan_tag_present(skb))
ccb1352e7   Jesse Gross   net: Add Open vSw...
458
459
460
461
462
463
464
465
466
467
  		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);
25cd9ba0a   Simon Horman   openvswitch: Add ...
468
  	skb_reset_mac_len(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
469
470
471
472
473
474
  	__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...
475
476
  		error = check_iphdr(skb);
  		if (unlikely(error)) {
071481213   Jesse Gross   openvswitch: Elim...
477
478
  			memset(&key->ip, 0, sizeof(key->ip));
  			memset(&key->ipv4, 0, sizeof(key->ipv4));
ccb1352e7   Jesse Gross   net: Add Open vSw...
479
480
481
482
  			if (error == -EINVAL) {
  				skb->transport_header = skb->network_header;
  				error = 0;
  			}
03f0d916a   Andy Zhou   openvswitch: Mega...
483
  			return error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
484
485
486
487
488
489
490
491
492
493
494
495
496
  		}
  
  		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...
497
  			return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
498
499
  		}
  		if (nh->frag_off & htons(IP_MF) ||
071481213   Jesse Gross   openvswitch: Elim...
500
  			skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
ccb1352e7   Jesse Gross   net: Add Open vSw...
501
  			key->ip.frag = OVS_FRAG_TYPE_FIRST;
071481213   Jesse Gross   openvswitch: Elim...
502
503
  		else
  			key->ip.frag = OVS_FRAG_TYPE_NONE;
ccb1352e7   Jesse Gross   net: Add Open vSw...
504
505
506
  
  		/* Transport layer. */
  		if (key->ip.proto == IPPROTO_TCP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
507
508
  			if (tcphdr_ok(skb)) {
  				struct tcphdr *tcp = tcp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
509
510
511
  				key->tp.src = tcp->source;
  				key->tp.dst = tcp->dest;
  				key->tp.flags = TCP_FLAGS_BE16(tcp);
071481213   Jesse Gross   openvswitch: Elim...
512
513
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
514
  			}
071481213   Jesse Gross   openvswitch: Elim...
515

ccb1352e7   Jesse Gross   net: Add Open vSw...
516
  		} else if (key->ip.proto == IPPROTO_UDP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
517
518
  			if (udphdr_ok(skb)) {
  				struct udphdr *udp = udp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
519
520
  				key->tp.src = udp->source;
  				key->tp.dst = udp->dest;
071481213   Jesse Gross   openvswitch: Elim...
521
522
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
523
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
524
525
526
  		} else if (key->ip.proto == IPPROTO_SCTP) {
  			if (sctphdr_ok(skb)) {
  				struct sctphdr *sctp = sctp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
527
528
  				key->tp.src = sctp->source;
  				key->tp.dst = sctp->dest;
071481213   Jesse Gross   openvswitch: Elim...
529
530
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
a175a7233   Joe Stringer   openvswitch: Add ...
531
  			}
ccb1352e7   Jesse Gross   net: Add Open vSw...
532
  		} else if (key->ip.proto == IPPROTO_ICMP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
533
534
535
536
537
  			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. */
1139e241e   Jarno Rajahalme   openvswitch: Comp...
538
539
  				key->tp.src = htons(icmp->type);
  				key->tp.dst = htons(icmp->code);
071481213   Jesse Gross   openvswitch: Elim...
540
541
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
542
543
  			}
  		}
071481213   Jesse Gross   openvswitch: Elim...
544
545
  	} else if (key->eth.type == htons(ETH_P_ARP) ||
  		   key->eth.type == htons(ETH_P_RARP)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
546
  		struct arp_eth_header *arp;
389f48947   Li RongQing   openvswitch: fix ...
547
  		bool arp_available = arphdr_ok(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
548
549
  
  		arp = (struct arp_eth_header *)skb_network_header(skb);
389f48947   Li RongQing   openvswitch: fix ...
550
  		if (arp_available &&
071481213   Jesse Gross   openvswitch: Elim...
551
552
553
554
  		    arp->ar_hrd == htons(ARPHRD_ETHER) &&
  		    arp->ar_pro == htons(ETH_P_IP) &&
  		    arp->ar_hln == ETH_ALEN &&
  		    arp->ar_pln == 4) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
555
556
557
558
  
  			/* We only match on the lower 8 bits of the opcode. */
  			if (ntohs(arp->ar_op) <= 0xff)
  				key->ip.proto = ntohs(arp->ar_op);
071481213   Jesse Gross   openvswitch: Elim...
559
560
  			else
  				key->ip.proto = 0;
d04d38298   Mehak Mahajan   openvswitch: Stor...
561
562
  			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));
8c63ff09b   Joe Perches   openvswitch: Use ...
563
564
  			ether_addr_copy(key->ipv4.arp.sha, arp->ar_sha);
  			ether_addr_copy(key->ipv4.arp.tha, arp->ar_tha);
071481213   Jesse Gross   openvswitch: Elim...
565
566
567
  		} else {
  			memset(&key->ip, 0, sizeof(key->ip));
  			memset(&key->ipv4, 0, sizeof(key->ipv4));
ccb1352e7   Jesse Gross   net: Add Open vSw...
568
  		}
25cd9ba0a   Simon Horman   openvswitch: Add ...
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
  	} else if (eth_p_mpls(key->eth.type)) {
  		size_t stack_len = MPLS_HLEN;
  
  		/* In the presence of an MPLS label stack the end of the L2
  		 * header and the beginning of the L3 header differ.
  		 *
  		 * Advance network_header to the beginning of the L3
  		 * header. mac_len corresponds to the end of the L2 header.
  		 */
  		while (1) {
  			__be32 lse;
  
  			error = check_header(skb, skb->mac_len + stack_len);
  			if (unlikely(error))
  				return 0;
  
  			memcpy(&lse, skb_network_header(skb), MPLS_HLEN);
  
  			if (stack_len == MPLS_HLEN)
  				memcpy(&key->mpls.top_lse, &lse, MPLS_HLEN);
  
  			skb_set_network_header(skb, skb->mac_len + stack_len);
  			if (lse & htonl(MPLS_LS_S_MASK))
  				break;
  
  			stack_len += MPLS_HLEN;
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
596
597
  	} else if (key->eth.type == htons(ETH_P_IPV6)) {
  		int nh_len;             /* IPv6 Header + Extensions */
03f0d916a   Andy Zhou   openvswitch: Mega...
598
  		nh_len = parse_ipv6hdr(skb, key);
ccb1352e7   Jesse Gross   net: Add Open vSw...
599
  		if (unlikely(nh_len < 0)) {
071481213   Jesse Gross   openvswitch: Elim...
600
601
  			memset(&key->ip, 0, sizeof(key->ip));
  			memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr));
03f0d916a   Andy Zhou   openvswitch: Mega...
602
  			if (nh_len == -EINVAL) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
603
  				skb->transport_header = skb->network_header;
03f0d916a   Andy Zhou   openvswitch: Mega...
604
605
  				error = 0;
  			} else {
ccb1352e7   Jesse Gross   net: Add Open vSw...
606
  				error = nh_len;
03f0d916a   Andy Zhou   openvswitch: Mega...
607
608
  			}
  			return error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
609
610
611
  		}
  
  		if (key->ip.frag == OVS_FRAG_TYPE_LATER)
03f0d916a   Andy Zhou   openvswitch: Mega...
612
  			return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
613
614
615
616
617
  		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...
618
619
  			if (tcphdr_ok(skb)) {
  				struct tcphdr *tcp = tcp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
620
621
622
  				key->tp.src = tcp->source;
  				key->tp.dst = tcp->dest;
  				key->tp.flags = TCP_FLAGS_BE16(tcp);
071481213   Jesse Gross   openvswitch: Elim...
623
624
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
625
626
  			}
  		} else if (key->ip.proto == NEXTHDR_UDP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
627
628
  			if (udphdr_ok(skb)) {
  				struct udphdr *udp = udp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
629
630
  				key->tp.src = udp->source;
  				key->tp.dst = udp->dest;
071481213   Jesse Gross   openvswitch: Elim...
631
632
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
633
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
634
635
636
  		} else if (key->ip.proto == NEXTHDR_SCTP) {
  			if (sctphdr_ok(skb)) {
  				struct sctphdr *sctp = sctp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
637
638
  				key->tp.src = sctp->source;
  				key->tp.dst = sctp->dest;
071481213   Jesse Gross   openvswitch: Elim...
639
640
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
a175a7233   Joe Stringer   openvswitch: Add ...
641
  			}
ccb1352e7   Jesse Gross   net: Add Open vSw...
642
  		} else if (key->ip.proto == NEXTHDR_ICMP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
643
  			if (icmp6hdr_ok(skb)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
644
645
646
  				error = parse_icmpv6(skb, key, nh_len);
  				if (error)
  					return error;
071481213   Jesse Gross   openvswitch: Elim...
647
648
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
649
650
651
  			}
  		}
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
652
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
653
  }
83c8df26a   Pravin B Shelar   openvswitch: refa...
654

971427f35   Andy Zhou   openvswitch: Add ...
655
656
657
658
  int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
  {
  	return key_extract(skb, key);
  }
12eb18f71   Thomas Graf   openvswitch: Cons...
659
  int ovs_flow_key_extract(const struct ovs_tunnel_info *tun_info,
8c8b1b83f   Pravin B Shelar   openvswitch: Use ...
660
  			 struct sk_buff *skb, struct sw_flow_key *key)
83c8df26a   Pravin B Shelar   openvswitch: refa...
661
662
  {
  	/* Extract metadata from packet. */
f57966840   Jesse Gross   openvswitch: Add ...
663
  	if (tun_info) {
f0b128c1e   Jesse Gross   openvswitch: Wrap...
664
  		memcpy(&key->tun_key, &tun_info->tunnel, sizeof(key->tun_key));
f57966840   Jesse Gross   openvswitch: Add ...
665
666
667
668
669
  
  		if (tun_info->options) {
  			BUILD_BUG_ON((1 << (sizeof(tun_info->options_len) *
  						   8)) - 1
  					> sizeof(key->tun_opts));
d91641d9b   Thomas Graf   openvswitch: Rena...
670
  			memcpy(TUN_METADATA_OPTS(key, tun_info->options_len),
f57966840   Jesse Gross   openvswitch: Add ...
671
672
673
674
675
676
677
  			       tun_info->options, tun_info->options_len);
  			key->tun_opts_len = tun_info->options_len;
  		} else {
  			key->tun_opts_len = 0;
  		}
  	} else  {
  		key->tun_opts_len = 0;
071481213   Jesse Gross   openvswitch: Elim...
678
  		memset(&key->tun_key, 0, sizeof(key->tun_key));
f57966840   Jesse Gross   openvswitch: Add ...
679
  	}
83c8df26a   Pravin B Shelar   openvswitch: refa...
680
681
682
683
  
  	key->phy.priority = skb->priority;
  	key->phy.in_port = OVS_CB(skb)->input_vport->port_no;
  	key->phy.skb_mark = skb->mark;
071481213   Jesse Gross   openvswitch: Elim...
684
685
  	key->ovs_flow_hash = 0;
  	key->recirc_id = 0;
83c8df26a   Pravin B Shelar   openvswitch: refa...
686
687
688
689
690
  	return key_extract(skb, key);
  }
  
  int ovs_flow_key_extract_userspace(const struct nlattr *attr,
  				   struct sk_buff *skb,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
691
  				   struct sw_flow_key *key, bool log)
83c8df26a   Pravin B Shelar   openvswitch: refa...
692
693
  {
  	int err;
b35725a28   Pravin B Shelar   openvswitch: Rese...
694
  	memset(key, 0, OVS_SW_FLOW_KEY_METADATA_SIZE);
83c8df26a   Pravin B Shelar   openvswitch: refa...
695
  	/* Extract metadata from netlink attributes. */
05da5898a   Jarno Rajahalme   openvswitch: Add ...
696
  	err = ovs_nla_get_flow_metadata(attr, key, log);
83c8df26a   Pravin B Shelar   openvswitch: refa...
697
698
699
700
701
  	if (err)
  		return err;
  
  	return key_extract(skb, key);
  }