Blame view

net/openvswitch/flow.c 23.9 KB
c94229992   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
ccb1352e7   Jesse Gross   net: Add Open vSw...
2
  /*
971427f35   Andy Zhou   openvswitch: Add ...
3
   * Copyright (c) 2007-2014 Nicira, Inc.
ccb1352e7   Jesse Gross   net: Add Open vSw...
4
   */
ccb1352e7   Jesse Gross   net: Add Open vSw...
5
6
7
8
9
10
11
12
13
14
15
16
17
  #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>
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
18
  #include <linux/cpumask.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
19
  #include <linux/if_arp.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
20
21
  #include <linux/ip.h>
  #include <linux/ipv6.h>
25cd9ba0a   Simon Horman   openvswitch: Add ...
22
  #include <linux/mpls.h>
a175a7233   Joe Stringer   openvswitch: Add ...
23
  #include <linux/sctp.h>
e298e5057   Pravin B Shelar   openvswitch: Per ...
24
  #include <linux/smp.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
25
26
27
28
29
30
  #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 ...
31
  #include <net/ip_tunnels.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
32
  #include <net/ipv6.h>
25cd9ba0a   Simon Horman   openvswitch: Add ...
33
  #include <net/mpls.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
34
  #include <net/ndisc.h>
b2d0f5d5d   Yi Yang   openvswitch: enab...
35
  #include <net/nsh.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
36

a581b96db   Pravin B Shelar   openvswitch: Remo...
37
  #include "conntrack.h"
83c8df26a   Pravin B Shelar   openvswitch: refa...
38
39
40
  #include "datapath.h"
  #include "flow.h"
  #include "flow_netlink.h"
a581b96db   Pravin B Shelar   openvswitch: Remo...
41
  #include "vport.h"
83c8df26a   Pravin B Shelar   openvswitch: refa...
42

e64457191   Pravin B Shelar   openvswitch: Rest...
43
  u64 ovs_flow_used_time(unsigned long flow_jiffies)
03f0d916a   Andy Zhou   openvswitch: Mega...
44
  {
311af51dc   Arnd Bergmann   openvswitch: use ...
45
  	struct timespec64 cur_ts;
e64457191   Pravin B Shelar   openvswitch: Rest...
46
  	u64 cur_ms, idle_ms;
03f0d916a   Andy Zhou   openvswitch: Mega...
47

311af51dc   Arnd Bergmann   openvswitch: use ...
48
  	ktime_get_ts64(&cur_ts);
e64457191   Pravin B Shelar   openvswitch: Rest...
49
  	idle_ms = jiffies_to_msecs(jiffies - flow_jiffies);
311af51dc   Arnd Bergmann   openvswitch: use ...
50
  	cur_ms = (u64)(u32)cur_ts.tv_sec * MSEC_PER_SEC +
e64457191   Pravin B Shelar   openvswitch: Rest...
51
  		 cur_ts.tv_nsec / NSEC_PER_MSEC;
03f0d916a   Andy Zhou   openvswitch: Mega...
52

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

ad5520073   Ben Pfaff   openvswitch: Fix ...
57
  void ovs_flow_stats_update(struct sw_flow *flow, __be16 tcp_flags,
12eb18f71   Thomas Graf   openvswitch: Cons...
58
  			   const struct sk_buff *skb)
03f0d916a   Andy Zhou   openvswitch: Mega...
59
  {
aef833c58   Pablo Neira Ayuso   net: openvswitch:...
60
  	struct sw_flow_stats *stats;
c4b2bf6b4   Tonghao Zhang   openvswitch: Opti...
61
  	unsigned int cpu = smp_processor_id();
df8a39def   Jiri Pirko   net: rename vlan_...
62
  	int len = skb->len + (skb_vlan_tag_present(skb) ? VLAN_HLEN : 0);
03f0d916a   Andy Zhou   openvswitch: Mega...
63

db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
64
  	stats = rcu_dereference(flow->stats[cpu]);
e298e5057   Pravin B Shelar   openvswitch: Per ...
65

db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
66
  	/* Check if already have CPU-specific stats. */
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
67
68
69
  	if (likely(stats)) {
  		spin_lock(&stats->lock);
  		/* Mark if we write on the pre-allocated stats. */
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
70
71
  		if (cpu == 0 && unlikely(flow->stats_last_writer != cpu))
  			flow->stats_last_writer = cpu;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
72
73
74
  	} else {
  		stats = rcu_dereference(flow->stats[0]); /* Pre-allocated. */
  		spin_lock(&stats->lock);
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
75
  		/* If the current CPU is the only writer on the
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
76
77
  		 * pre-allocated stats keep using them.
  		 */
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
78
  		if (unlikely(flow->stats_last_writer != cpu)) {
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
79
  			/* A previous locker may have already allocated the
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
80
  			 * stats, so we need to check again.  If CPU-specific
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
81
82
83
  			 * stats were already allocated, we update the pre-
  			 * allocated stats as we have already locked them.
  			 */
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
84
85
86
  			if (likely(flow->stats_last_writer != -1) &&
  			    likely(!rcu_access_pointer(flow->stats[cpu]))) {
  				/* Try to allocate CPU-specific stats. */
aef833c58   Pablo Neira Ayuso   net: openvswitch:...
87
  				struct sw_flow_stats *new_stats;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
88
89
90
  
  				new_stats =
  					kmem_cache_alloc_node(flow_stats_cache,
4167e9b2c   David Rientjes   mm: remove GFP_TH...
91
92
93
  							      GFP_NOWAIT |
  							      __GFP_THISNODE |
  							      __GFP_NOWARN |
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
94
  							      __GFP_NOMEMALLOC,
c57c054eb   Tonghao Zhang   openvswitch: Opti...
95
  							      numa_node_id());
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
96
97
98
  				if (likely(new_stats)) {
  					new_stats->used = jiffies;
  					new_stats->packet_count = 1;
24cc59d1e   Ben Pfaff   openvswitch: Cons...
99
  					new_stats->byte_count = len;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
100
101
  					new_stats->tcp_flags = tcp_flags;
  					spin_lock_init(&new_stats->lock);
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
102
  					rcu_assign_pointer(flow->stats[cpu],
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
103
  							   new_stats);
c4b2bf6b4   Tonghao Zhang   openvswitch: Opti...
104
  					cpumask_set_cpu(cpu, &flow->cpu_used_mask);
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
105
106
107
  					goto unlock;
  				}
  			}
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
108
  			flow->stats_last_writer = cpu;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
109
110
  		}
  	}
e298e5057   Pravin B Shelar   openvswitch: Per ...
111
112
  	stats->used = jiffies;
  	stats->packet_count++;
24cc59d1e   Ben Pfaff   openvswitch: Cons...
113
  	stats->byte_count += len;
e298e5057   Pravin B Shelar   openvswitch: Per ...
114
  	stats->tcp_flags |= tcp_flags;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
115
  unlock:
e298e5057   Pravin B Shelar   openvswitch: Per ...
116
117
  	spin_unlock(&stats->lock);
  }
86ec8dbae   Jarno Rajahalme   openvswitch: Fix ...
118
119
120
  /* 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 ...
121
122
  			unsigned long *used, __be16 *tcp_flags)
  {
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
123
  	int cpu;
e298e5057   Pravin B Shelar   openvswitch: Per ...
124
125
126
127
  
  	*used = 0;
  	*tcp_flags = 0;
  	memset(ovs_stats, 0, sizeof(*ovs_stats));
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
128
  	/* We open code this to make sure cpu 0 is always considered */
c4b2bf6b4   Tonghao Zhang   openvswitch: Opti...
129
  	for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) {
aef833c58   Pablo Neira Ayuso   net: openvswitch:...
130
  		struct sw_flow_stats *stats = rcu_dereference_ovsl(flow->stats[cpu]);
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
131
132
133
134
135
136
137
138
139
140
141
142
143
  
  		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 ...
144
  	}
e298e5057   Pravin B Shelar   openvswitch: Per ...
145
  }
86ec8dbae   Jarno Rajahalme   openvswitch: Fix ...
146
  /* Called with ovs_mutex. */
e298e5057   Pravin B Shelar   openvswitch: Per ...
147
148
  void ovs_flow_stats_clear(struct sw_flow *flow)
  {
db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
149
  	int cpu;
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
150

db74a3335   Thadeu Lima de Souza Cascardo   openvswitch: use ...
151
  	/* We open code this to make sure cpu 0 is always considered */
c4b2bf6b4   Tonghao Zhang   openvswitch: Opti...
152
  	for (cpu = 0; cpu < nr_cpu_ids; cpu = cpumask_next(cpu, &flow->cpu_used_mask)) {
aef833c58   Pablo Neira Ayuso   net: openvswitch:...
153
  		struct sw_flow_stats *stats = ovsl_dereference(flow->stats[cpu]);
63e7959c4   Jarno Rajahalme   openvswitch: Per ...
154
155
156
157
158
159
160
161
162
163
  
  		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...
164
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
165
166
167
168
169
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
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
  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 ...
220
221
222
223
224
  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...
225
226
227
228
229
  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...
230
  static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
231
  {
fa642f088   Yi-Hung Wei   openvswitch: Deri...
232
233
  	unsigned short frag_off;
  	unsigned int payload_ofs = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
234
235
  	unsigned int nh_ofs = skb_network_offset(skb);
  	unsigned int nh_len;
ccb1352e7   Jesse Gross   net: Add Open vSw...
236
  	struct ipv6hdr *nh;
fa642f088   Yi-Hung Wei   openvswitch: Deri...
237
  	int err, nexthdr, flags = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
238

ccb1352e7   Jesse Gross   net: Add Open vSw...
239
240
241
242
243
  	err = check_header(skb, nh_ofs + sizeof(*nh));
  	if (unlikely(err))
  		return err;
  
  	nh = ipv6_hdr(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
244
245
246
247
248
249
250
  
  	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;
fa642f088   Yi-Hung Wei   openvswitch: Deri...
251
252
  	nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags);
  	if (flags & IP6_FH_F_FRAG) {
41e4e2cd7   Yi-Hung Wei   openvswitch: Fix ...
253
  		if (frag_off) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
254
  			key->ip.frag = OVS_FRAG_TYPE_LATER;
41e4e2cd7   Yi-Hung Wei   openvswitch: Fix ...
255
256
257
258
  			key->ip.proto = nexthdr;
  			return 0;
  		}
  		key->ip.frag = OVS_FRAG_TYPE_FIRST;
25ef1328a   Pravin B Shelar   openvswitch: Set ...
259
260
  	} else {
  		key->ip.frag = OVS_FRAG_TYPE_NONE;
ccb1352e7   Jesse Gross   net: Add Open vSw...
261
  	}
fa642f088   Yi-Hung Wei   openvswitch: Deri...
262
263
  	/* Delayed handling of error in ipv6_find_hdr() as it
  	 * always sets flags and frag_off to a valid value which may be
c30da4978   Simon Horman   openvswitch: reta...
264
265
  	 * used to set key->ip.frag above.
  	 */
fa642f088   Yi-Hung Wei   openvswitch: Deri...
266
  	if (unlikely(nexthdr < 0))
c30da4978   Simon Horman   openvswitch: reta...
267
  		return -EPROTO;
ccb1352e7   Jesse Gross   net: Add Open vSw...
268
269
270
271
272
273
274
275
276
277
278
  	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));
  }
018c1dda5   Eric Garver   openvswitch: 802....
279
280
281
282
283
284
  /**
   * Parse vlan tag from vlan header.
   * Returns ERROR on memory error.
   * Returns 0 if it encounters a non-vlan or incomplete packet.
   * Returns 1 after successfully parsing vlan tag.
   */
df30f7408   pravin shelar   openvswitch: upca...
285
286
  static int parse_vlan_tag(struct sk_buff *skb, struct vlan_head *key_vh,
  			  bool untag_vlan)
ccb1352e7   Jesse Gross   net: Add Open vSw...
287
  {
018c1dda5   Eric Garver   openvswitch: 802....
288
  	struct vlan_head *vh = (struct vlan_head *)skb->data;
ccb1352e7   Jesse Gross   net: Add Open vSw...
289

018c1dda5   Eric Garver   openvswitch: 802....
290
  	if (likely(!eth_type_vlan(vh->tpid)))
ccb1352e7   Jesse Gross   net: Add Open vSw...
291
  		return 0;
018c1dda5   Eric Garver   openvswitch: 802....
292
293
294
295
296
  	if (unlikely(skb->len < sizeof(struct vlan_head) + sizeof(__be16)))
  		return 0;
  
  	if (unlikely(!pskb_may_pull(skb, sizeof(struct vlan_head) +
  				 sizeof(__be16))))
ccb1352e7   Jesse Gross   net: Add Open vSw...
297
  		return -ENOMEM;
018c1dda5   Eric Garver   openvswitch: 802....
298
  	vh = (struct vlan_head *)skb->data;
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
299
  	key_vh->tci = vh->tci | htons(VLAN_CFI_MASK);
018c1dda5   Eric Garver   openvswitch: 802....
300
  	key_vh->tpid = vh->tpid;
df30f7408   pravin shelar   openvswitch: upca...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  	if (unlikely(untag_vlan)) {
  		int offset = skb->data - skb_mac_header(skb);
  		u16 tci;
  		int err;
  
  		__skb_push(skb, offset);
  		err = __skb_vlan_pop(skb, &tci);
  		__skb_pull(skb, offset);
  		if (err)
  			return err;
  		__vlan_hwaccel_put_tag(skb, key_vh->tpid, tci);
  	} else {
  		__skb_pull(skb, sizeof(struct vlan_head));
  	}
018c1dda5   Eric Garver   openvswitch: 802....
315
316
  	return 1;
  }
5108bbadd   Jiri Benc   openvswitch: add ...
317
  static void clear_vlan(struct sw_flow_key *key)
018c1dda5   Eric Garver   openvswitch: 802....
318
  {
018c1dda5   Eric Garver   openvswitch: 802....
319
320
321
322
  	key->eth.vlan.tci = 0;
  	key->eth.vlan.tpid = 0;
  	key->eth.cvlan.tci = 0;
  	key->eth.cvlan.tpid = 0;
5108bbadd   Jiri Benc   openvswitch: add ...
323
324
325
326
327
  }
  
  static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key)
  {
  	int res;
018c1dda5   Eric Garver   openvswitch: 802....
328

20ecf1e4e   Jiri Benc   openvswitch: vlan...
329
  	if (skb_vlan_tag_present(skb)) {
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
330
  		key->eth.vlan.tci = htons(skb->vlan_tci) | htons(VLAN_CFI_MASK);
018c1dda5   Eric Garver   openvswitch: 802....
331
332
333
  		key->eth.vlan.tpid = skb->vlan_proto;
  	} else {
  		/* Parse outer vlan tag in the non-accelerated case. */
df30f7408   pravin shelar   openvswitch: upca...
334
  		res = parse_vlan_tag(skb, &key->eth.vlan, true);
018c1dda5   Eric Garver   openvswitch: 802....
335
336
337
338
339
  		if (res <= 0)
  			return res;
  	}
  
  	/* Parse inner vlan tag. */
df30f7408   pravin shelar   openvswitch: upca...
340
  	res = parse_vlan_tag(skb, &key->eth.cvlan, false);
018c1dda5   Eric Garver   openvswitch: 802....
341
342
  	if (res <= 0)
  		return res;
ccb1352e7   Jesse Gross   net: Add Open vSw...
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  
  	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));
6713fc9b8   Alexander Duyck   openvswitch: Use ...
361
  	if (eth_proto_is_802_3(proto))
ccb1352e7   Jesse Gross   net: Add Open vSw...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  		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 ...
377

6713fc9b8   Alexander Duyck   openvswitch: Use ...
378
  	if (eth_proto_is_802_3(llc->ethertype))
17b682a04   Rich Lane   openvswitch: Fix ...
379
380
381
  		return llc->ethertype;
  
  	return htons(ETH_P_802_2);
ccb1352e7   Jesse Gross   net: Add Open vSw...
382
383
384
  }
  
  static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
03f0d916a   Andy Zhou   openvswitch: Mega...
385
  			int nh_len)
ccb1352e7   Jesse Gross   net: Add Open vSw...
386
387
  {
  	struct icmp6hdr *icmp = icmp6_hdr(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
388
389
390
391
  
  	/* 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...
392
393
  	key->tp.src = htons(icmp->icmp6_type);
  	key->tp.dst = htons(icmp->icmp6_code);
25ef1328a   Pravin B Shelar   openvswitch: Set ...
394
  	memset(&key->ipv6.nd, 0, sizeof(key->ipv6.nd));
ccb1352e7   Jesse Gross   net: Add Open vSw...
395
396
397
398
399
400
401
  
  	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...
402
403
404
405
  		/* In order to process neighbor discovery options, we need the
  		 * entire packet.
  		 */
  		if (unlikely(icmp_len < sizeof(*nd)))
03f0d916a   Andy Zhou   openvswitch: Mega...
406
407
408
409
  			return 0;
  
  		if (unlikely(skb_linearize(skb)))
  			return -ENOMEM;
ccb1352e7   Jesse Gross   net: Add Open vSw...
410
411
412
  
  		nd = (struct nd_msg *)skb_transport_header(skb);
  		key->ipv6.nd.target = nd->target;
ccb1352e7   Jesse Gross   net: Add Open vSw...
413
414
415
416
417
418
419
420
421
  
  		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...
422
  				return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
423
424
425
426
427
428
429
430
431
  
  			/* 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 ...
432
433
  				ether_addr_copy(key->ipv6.nd.sll,
  						&nd->opt[offset+sizeof(*nd_opt)]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
434
435
436
437
  			} 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 ...
438
439
  				ether_addr_copy(key->ipv6.nd.tll,
  						&nd->opt[offset+sizeof(*nd_opt)]);
ccb1352e7   Jesse Gross   net: Add Open vSw...
440
441
442
443
444
445
  			}
  
  			icmp_len -= opt_len;
  			offset += opt_len;
  		}
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
446
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
447
448
449
450
451
  
  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...
452
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
453
  }
b2d0f5d5d   Yi Yang   openvswitch: enab...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
  static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
  {
  	struct nshhdr *nh;
  	unsigned int nh_ofs = skb_network_offset(skb);
  	u8 version, length;
  	int err;
  
  	err = check_header(skb, nh_ofs + NSH_BASE_HDR_LEN);
  	if (unlikely(err))
  		return err;
  
  	nh = nsh_hdr(skb);
  	version = nsh_get_ver(nh);
  	length = nsh_hdr_len(nh);
  
  	if (version != 0)
  		return -EINVAL;
  
  	err = check_header(skb, nh_ofs + length);
  	if (unlikely(err))
  		return err;
  
  	nh = nsh_hdr(skb);
  	key->nsh.base.flags = nsh_get_flags(nh);
  	key->nsh.base.ttl = nsh_get_ttl(nh);
  	key->nsh.base.mdtype = nh->mdtype;
  	key->nsh.base.np = nh->np;
  	key->nsh.base.path_hdr = nh->path_hdr;
  	switch (key->nsh.base.mdtype) {
  	case NSH_M_TYPE1:
  		if (length != NSH_M_TYPE1_LEN)
  			return -EINVAL;
  		memcpy(key->nsh.context, nh->md1.context,
  		       sizeof(nh->md1));
  		break;
  	case NSH_M_TYPE2:
  		memset(key->nsh.context, 0,
  		       sizeof(nh->md1));
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return 0;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
499
  /**
ad06a566e   Greg Rose   openvswitch: Prop...
500
   * key_extract_l3l4 - extracts L3/L4 header information.
ccb1352e7   Jesse Gross   net: Add Open vSw...
501
   * @skb: sk_buff that contains the frame, with skb->data pointing to the
ad06a566e   Greg Rose   openvswitch: Prop...
502
   *       L3 header
ccb1352e7   Jesse Gross   net: Add Open vSw...
503
   * @key: output flow key
ccb1352e7   Jesse Gross   net: Add Open vSw...
504
   *
ccb1352e7   Jesse Gross   net: Add Open vSw...
505
   */
ad06a566e   Greg Rose   openvswitch: Prop...
506
  static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
507
  {
03f0d916a   Andy Zhou   openvswitch: Mega...
508
  	int error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
509
510
511
512
513
  
  	/* Network layer. */
  	if (key->eth.type == htons(ETH_P_IP)) {
  		struct iphdr *nh;
  		__be16 offset;
ccb1352e7   Jesse Gross   net: Add Open vSw...
514
515
  		error = check_iphdr(skb);
  		if (unlikely(error)) {
071481213   Jesse Gross   openvswitch: Elim...
516
517
  			memset(&key->ip, 0, sizeof(key->ip));
  			memset(&key->ipv4, 0, sizeof(key->ipv4));
ccb1352e7   Jesse Gross   net: Add Open vSw...
518
519
520
521
  			if (error == -EINVAL) {
  				skb->transport_header = skb->network_header;
  				error = 0;
  			}
03f0d916a   Andy Zhou   openvswitch: Mega...
522
  			return error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
523
524
525
526
527
528
529
530
531
532
533
534
535
  		}
  
  		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;
0754b4e8c   Justin Pettit   openvswitch: Clea...
536
  			memset(&key->tp, 0, sizeof(key->tp));
03f0d916a   Andy Zhou   openvswitch: Mega...
537
  			return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
538
  		}
0c19f846d   Willem de Bruijn   net: accept UFO d...
539
540
  		if (nh->frag_off & htons(IP_MF) ||
  			skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
ccb1352e7   Jesse Gross   net: Add Open vSw...
541
  			key->ip.frag = OVS_FRAG_TYPE_FIRST;
071481213   Jesse Gross   openvswitch: Elim...
542
543
  		else
  			key->ip.frag = OVS_FRAG_TYPE_NONE;
ccb1352e7   Jesse Gross   net: Add Open vSw...
544
545
546
  
  		/* Transport layer. */
  		if (key->ip.proto == IPPROTO_TCP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
547
548
  			if (tcphdr_ok(skb)) {
  				struct tcphdr *tcp = tcp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
549
550
551
  				key->tp.src = tcp->source;
  				key->tp.dst = tcp->dest;
  				key->tp.flags = TCP_FLAGS_BE16(tcp);
071481213   Jesse Gross   openvswitch: Elim...
552
553
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
554
  			}
071481213   Jesse Gross   openvswitch: Elim...
555

ccb1352e7   Jesse Gross   net: Add Open vSw...
556
  		} else if (key->ip.proto == IPPROTO_UDP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
557
558
  			if (udphdr_ok(skb)) {
  				struct udphdr *udp = udp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
559
560
  				key->tp.src = udp->source;
  				key->tp.dst = udp->dest;
071481213   Jesse Gross   openvswitch: Elim...
561
562
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
563
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
564
565
566
  		} else if (key->ip.proto == IPPROTO_SCTP) {
  			if (sctphdr_ok(skb)) {
  				struct sctphdr *sctp = sctp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
567
568
  				key->tp.src = sctp->source;
  				key->tp.dst = sctp->dest;
071481213   Jesse Gross   openvswitch: Elim...
569
570
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
a175a7233   Joe Stringer   openvswitch: Add ...
571
  			}
ccb1352e7   Jesse Gross   net: Add Open vSw...
572
  		} else if (key->ip.proto == IPPROTO_ICMP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
573
574
575
576
577
  			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...
578
579
  				key->tp.src = htons(icmp->type);
  				key->tp.dst = htons(icmp->code);
071481213   Jesse Gross   openvswitch: Elim...
580
581
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
582
583
  			}
  		}
071481213   Jesse Gross   openvswitch: Elim...
584
585
  	} else if (key->eth.type == htons(ETH_P_ARP) ||
  		   key->eth.type == htons(ETH_P_RARP)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
586
  		struct arp_eth_header *arp;
389f48947   Li RongQing   openvswitch: fix ...
587
  		bool arp_available = arphdr_ok(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
588
589
  
  		arp = (struct arp_eth_header *)skb_network_header(skb);
389f48947   Li RongQing   openvswitch: fix ...
590
  		if (arp_available &&
071481213   Jesse Gross   openvswitch: Elim...
591
592
593
594
  		    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...
595
596
597
598
  
  			/* 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...
599
600
  			else
  				key->ip.proto = 0;
d04d38298   Mehak Mahajan   openvswitch: Stor...
601
602
  			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 ...
603
604
  			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...
605
606
607
  		} else {
  			memset(&key->ip, 0, sizeof(key->ip));
  			memset(&key->ipv4, 0, sizeof(key->ipv4));
ccb1352e7   Jesse Gross   net: Add Open vSw...
608
  		}
25cd9ba0a   Simon Horman   openvswitch: Add ...
609
  	} else if (eth_p_mpls(key->eth.type)) {
fbdcdd78d   Martin Varghese   Change in Openvsw...
610
  		u8 label_count = 1;
25cd9ba0a   Simon Horman   openvswitch: Add ...
611

fbdcdd78d   Martin Varghese   Change in Openvsw...
612
  		memset(&key->mpls, 0, sizeof(key->mpls));
f7d49bce8   Jiri Benc   openvswitch: mpls...
613
  		skb_set_inner_network_header(skb, skb->mac_len);
25cd9ba0a   Simon Horman   openvswitch: Add ...
614
615
  		while (1) {
  			__be32 lse;
fbdcdd78d   Martin Varghese   Change in Openvsw...
616
617
  			error = check_header(skb, skb->mac_len +
  					     label_count * MPLS_HLEN);
25cd9ba0a   Simon Horman   openvswitch: Add ...
618
619
  			if (unlikely(error))
  				return 0;
f7d49bce8   Jiri Benc   openvswitch: mpls...
620
  			memcpy(&lse, skb_inner_network_header(skb), MPLS_HLEN);
25cd9ba0a   Simon Horman   openvswitch: Add ...
621

fbdcdd78d   Martin Varghese   Change in Openvsw...
622
623
624
  			if (label_count <= MPLS_LABEL_DEPTH)
  				memcpy(&key->mpls.lse[label_count - 1], &lse,
  				       MPLS_HLEN);
25cd9ba0a   Simon Horman   openvswitch: Add ...
625

fbdcdd78d   Martin Varghese   Change in Openvsw...
626
627
  			skb_set_inner_network_header(skb, skb->mac_len +
  						     label_count * MPLS_HLEN);
25cd9ba0a   Simon Horman   openvswitch: Add ...
628
629
  			if (lse & htonl(MPLS_LS_S_MASK))
  				break;
fbdcdd78d   Martin Varghese   Change in Openvsw...
630
  			label_count++;
25cd9ba0a   Simon Horman   openvswitch: Add ...
631
  		}
fbdcdd78d   Martin Varghese   Change in Openvsw...
632
633
634
635
  		if (label_count > MPLS_LABEL_DEPTH)
  			label_count = MPLS_LABEL_DEPTH;
  
  		key->mpls.num_labels_mask = GENMASK(label_count - 1, 0);
ccb1352e7   Jesse Gross   net: Add Open vSw...
636
637
  	} else if (key->eth.type == htons(ETH_P_IPV6)) {
  		int nh_len;             /* IPv6 Header + Extensions */
03f0d916a   Andy Zhou   openvswitch: Mega...
638
  		nh_len = parse_ipv6hdr(skb, key);
ccb1352e7   Jesse Gross   net: Add Open vSw...
639
  		if (unlikely(nh_len < 0)) {
c30da4978   Simon Horman   openvswitch: reta...
640
641
642
643
  			switch (nh_len) {
  			case -EINVAL:
  				memset(&key->ip, 0, sizeof(key->ip));
  				memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr));
df561f668   Gustavo A. R. Silva   treewide: Use fal...
644
  				fallthrough;
c30da4978   Simon Horman   openvswitch: reta...
645
  			case -EPROTO:
ccb1352e7   Jesse Gross   net: Add Open vSw...
646
  				skb->transport_header = skb->network_header;
03f0d916a   Andy Zhou   openvswitch: Mega...
647
  				error = 0;
c30da4978   Simon Horman   openvswitch: reta...
648
649
  				break;
  			default:
ccb1352e7   Jesse Gross   net: Add Open vSw...
650
  				error = nh_len;
03f0d916a   Andy Zhou   openvswitch: Mega...
651
652
  			}
  			return error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
653
  		}
0754b4e8c   Justin Pettit   openvswitch: Clea...
654
655
  		if (key->ip.frag == OVS_FRAG_TYPE_LATER) {
  			memset(&key->tp, 0, sizeof(key->tp));
03f0d916a   Andy Zhou   openvswitch: Mega...
656
  			return 0;
0754b4e8c   Justin Pettit   openvswitch: Clea...
657
  		}
0c19f846d   Willem de Bruijn   net: accept UFO d...
658
659
  		if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
  			key->ip.frag = OVS_FRAG_TYPE_FIRST;
ccb1352e7   Jesse Gross   net: Add Open vSw...
660
661
  		/* Transport layer. */
  		if (key->ip.proto == NEXTHDR_TCP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
662
663
  			if (tcphdr_ok(skb)) {
  				struct tcphdr *tcp = tcp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
664
665
666
  				key->tp.src = tcp->source;
  				key->tp.dst = tcp->dest;
  				key->tp.flags = TCP_FLAGS_BE16(tcp);
071481213   Jesse Gross   openvswitch: Elim...
667
668
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
669
670
  			}
  		} else if (key->ip.proto == NEXTHDR_UDP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
671
672
  			if (udphdr_ok(skb)) {
  				struct udphdr *udp = udp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
673
674
  				key->tp.src = udp->source;
  				key->tp.dst = udp->dest;
071481213   Jesse Gross   openvswitch: Elim...
675
676
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
677
  			}
a175a7233   Joe Stringer   openvswitch: Add ...
678
679
680
  		} else if (key->ip.proto == NEXTHDR_SCTP) {
  			if (sctphdr_ok(skb)) {
  				struct sctphdr *sctp = sctp_hdr(skb);
1139e241e   Jarno Rajahalme   openvswitch: Comp...
681
682
  				key->tp.src = sctp->source;
  				key->tp.dst = sctp->dest;
071481213   Jesse Gross   openvswitch: Elim...
683
684
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
a175a7233   Joe Stringer   openvswitch: Add ...
685
  			}
ccb1352e7   Jesse Gross   net: Add Open vSw...
686
  		} else if (key->ip.proto == NEXTHDR_ICMP) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
687
  			if (icmp6hdr_ok(skb)) {
03f0d916a   Andy Zhou   openvswitch: Mega...
688
689
690
  				error = parse_icmpv6(skb, key, nh_len);
  				if (error)
  					return error;
071481213   Jesse Gross   openvswitch: Elim...
691
692
  			} else {
  				memset(&key->tp, 0, sizeof(key->tp));
ccb1352e7   Jesse Gross   net: Add Open vSw...
693
694
  			}
  		}
b2d0f5d5d   Yi Yang   openvswitch: enab...
695
696
697
698
  	} else if (key->eth.type == htons(ETH_P_NSH)) {
  		error = parse_nsh(skb, key);
  		if (error)
  			return error;
ccb1352e7   Jesse Gross   net: Add Open vSw...
699
  	}
03f0d916a   Andy Zhou   openvswitch: Mega...
700
  	return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
701
  }
83c8df26a   Pravin B Shelar   openvswitch: refa...
702

ad06a566e   Greg Rose   openvswitch: Prop...
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
  /**
   * key_extract - extracts a flow key from an Ethernet frame.
   * @skb: sk_buff that contains the frame, with skb->data pointing to the
   * Ethernet header
   * @key: output flow key
   *
   * The caller must ensure that skb->len >= ETH_HLEN.
   *
   * Returns 0 if successful, otherwise a negative errno value.
   *
   * Initializes @skb header fields as follows:
   *
   *    - skb->mac_header: the L2 header.
   *
   *    - skb->network_header: just past the L2 header, or just past the
   *      VLAN header, to the first byte of the L2 payload.
   *
   *    - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6
   *      on output, then just past the IP header, if one is present and
   *      of a correct length, otherwise the same as skb->network_header.
   *      For other key->eth.type values it is left untouched.
   *
   *    - skb->protocol: the type of the data starting at skb->network_header.
   *      Equals to key->eth.type.
   */
  static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
  {
  	struct ethhdr *eth;
  
  	/* Flags are always used as part of stats */
  	key->tp.flags = 0;
  
  	skb_reset_mac_header(skb);
  
  	/* Link layer. */
  	clear_vlan(key);
  	if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) {
  		if (unlikely(eth_type_vlan(skb->protocol)))
  			return -EINVAL;
  
  		skb_reset_network_header(skb);
  		key->eth.type = skb->protocol;
  	} else {
  		eth = eth_hdr(skb);
  		ether_addr_copy(key->eth.src, eth->h_source);
  		ether_addr_copy(key->eth.dst, eth->h_dest);
  
  		__skb_pull(skb, 2 * ETH_ALEN);
  		/* We are going to push all headers that we pull, so no need to
  		 * update skb->csum here.
  		 */
  
  		if (unlikely(parse_vlan(skb, key)))
  			return -ENOMEM;
  
  		key->eth.type = parse_ethertype(skb);
  		if (unlikely(key->eth.type == htons(0)))
  			return -ENOMEM;
  
  		/* Multiple tagged packets need to retain TPID to satisfy
  		 * skb_vlan_pop(), which will later shift the ethertype into
  		 * skb->protocol.
  		 */
  		if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK))
  			skb->protocol = key->eth.cvlan.tpid;
  		else
  			skb->protocol = key->eth.type;
  
  		skb_reset_network_header(skb);
  		__skb_push(skb, skb->data - skb_mac_header(skb));
  	}
  
  	skb_reset_mac_len(skb);
  
  	/* Fill out L3/L4 key info, if any */
  	return key_extract_l3l4(skb, key);
  }
  
  /* In the case of conntrack fragment handling it expects L3 headers,
   * add a helper.
   */
  int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
  {
  	return key_extract_l3l4(skb, key);
  }
971427f35   Andy Zhou   openvswitch: Add ...
788
789
  int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
  {
6f56f6186   Yi-Hung Wei   openvswitch: Fix ...
790
791
792
793
794
795
796
  	int res;
  
  	res = key_extract(skb, key);
  	if (!res)
  		key->mac_proto &= ~SW_FLOW_KEY_INVALID;
  
  	return res;
971427f35   Andy Zhou   openvswitch: Add ...
797
  }
5108bbadd   Jiri Benc   openvswitch: add ...
798
799
800
801
802
803
804
805
806
807
808
809
810
  static int key_extract_mac_proto(struct sk_buff *skb)
  {
  	switch (skb->dev->type) {
  	case ARPHRD_ETHER:
  		return MAC_PROTO_ETHERNET;
  	case ARPHRD_NONE:
  		if (skb->protocol == htons(ETH_P_TEB))
  			return MAC_PROTO_ETHERNET;
  		return MAC_PROTO_NONE;
  	}
  	WARN_ON_ONCE(1);
  	return -EINVAL;
  }
1d8fff907   Thomas Graf   ip_tunnel: Make o...
811
  int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
8c8b1b83f   Pravin B Shelar   openvswitch: Use ...
812
  			 struct sk_buff *skb, struct sw_flow_key *key)
83c8df26a   Pravin B Shelar   openvswitch: refa...
813
  {
95a7233c4   Paul Blakey   net: openvswitch:...
814
815
816
  #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
  	struct tc_skb_ext *tc_ext;
  #endif
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
817
  	int res, err;
5108bbadd   Jiri Benc   openvswitch: add ...
818

83c8df26a   Pravin B Shelar   openvswitch: refa...
819
  	/* Extract metadata from packet. */
f57966840   Jesse Gross   openvswitch: Add ...
820
  	if (tun_info) {
00a93babd   Jiri Benc   openvswitch: add ...
821
  		key->tun_proto = ip_tunnel_info_af(tun_info);
1d8fff907   Thomas Graf   ip_tunnel: Make o...
822
  		memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key));
f57966840   Jesse Gross   openvswitch: Add ...
823

4c2227984   Pravin B Shelar   ip-tunnel: Use AP...
824
  		if (tun_info->options_len) {
f57966840   Jesse Gross   openvswitch: Add ...
825
826
827
  			BUILD_BUG_ON((1 << (sizeof(tun_info->options_len) *
  						   8)) - 1
  					> sizeof(key->tun_opts));
4c2227984   Pravin B Shelar   ip-tunnel: Use AP...
828
829
830
  
  			ip_tunnel_info_opts_get(TUN_METADATA_OPTS(key, tun_info->options_len),
  						tun_info);
f57966840   Jesse Gross   openvswitch: Add ...
831
832
833
834
835
  			key->tun_opts_len = tun_info->options_len;
  		} else {
  			key->tun_opts_len = 0;
  		}
  	} else  {
00a93babd   Jiri Benc   openvswitch: add ...
836
  		key->tun_proto = 0;
f57966840   Jesse Gross   openvswitch: Add ...
837
  		key->tun_opts_len = 0;
071481213   Jesse Gross   openvswitch: Elim...
838
  		memset(&key->tun_key, 0, sizeof(key->tun_key));
f57966840   Jesse Gross   openvswitch: Add ...
839
  	}
83c8df26a   Pravin B Shelar   openvswitch: refa...
840
841
842
843
  
  	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...
844
  	key->ovs_flow_hash = 0;
5108bbadd   Jiri Benc   openvswitch: add ...
845
846
847
848
  	res = key_extract_mac_proto(skb);
  	if (res < 0)
  		return res;
  	key->mac_proto = res;
95a7233c4   Paul Blakey   net: openvswitch:...
849
850
851
852
853
  
  #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
  	if (static_branch_unlikely(&tc_recirc_sharing_support)) {
  		tc_ext = skb_ext_find(skb, TC_SKB_EXT);
  		key->recirc_id = tc_ext ? tc_ext->chain : 0;
038ebb1a7   wenxu   net/sched: act_ct...
854
  		OVS_CB(skb)->mru = tc_ext ? tc_ext->mru : 0;
95a7233c4   Paul Blakey   net: openvswitch:...
855
856
857
858
  	} else {
  		key->recirc_id = 0;
  	}
  #else
071481213   Jesse Gross   openvswitch: Elim...
859
  	key->recirc_id = 0;
95a7233c4   Paul Blakey   net: openvswitch:...
860
  #endif
071481213   Jesse Gross   openvswitch: Elim...
861

9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
862
863
864
865
  	err = key_extract(skb, key);
  	if (!err)
  		ovs_ct_fill_key(skb, key);   /* Must be after key_extract(). */
  	return err;
83c8df26a   Pravin B Shelar   openvswitch: refa...
866
  }
c2ac66735   Joe Stringer   openvswitch: Allo...
867
  int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
83c8df26a   Pravin B Shelar   openvswitch: refa...
868
  				   struct sk_buff *skb,
05da5898a   Jarno Rajahalme   openvswitch: Add ...
869
  				   struct sw_flow_key *key, bool log)
83c8df26a   Pravin B Shelar   openvswitch: refa...
870
  {
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
871
872
  	const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
  	u64 attrs = 0;
83c8df26a   Pravin B Shelar   openvswitch: refa...
873
  	int err;
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
874
875
876
  	err = parse_flow_nlattrs(attr, a, &attrs, log);
  	if (err)
  		return -EINVAL;
83c8df26a   Pravin B Shelar   openvswitch: refa...
877
  	/* Extract metadata from netlink attributes. */
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
878
  	err = ovs_nla_get_flow_metadata(net, a, attrs, key, log);
83c8df26a   Pravin B Shelar   openvswitch: refa...
879
880
  	if (err)
  		return err;
df30f7408   pravin shelar   openvswitch: upca...
881
882
883
884
885
886
887
888
  	/* key_extract assumes that skb->protocol is set-up for
  	 * layer 3 packets which is the case for other callers,
  	 * in particular packets received from the network stack.
  	 * Here the correct value can be set from the metadata
  	 * extracted above.
  	 * For L2 packet key eth type would be zero. skb protocol
  	 * would be set to correct value later during key-extact.
  	 */
5108bbadd   Jiri Benc   openvswitch: add ...
889

df30f7408   pravin shelar   openvswitch: upca...
890
  	skb->protocol = key->eth.type;
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
  	err = key_extract(skb, key);
  	if (err)
  		return err;
  
  	/* Check that we have conntrack original direction tuple metadata only
  	 * for packets for which it makes sense.  Otherwise the key may be
  	 * corrupted due to overlapping key fields.
  	 */
  	if (attrs & (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4) &&
  	    key->eth.type != htons(ETH_P_IP))
  		return -EINVAL;
  	if (attrs & (1 << OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6) &&
  	    (key->eth.type != htons(ETH_P_IPV6) ||
  	     sw_flow_key_is_nd(key)))
  		return -EINVAL;
  
  	return 0;
83c8df26a   Pravin B Shelar   openvswitch: refa...
908
  }