Blame view

net/openvswitch/actions.c 38.5 KB
c94229992   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
ccb1352e7   Jesse Gross   net: Add Open vSw...
2
  /*
4572ef52a   andy zhou   openvswitch: Refa...
3
   * Copyright (c) 2007-2017 Nicira, Inc.
ccb1352e7   Jesse Gross   net: Add Open vSw...
4
5
6
7
8
9
10
11
   */
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/skbuff.h>
  #include <linux/in.h>
  #include <linux/ip.h>
  #include <linux/openvswitch.h>
a175a7233   Joe Stringer   openvswitch: Add ...
12
  #include <linux/sctp.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
13
14
15
16
17
  #include <linux/tcp.h>
  #include <linux/udp.h>
  #include <linux/in6.h>
  #include <linux/if_arp.h>
  #include <linux/if_vlan.h>
25cd9ba0a   Simon Horman   openvswitch: Add ...
18

7f8a436ea   Joe Stringer   openvswitch: Add ...
19
  #include <net/dst.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
20
  #include <net/ip.h>
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
21
  #include <net/ipv6.h>
7b85b4dff   Joe Stringer   openvswitch: Incl...
22
  #include <net/ip6_fib.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
23
24
  #include <net/checksum.h>
  #include <net/dsfield.h>
25cd9ba0a   Simon Horman   openvswitch: Add ...
25
  #include <net/mpls.h>
a175a7233   Joe Stringer   openvswitch: Add ...
26
  #include <net/sctp/checksum.h>
ccb1352e7   Jesse Gross   net: Add Open vSw...
27
28
  
  #include "datapath.h"
971427f35   Andy Zhou   openvswitch: Add ...
29
  #include "flow.h"
7f8a436ea   Joe Stringer   openvswitch: Add ...
30
  #include "conntrack.h"
ccb1352e7   Jesse Gross   net: Add Open vSw...
31
  #include "vport.h"
b2d0f5d5d   Yi Yang   openvswitch: enab...
32
  #include "flow_netlink.h"
ccb1352e7   Jesse Gross   net: Add Open vSw...
33

971427f35   Andy Zhou   openvswitch: Add ...
34
35
36
  struct deferred_action {
  	struct sk_buff *skb;
  	const struct nlattr *actions;
47c697aa2   andy zhou   openvswitch: Defe...
37
  	int actions_len;
971427f35   Andy Zhou   openvswitch: Add ...
38
39
40
41
  
  	/* Store pkt_key clone when creating deferred action. */
  	struct sw_flow_key pkt_key;
  };
7f8a436ea   Joe Stringer   openvswitch: Add ...
42
43
44
45
46
47
  #define MAX_L2_LEN	(VLAN_ETH_HLEN + 3 * MPLS_HLEN)
  struct ovs_frag_data {
  	unsigned long dst;
  	struct vport *vport;
  	struct ovs_skb_cb cb;
  	__be16 inner_protocol;
c66549ffd   Jiri Benc   openvswitch: corr...
48
49
  	u16 network_offset;	/* valid only for MPLS */
  	u16 vlan_tci;
7f8a436ea   Joe Stringer   openvswitch: Add ...
50
51
  	__be16 vlan_proto;
  	unsigned int l2_len;
e2d9d8358   Jiri Benc   openvswitch: pass...
52
  	u8 mac_proto;
7f8a436ea   Joe Stringer   openvswitch: Add ...
53
54
55
56
  	u8 l2_data[MAX_L2_LEN];
  };
  
  static DEFINE_PER_CPU(struct ovs_frag_data, ovs_frag_data_storage);
971427f35   Andy Zhou   openvswitch: Add ...
57
  #define DEFERRED_ACTION_FIFO_SIZE 10
2679d0404   Lance Richardson   openvswitch: avoi...
58
59
  #define OVS_RECURSION_LIMIT 5
  #define OVS_DEFERRED_ACTION_THRESHOLD (OVS_RECURSION_LIMIT - 2)
971427f35   Andy Zhou   openvswitch: Add ...
60
61
62
63
64
65
  struct action_fifo {
  	int head;
  	int tail;
  	/* Deferred action fifo queue storage. */
  	struct deferred_action fifo[DEFERRED_ACTION_FIFO_SIZE];
  };
4572ef52a   andy zhou   openvswitch: Refa...
66
  struct action_flow_keys {
2679d0404   Lance Richardson   openvswitch: avoi...
67
68
  	struct sw_flow_key key[OVS_DEFERRED_ACTION_THRESHOLD];
  };
971427f35   Andy Zhou   openvswitch: Add ...
69
  static struct action_fifo __percpu *action_fifos;
4572ef52a   andy zhou   openvswitch: Refa...
70
  static struct action_flow_keys __percpu *flow_keys;
971427f35   Andy Zhou   openvswitch: Add ...
71
  static DEFINE_PER_CPU(int, exec_actions_level);
4572ef52a   andy zhou   openvswitch: Refa...
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  /* Make a clone of the 'key', using the pre-allocated percpu 'flow_keys'
   * space. Return NULL if out of key spaces.
   */
  static struct sw_flow_key *clone_key(const struct sw_flow_key *key_)
  {
  	struct action_flow_keys *keys = this_cpu_ptr(flow_keys);
  	int level = this_cpu_read(exec_actions_level);
  	struct sw_flow_key *key = NULL;
  
  	if (level <= OVS_DEFERRED_ACTION_THRESHOLD) {
  		key = &keys->key[level - 1];
  		*key = *key_;
  	}
  
  	return key;
  }
971427f35   Andy Zhou   openvswitch: Add ...
88
89
90
91
92
  static void action_fifo_init(struct action_fifo *fifo)
  {
  	fifo->head = 0;
  	fifo->tail = 0;
  }
12eb18f71   Thomas Graf   openvswitch: Cons...
93
  static bool action_fifo_is_empty(const struct action_fifo *fifo)
971427f35   Andy Zhou   openvswitch: Add ...
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  {
  	return (fifo->head == fifo->tail);
  }
  
  static struct deferred_action *action_fifo_get(struct action_fifo *fifo)
  {
  	if (action_fifo_is_empty(fifo))
  		return NULL;
  
  	return &fifo->fifo[fifo->tail++];
  }
  
  static struct deferred_action *action_fifo_put(struct action_fifo *fifo)
  {
  	if (fifo->head >= DEFERRED_ACTION_FIFO_SIZE - 1)
  		return NULL;
  
  	return &fifo->fifo[fifo->head++];
  }
  
  /* Return true if fifo is not full */
  static struct deferred_action *add_deferred_actions(struct sk_buff *skb,
47c697aa2   andy zhou   openvswitch: Defe...
116
117
118
  				    const struct sw_flow_key *key,
  				    const struct nlattr *actions,
  				    const int actions_len)
971427f35   Andy Zhou   openvswitch: Add ...
119
120
121
122
123
124
125
126
  {
  	struct action_fifo *fifo;
  	struct deferred_action *da;
  
  	fifo = this_cpu_ptr(action_fifos);
  	da = action_fifo_put(fifo);
  	if (da) {
  		da->skb = skb;
47c697aa2   andy zhou   openvswitch: Defe...
127
128
  		da->actions = actions;
  		da->actions_len = actions_len;
971427f35   Andy Zhou   openvswitch: Add ...
129
130
131
132
133
  		da->pkt_key = *key;
  	}
  
  	return da;
  }
fff06c36a   Pravin B Shelar   openvswitch: Opti...
134
135
  static void invalidate_flow_key(struct sw_flow_key *key)
  {
329f45bc4   Jiri Benc   openvswitch: add ...
136
  	key->mac_proto |= SW_FLOW_KEY_INVALID;
fff06c36a   Pravin B Shelar   openvswitch: Opti...
137
138
139
140
  }
  
  static bool is_flow_key_valid(const struct sw_flow_key *key)
  {
329f45bc4   Jiri Benc   openvswitch: add ...
141
  	return !(key->mac_proto & SW_FLOW_KEY_INVALID);
fff06c36a   Pravin B Shelar   openvswitch: Opti...
142
  }
bef7f7567   andy zhou   Openvswitch: Refa...
143
144
145
146
147
  static int clone_execute(struct datapath *dp, struct sk_buff *skb,
  			 struct sw_flow_key *key,
  			 u32 recirc_id,
  			 const struct nlattr *actions, int len,
  			 bool last, bool clone_flow_key);
4d5ec89fc   Numan Siddique   net: openvswitch:...
148
149
150
  static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
  			      struct sw_flow_key *key,
  			      const struct nlattr *attr, int len);
fff06c36a   Pravin B Shelar   openvswitch: Opti...
151
  static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
f66b53fdb   Martin Varghese   openvswitch: New ...
152
  		     __be32 mpls_lse, __be16 mpls_ethertype, __u16 mac_len)
25cd9ba0a   Simon Horman   openvswitch: Add ...
153
  {
8822e270d   John Hurley   net: core: move p...
154
  	int err;
25cd9ba0a   Simon Horman   openvswitch: Add ...
155

f66b53fdb   Martin Varghese   openvswitch: New ...
156
  	err = skb_mpls_push(skb, mpls_lse, mpls_ethertype, mac_len, !!mac_len);
8822e270d   John Hurley   net: core: move p...
157
158
  	if (err)
  		return err;
25cd9ba0a   Simon Horman   openvswitch: Add ...
159

f66b53fdb   Martin Varghese   openvswitch: New ...
160
161
  	if (!mac_len)
  		key->mac_proto = MAC_PROTO_NONE;
fff06c36a   Pravin B Shelar   openvswitch: Opti...
162
  	invalidate_flow_key(key);
25cd9ba0a   Simon Horman   openvswitch: Add ...
163
164
  	return 0;
  }
fff06c36a   Pravin B Shelar   openvswitch: Opti...
165
166
  static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
  		    const __be16 ethertype)
25cd9ba0a   Simon Horman   openvswitch: Add ...
167
  {
25cd9ba0a   Simon Horman   openvswitch: Add ...
168
  	int err;
040b5cfbc   Martin Varghese   Fixed updating of...
169
170
  	err = skb_mpls_pop(skb, ethertype, skb->mac_len,
  			   ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET);
ed246cee0   John Hurley   net: core: move p...
171
  	if (err)
25cd9ba0a   Simon Horman   openvswitch: Add ...
172
  		return err;
f66b53fdb   Martin Varghese   openvswitch: New ...
173
174
  	if (ethertype == htons(ETH_P_TEB))
  		key->mac_proto = MAC_PROTO_ETHERNET;
fff06c36a   Pravin B Shelar   openvswitch: Opti...
175
  	invalidate_flow_key(key);
25cd9ba0a   Simon Horman   openvswitch: Add ...
176
177
  	return 0;
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
178
179
  static int set_mpls(struct sk_buff *skb, struct sw_flow_key *flow_key,
  		    const __be32 *mpls_lse, const __be32 *mask)
25cd9ba0a   Simon Horman   openvswitch: Add ...
180
  {
85de4a210   Jiri Benc   openvswitch: use ...
181
  	struct mpls_shim_hdr *stack;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
182
  	__be32 lse;
25cd9ba0a   Simon Horman   openvswitch: Add ...
183
  	int err;
43c13605b   Davide Caratti   net: openvswitch:...
184
185
  	if (!pskb_may_pull(skb, skb_network_offset(skb) + MPLS_HLEN))
  		return -ENOMEM;
85de4a210   Jiri Benc   openvswitch: use ...
186
187
  	stack = mpls_hdr(skb);
  	lse = OVS_MASKED(stack->label_stack_entry, *mpls_lse, *mask);
d27cf5c59   John Hurley   net: core: add MP...
188
189
190
  	err = skb_mpls_update_lse(skb, lse);
  	if (err)
  		return err;
25cd9ba0a   Simon Horman   openvswitch: Add ...
191

fbdcdd78d   Martin Varghese   Change in Openvsw...
192
  	flow_key->mpls.lse[0] = lse;
25cd9ba0a   Simon Horman   openvswitch: Add ...
193
194
  	return 0;
  }
fff06c36a   Pravin B Shelar   openvswitch: Opti...
195
  static int pop_vlan(struct sk_buff *skb, struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
196
  {
ccb1352e7   Jesse Gross   net: Add Open vSw...
197
  	int err;
93515d53b   Jiri Pirko   net: move vlan po...
198
  	err = skb_vlan_pop(skb);
018c1dda5   Eric Garver   openvswitch: 802....
199
  	if (skb_vlan_tag_present(skb)) {
93515d53b   Jiri Pirko   net: move vlan po...
200
  		invalidate_flow_key(key);
018c1dda5   Eric Garver   openvswitch: 802....
201
202
203
204
  	} else {
  		key->eth.vlan.tci = 0;
  		key->eth.vlan.tpid = 0;
  	}
93515d53b   Jiri Pirko   net: move vlan po...
205
  	return err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
206
  }
fff06c36a   Pravin B Shelar   openvswitch: Opti...
207
208
  static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key,
  		     const struct ovs_action_push_vlan *vlan)
ccb1352e7   Jesse Gross   net: Add Open vSw...
209
  {
018c1dda5   Eric Garver   openvswitch: 802....
210
  	if (skb_vlan_tag_present(skb)) {
fff06c36a   Pravin B Shelar   openvswitch: Opti...
211
  		invalidate_flow_key(key);
018c1dda5   Eric Garver   openvswitch: 802....
212
213
214
215
  	} else {
  		key->eth.vlan.tci = vlan->vlan_tci;
  		key->eth.vlan.tpid = vlan->vlan_tpid;
  	}
93515d53b   Jiri Pirko   net: move vlan po...
216
  	return skb_vlan_push(skb, vlan->vlan_tpid,
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
217
  			     ntohs(vlan->vlan_tci) & ~VLAN_CFI_MASK);
ccb1352e7   Jesse Gross   net: Add Open vSw...
218
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
219
220
221
222
223
224
  /* 'src' is already properly masked. */
  static void ether_addr_copy_masked(u8 *dst_, const u8 *src_, const u8 *mask_)
  {
  	u16 *dst = (u16 *)dst_;
  	const u16 *src = (const u16 *)src_;
  	const u16 *mask = (const u16 *)mask_;
be26b9a88   Joe Stringer   openvswitch: Move...
225
226
227
  	OVS_SET_MASKED(dst[0], src[0], mask[0]);
  	OVS_SET_MASKED(dst[1], src[1], mask[1]);
  	OVS_SET_MASKED(dst[2], src[2], mask[2]);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
228
229
230
231
232
  }
  
  static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *flow_key,
  			const struct ovs_key_ethernet *key,
  			const struct ovs_key_ethernet *mask)
ccb1352e7   Jesse Gross   net: Add Open vSw...
233
234
  {
  	int err;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
235

e21951212   Jiri Pirko   net: move make_wr...
236
  	err = skb_ensure_writable(skb, ETH_HLEN);
ccb1352e7   Jesse Gross   net: Add Open vSw...
237
238
  	if (unlikely(err))
  		return err;
b34df5e80   Pravin B Shelar   openvswitch: make...
239
  	skb_postpull_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
240
241
242
243
  	ether_addr_copy_masked(eth_hdr(skb)->h_source, key->eth_src,
  			       mask->eth_src);
  	ether_addr_copy_masked(eth_hdr(skb)->h_dest, key->eth_dst,
  			       mask->eth_dst);
ccb1352e7   Jesse Gross   net: Add Open vSw...
244

6b83d28a5   Daniel Borkmann   net: use skb_post...
245
  	skb_postpush_rcsum(skb, eth_hdr(skb), ETH_ALEN * 2);
b34df5e80   Pravin B Shelar   openvswitch: make...
246

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
247
248
  	ether_addr_copy(flow_key->eth.src, eth_hdr(skb)->h_source);
  	ether_addr_copy(flow_key->eth.dst, eth_hdr(skb)->h_dest);
ccb1352e7   Jesse Gross   net: Add Open vSw...
249
250
  	return 0;
  }
91820da6a   Jiri Benc   openvswitch: add ...
251
252
253
254
255
  /* pop_eth does not support VLAN packets as this action is never called
   * for them.
   */
  static int pop_eth(struct sk_buff *skb, struct sw_flow_key *key)
  {
19fbcb36a   Guillaume Nault   net/sched: act_vl...
256
257
258
259
260
  	int err;
  
  	err = skb_eth_pop(skb);
  	if (err)
  		return err;
91820da6a   Jiri Benc   openvswitch: add ...
261
262
263
264
265
266
267
268
269
270
  
  	/* safe right before invalidate_flow_key */
  	key->mac_proto = MAC_PROTO_NONE;
  	invalidate_flow_key(key);
  	return 0;
  }
  
  static int push_eth(struct sk_buff *skb, struct sw_flow_key *key,
  		    const struct ovs_action_push_eth *ethh)
  {
19fbcb36a   Guillaume Nault   net/sched: act_vl...
271
  	int err;
91820da6a   Jiri Benc   openvswitch: add ...
272

19fbcb36a   Guillaume Nault   net/sched: act_vl...
273
274
275
276
  	err = skb_eth_push(skb, ethh->addresses.eth_dst,
  			   ethh->addresses.eth_src);
  	if (err)
  		return err;
91820da6a   Jiri Benc   openvswitch: add ...
277
278
279
280
281
282
  
  	/* safe right before invalidate_flow_key */
  	key->mac_proto = MAC_PROTO_ETHERNET;
  	invalidate_flow_key(key);
  	return 0;
  }
b2d0f5d5d   Yi Yang   openvswitch: enab...
283
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
  static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key,
  		    const struct nshhdr *nh)
  {
  	int err;
  
  	err = nsh_push(skb, nh);
  	if (err)
  		return err;
  
  	/* safe right before invalidate_flow_key */
  	key->mac_proto = MAC_PROTO_NONE;
  	invalidate_flow_key(key);
  	return 0;
  }
  
  static int pop_nsh(struct sk_buff *skb, struct sw_flow_key *key)
  {
  	int err;
  
  	err = nsh_pop(skb);
  	if (err)
  		return err;
  
  	/* safe right before invalidate_flow_key */
  	if (skb->protocol == htons(ETH_P_TEB))
  		key->mac_proto = MAC_PROTO_ETHERNET;
  	else
  		key->mac_proto = MAC_PROTO_NONE;
  	invalidate_flow_key(key);
  	return 0;
  }
3576fd794   Glenn Griffin   openvswitch: Fix ...
314
315
  static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
  				  __be32 addr, __be32 new_addr)
ccb1352e7   Jesse Gross   net: Add Open vSw...
316
317
  {
  	int transport_len = skb->len - skb_transport_offset(skb);
3576fd794   Glenn Griffin   openvswitch: Fix ...
318
319
  	if (nh->frag_off & htons(IP_OFFSET))
  		return;
ccb1352e7   Jesse Gross   net: Add Open vSw...
320
321
322
  	if (nh->protocol == IPPROTO_TCP) {
  		if (likely(transport_len >= sizeof(struct tcphdr)))
  			inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb,
4b048d6d9   Tom Herbert   net: Change pseud...
323
  						 addr, new_addr, true);
ccb1352e7   Jesse Gross   net: Add Open vSw...
324
  	} else if (nh->protocol == IPPROTO_UDP) {
81e5d41d7   Jesse Gross   openvswitch: Fix ...
325
326
327
328
329
  		if (likely(transport_len >= sizeof(struct udphdr))) {
  			struct udphdr *uh = udp_hdr(skb);
  
  			if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
  				inet_proto_csum_replace4(&uh->check, skb,
4b048d6d9   Tom Herbert   net: Change pseud...
330
  							 addr, new_addr, true);
81e5d41d7   Jesse Gross   openvswitch: Fix ...
331
332
333
334
  				if (!uh->check)
  					uh->check = CSUM_MANGLED_0;
  			}
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
335
  	}
3576fd794   Glenn Griffin   openvswitch: Fix ...
336
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
337

3576fd794   Glenn Griffin   openvswitch: Fix ...
338
339
340
341
  static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
  			__be32 *addr, __be32 new_addr)
  {
  	update_ip_l4_checksum(skb, nh, *addr, new_addr);
ccb1352e7   Jesse Gross   net: Add Open vSw...
342
  	csum_replace4(&nh->check, *addr, new_addr);
7539fadcb   Tom Herbert   net: Add utility ...
343
  	skb_clear_hash(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
344
345
  	*addr = new_addr;
  }
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
346
347
348
349
  static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
  				 __be32 addr[4], const __be32 new_addr[4])
  {
  	int transport_len = skb->len - skb_transport_offset(skb);
856447d02   Jesse Gross   openvswitch: Fix ...
350
  	if (l4_proto == NEXTHDR_TCP) {
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
351
352
  		if (likely(transport_len >= sizeof(struct tcphdr)))
  			inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb,
4b048d6d9   Tom Herbert   net: Change pseud...
353
  						  addr, new_addr, true);
856447d02   Jesse Gross   openvswitch: Fix ...
354
  	} else if (l4_proto == NEXTHDR_UDP) {
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
355
356
357
358
359
  		if (likely(transport_len >= sizeof(struct udphdr))) {
  			struct udphdr *uh = udp_hdr(skb);
  
  			if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
  				inet_proto_csum_replace16(&uh->check, skb,
4b048d6d9   Tom Herbert   net: Change pseud...
360
  							  addr, new_addr, true);
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
361
362
363
364
  				if (!uh->check)
  					uh->check = CSUM_MANGLED_0;
  			}
  		}
856447d02   Jesse Gross   openvswitch: Fix ...
365
366
367
  	} else if (l4_proto == NEXTHDR_ICMP) {
  		if (likely(transport_len >= sizeof(struct icmp6hdr)))
  			inet_proto_csum_replace16(&icmp6_hdr(skb)->icmp6_cksum,
4b048d6d9   Tom Herbert   net: Change pseud...
368
  						  skb, addr, new_addr, true);
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
369
370
  	}
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
371
372
373
  static void mask_ipv6_addr(const __be32 old[4], const __be32 addr[4],
  			   const __be32 mask[4], __be32 masked[4])
  {
be26b9a88   Joe Stringer   openvswitch: Move...
374
375
376
377
  	masked[0] = OVS_MASKED(old[0], addr[0], mask[0]);
  	masked[1] = OVS_MASKED(old[1], addr[1], mask[1]);
  	masked[2] = OVS_MASKED(old[2], addr[2], mask[2]);
  	masked[3] = OVS_MASKED(old[3], addr[3], mask[3]);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
378
  }
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
379
380
381
382
383
384
  static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
  			  __be32 addr[4], const __be32 new_addr[4],
  			  bool recalculate_csum)
  {
  	if (recalculate_csum)
  		update_ipv6_checksum(skb, l4_proto, addr, new_addr);
7539fadcb   Tom Herbert   net: Add utility ...
385
  	skb_clear_hash(skb);
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
386
387
  	memcpy(addr, new_addr, sizeof(__be32[4]));
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
388
  static void set_ipv6_fl(struct ipv6hdr *nh, u32 fl, u32 mask)
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
389
  {
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
390
  	/* Bits 21-24 are always unmasked, so this retains their values. */
be26b9a88   Joe Stringer   openvswitch: Move...
391
392
393
  	OVS_SET_MASKED(nh->flow_lbl[0], (u8)(fl >> 16), (u8)(mask >> 16));
  	OVS_SET_MASKED(nh->flow_lbl[1], (u8)(fl >> 8), (u8)(mask >> 8));
  	OVS_SET_MASKED(nh->flow_lbl[2], (u8)fl, (u8)mask);
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
394
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
395
396
  static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl,
  		       u8 mask)
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
397
  {
be26b9a88   Joe Stringer   openvswitch: Move...
398
  	new_ttl = OVS_MASKED(nh->ttl, new_ttl, mask);
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
399

ccb1352e7   Jesse Gross   net: Add Open vSw...
400
401
402
  	csum_replace2(&nh->check, htons(nh->ttl << 8), htons(new_ttl << 8));
  	nh->ttl = new_ttl;
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
403
404
405
  static int set_ipv4(struct sk_buff *skb, struct sw_flow_key *flow_key,
  		    const struct ovs_key_ipv4 *key,
  		    const struct ovs_key_ipv4 *mask)
ccb1352e7   Jesse Gross   net: Add Open vSw...
406
407
  {
  	struct iphdr *nh;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
408
  	__be32 new_addr;
ccb1352e7   Jesse Gross   net: Add Open vSw...
409
  	int err;
e21951212   Jiri Pirko   net: move make_wr...
410
411
  	err = skb_ensure_writable(skb, skb_network_offset(skb) +
  				  sizeof(struct iphdr));
ccb1352e7   Jesse Gross   net: Add Open vSw...
412
413
414
415
  	if (unlikely(err))
  		return err;
  
  	nh = ip_hdr(skb);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
416
417
418
419
420
  	/* Setting an IP addresses is typically only a side effect of
  	 * matching on them in the current userspace implementation, so it
  	 * makes sense to check if the value actually changed.
  	 */
  	if (mask->ipv4_src) {
be26b9a88   Joe Stringer   openvswitch: Move...
421
  		new_addr = OVS_MASKED(nh->saddr, key->ipv4_src, mask->ipv4_src);
ccb1352e7   Jesse Gross   net: Add Open vSw...
422

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
423
424
425
426
  		if (unlikely(new_addr != nh->saddr)) {
  			set_ip_addr(skb, nh, &nh->saddr, new_addr);
  			flow_key->ipv4.addr.src = new_addr;
  		}
fff06c36a   Pravin B Shelar   openvswitch: Opti...
427
  	}
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
428
  	if (mask->ipv4_dst) {
be26b9a88   Joe Stringer   openvswitch: Move...
429
  		new_addr = OVS_MASKED(nh->daddr, key->ipv4_dst, mask->ipv4_dst);
ccb1352e7   Jesse Gross   net: Add Open vSw...
430

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
431
432
433
434
  		if (unlikely(new_addr != nh->daddr)) {
  			set_ip_addr(skb, nh, &nh->daddr, new_addr);
  			flow_key->ipv4.addr.dst = new_addr;
  		}
fff06c36a   Pravin B Shelar   openvswitch: Opti...
435
  	}
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
436
437
438
439
440
441
442
  	if (mask->ipv4_tos) {
  		ipv4_change_dsfield(nh, ~mask->ipv4_tos, key->ipv4_tos);
  		flow_key->ip.tos = nh->tos;
  	}
  	if (mask->ipv4_ttl) {
  		set_ip_ttl(skb, nh, key->ipv4_ttl, mask->ipv4_ttl);
  		flow_key->ip.ttl = nh->ttl;
fff06c36a   Pravin B Shelar   openvswitch: Opti...
443
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
444
445
446
  
  	return 0;
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
447
448
449
450
451
452
453
454
  static bool is_ipv6_mask_nonzero(const __be32 addr[4])
  {
  	return !!(addr[0] | addr[1] | addr[2] | addr[3]);
  }
  
  static int set_ipv6(struct sk_buff *skb, struct sw_flow_key *flow_key,
  		    const struct ovs_key_ipv6 *key,
  		    const struct ovs_key_ipv6 *mask)
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
455
456
457
  {
  	struct ipv6hdr *nh;
  	int err;
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
458

e21951212   Jiri Pirko   net: move make_wr...
459
460
  	err = skb_ensure_writable(skb, skb_network_offset(skb) +
  				  sizeof(struct ipv6hdr));
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
461
462
463
464
  	if (unlikely(err))
  		return err;
  
  	nh = ipv6_hdr(skb);
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
465

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
466
467
468
469
470
471
472
473
474
475
476
  	/* Setting an IP addresses is typically only a side effect of
  	 * matching on them in the current userspace implementation, so it
  	 * makes sense to check if the value actually changed.
  	 */
  	if (is_ipv6_mask_nonzero(mask->ipv6_src)) {
  		__be32 *saddr = (__be32 *)&nh->saddr;
  		__be32 masked[4];
  
  		mask_ipv6_addr(saddr, key->ipv6_src, mask->ipv6_src, masked);
  
  		if (unlikely(memcmp(saddr, masked, sizeof(masked)))) {
b4f70527f   Simon Horman   openvswitch: use ...
477
  			set_ipv6_addr(skb, flow_key->ip.proto, saddr, masked,
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
478
479
480
481
482
483
  				      true);
  			memcpy(&flow_key->ipv6.addr.src, masked,
  			       sizeof(flow_key->ipv6.addr.src));
  		}
  	}
  	if (is_ipv6_mask_nonzero(mask->ipv6_dst)) {
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
484
485
486
  		unsigned int offset = 0;
  		int flags = IP6_FH_F_SKIP_RH;
  		bool recalc_csum = true;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
487
488
489
490
491
492
493
494
495
496
497
  		__be32 *daddr = (__be32 *)&nh->daddr;
  		__be32 masked[4];
  
  		mask_ipv6_addr(daddr, key->ipv6_dst, mask->ipv6_dst, masked);
  
  		if (unlikely(memcmp(daddr, masked, sizeof(masked)))) {
  			if (ipv6_ext_hdr(nh->nexthdr))
  				recalc_csum = (ipv6_find_hdr(skb, &offset,
  							     NEXTHDR_ROUTING,
  							     NULL, &flags)
  					       != NEXTHDR_ROUTING);
b4f70527f   Simon Horman   openvswitch: use ...
498
  			set_ipv6_addr(skb, flow_key->ip.proto, daddr, masked,
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
  				      recalc_csum);
  			memcpy(&flow_key->ipv6.addr.dst, masked,
  			       sizeof(flow_key->ipv6.addr.dst));
  		}
  	}
  	if (mask->ipv6_tclass) {
  		ipv6_change_dsfield(nh, ~mask->ipv6_tclass, key->ipv6_tclass);
  		flow_key->ip.tos = ipv6_get_dsfield(nh);
  	}
  	if (mask->ipv6_label) {
  		set_ipv6_fl(nh, ntohl(key->ipv6_label),
  			    ntohl(mask->ipv6_label));
  		flow_key->ipv6.label =
  		    *(__be32 *)nh & htonl(IPV6_FLOWINFO_FLOWLABEL);
  	}
  	if (mask->ipv6_hlimit) {
be26b9a88   Joe Stringer   openvswitch: Move...
515
516
  		OVS_SET_MASKED(nh->hop_limit, key->ipv6_hlimit,
  			       mask->ipv6_hlimit);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
517
  		flow_key->ip.ttl = nh->hop_limit;
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
518
  	}
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
519
520
  	return 0;
  }
b2d0f5d5d   Yi Yang   openvswitch: enab...
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
  static int set_nsh(struct sk_buff *skb, struct sw_flow_key *flow_key,
  		   const struct nlattr *a)
  {
  	struct nshhdr *nh;
  	size_t length;
  	int err;
  	u8 flags;
  	u8 ttl;
  	int i;
  
  	struct ovs_key_nsh key;
  	struct ovs_key_nsh mask;
  
  	err = nsh_key_from_nlattr(a, &key, &mask);
  	if (err)
  		return err;
  
  	/* Make sure the NSH base header is there */
  	if (!pskb_may_pull(skb, skb_network_offset(skb) + NSH_BASE_HDR_LEN))
  		return -ENOMEM;
  
  	nh = nsh_hdr(skb);
  	length = nsh_hdr_len(nh);
  
  	/* Make sure the whole NSH header is there */
  	err = skb_ensure_writable(skb, skb_network_offset(skb) +
  				       length);
  	if (unlikely(err))
  		return err;
  
  	nh = nsh_hdr(skb);
  	skb_postpull_rcsum(skb, nh, length);
  	flags = nsh_get_flags(nh);
  	flags = OVS_MASKED(flags, key.base.flags, mask.base.flags);
  	flow_key->nsh.base.flags = flags;
  	ttl = nsh_get_ttl(nh);
  	ttl = OVS_MASKED(ttl, key.base.ttl, mask.base.ttl);
  	flow_key->nsh.base.ttl = ttl;
  	nsh_set_flags_and_ttl(nh, flags, ttl);
  	nh->path_hdr = OVS_MASKED(nh->path_hdr, key.base.path_hdr,
  				  mask.base.path_hdr);
  	flow_key->nsh.base.path_hdr = nh->path_hdr;
  	switch (nh->mdtype) {
  	case NSH_M_TYPE1:
  		for (i = 0; i < NSH_MD1_CONTEXT_SIZE; i++) {
  			nh->md1.context[i] =
  			    OVS_MASKED(nh->md1.context[i], key.context[i],
  				       mask.context[i]);
  		}
  		memcpy(flow_key->nsh.context, nh->md1.context,
  		       sizeof(nh->md1.context));
  		break;
  	case NSH_M_TYPE2:
  		memset(flow_key->nsh.context, 0,
  		       sizeof(flow_key->nsh.context));
  		break;
  	default:
  		return -EINVAL;
  	}
  	skb_postpush_rcsum(skb, nh, length);
  	return 0;
  }
e21951212   Jiri Pirko   net: move make_wr...
583
  /* Must follow skb_ensure_writable() since that can move the skb data. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
584
  static void set_tp_port(struct sk_buff *skb, __be16 *port,
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
585
  			__be16 new_port, __sum16 *check)
ccb1352e7   Jesse Gross   net: Add Open vSw...
586
  {
4b048d6d9   Tom Herbert   net: Change pseud...
587
  	inet_proto_csum_replace2(check, skb, *port, new_port, false);
ccb1352e7   Jesse Gross   net: Add Open vSw...
588
  	*port = new_port;
81e5d41d7   Jesse Gross   openvswitch: Fix ...
589
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
590
591
592
  static int set_udp(struct sk_buff *skb, struct sw_flow_key *flow_key,
  		   const struct ovs_key_udp *key,
  		   const struct ovs_key_udp *mask)
ccb1352e7   Jesse Gross   net: Add Open vSw...
593
594
  {
  	struct udphdr *uh;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
595
  	__be16 src, dst;
ccb1352e7   Jesse Gross   net: Add Open vSw...
596
  	int err;
e21951212   Jiri Pirko   net: move make_wr...
597
598
  	err = skb_ensure_writable(skb, skb_transport_offset(skb) +
  				  sizeof(struct udphdr));
ccb1352e7   Jesse Gross   net: Add Open vSw...
599
600
601
602
  	if (unlikely(err))
  		return err;
  
  	uh = udp_hdr(skb);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
603
  	/* Either of the masks is non-zero, so do not bother checking them. */
be26b9a88   Joe Stringer   openvswitch: Move...
604
605
  	src = OVS_MASKED(uh->source, key->udp_src, mask->udp_src);
  	dst = OVS_MASKED(uh->dest, key->udp_dst, mask->udp_dst);
ccb1352e7   Jesse Gross   net: Add Open vSw...
606

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  	if (uh->check && skb->ip_summed != CHECKSUM_PARTIAL) {
  		if (likely(src != uh->source)) {
  			set_tp_port(skb, &uh->source, src, &uh->check);
  			flow_key->tp.src = src;
  		}
  		if (likely(dst != uh->dest)) {
  			set_tp_port(skb, &uh->dest, dst, &uh->check);
  			flow_key->tp.dst = dst;
  		}
  
  		if (unlikely(!uh->check))
  			uh->check = CSUM_MANGLED_0;
  	} else {
  		uh->source = src;
  		uh->dest = dst;
  		flow_key->tp.src = src;
  		flow_key->tp.dst = dst;
fff06c36a   Pravin B Shelar   openvswitch: Opti...
624
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
625

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
626
  	skb_clear_hash(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
627
628
  	return 0;
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
629
630
631
  static int set_tcp(struct sk_buff *skb, struct sw_flow_key *flow_key,
  		   const struct ovs_key_tcp *key,
  		   const struct ovs_key_tcp *mask)
ccb1352e7   Jesse Gross   net: Add Open vSw...
632
633
  {
  	struct tcphdr *th;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
634
  	__be16 src, dst;
ccb1352e7   Jesse Gross   net: Add Open vSw...
635
  	int err;
e21951212   Jiri Pirko   net: move make_wr...
636
637
  	err = skb_ensure_writable(skb, skb_transport_offset(skb) +
  				  sizeof(struct tcphdr));
ccb1352e7   Jesse Gross   net: Add Open vSw...
638
639
640
641
  	if (unlikely(err))
  		return err;
  
  	th = tcp_hdr(skb);
be26b9a88   Joe Stringer   openvswitch: Move...
642
  	src = OVS_MASKED(th->source, key->tcp_src, mask->tcp_src);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
643
644
645
  	if (likely(src != th->source)) {
  		set_tp_port(skb, &th->source, src, &th->check);
  		flow_key->tp.src = src;
fff06c36a   Pravin B Shelar   openvswitch: Opti...
646
  	}
be26b9a88   Joe Stringer   openvswitch: Move...
647
  	dst = OVS_MASKED(th->dest, key->tcp_dst, mask->tcp_dst);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
648
649
650
  	if (likely(dst != th->dest)) {
  		set_tp_port(skb, &th->dest, dst, &th->check);
  		flow_key->tp.dst = dst;
fff06c36a   Pravin B Shelar   openvswitch: Opti...
651
  	}
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
652
  	skb_clear_hash(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
653
654
655
  
  	return 0;
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
656
657
658
  static int set_sctp(struct sk_buff *skb, struct sw_flow_key *flow_key,
  		    const struct ovs_key_sctp *key,
  		    const struct ovs_key_sctp *mask)
a175a7233   Joe Stringer   openvswitch: Add ...
659
  {
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
660
  	unsigned int sctphoff = skb_transport_offset(skb);
a175a7233   Joe Stringer   openvswitch: Add ...
661
  	struct sctphdr *sh;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
662
  	__le32 old_correct_csum, new_csum, old_csum;
a175a7233   Joe Stringer   openvswitch: Add ...
663
  	int err;
a175a7233   Joe Stringer   openvswitch: Add ...
664

e21951212   Jiri Pirko   net: move make_wr...
665
  	err = skb_ensure_writable(skb, sctphoff + sizeof(struct sctphdr));
a175a7233   Joe Stringer   openvswitch: Add ...
666
667
668
669
  	if (unlikely(err))
  		return err;
  
  	sh = sctp_hdr(skb);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
670
671
  	old_csum = sh->checksum;
  	old_correct_csum = sctp_compute_cksum(skb, sctphoff);
a175a7233   Joe Stringer   openvswitch: Add ...
672

be26b9a88   Joe Stringer   openvswitch: Move...
673
674
  	sh->source = OVS_MASKED(sh->source, key->sctp_src, mask->sctp_src);
  	sh->dest = OVS_MASKED(sh->dest, key->sctp_dst, mask->sctp_dst);
a175a7233   Joe Stringer   openvswitch: Add ...
675

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
676
  	new_csum = sctp_compute_cksum(skb, sctphoff);
a175a7233   Joe Stringer   openvswitch: Add ...
677

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
678
679
  	/* Carry any checksum errors through. */
  	sh->checksum = old_csum ^ old_correct_csum ^ new_csum;
a175a7233   Joe Stringer   openvswitch: Add ...
680

83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
681
682
683
  	skb_clear_hash(skb);
  	flow_key->tp.src = sh->source;
  	flow_key->tp.dst = sh->dest;
a175a7233   Joe Stringer   openvswitch: Add ...
684
685
686
  
  	return 0;
  }
cf3266ad4   Tonghao Zhang   net: openvswitch:...
687
688
  static int ovs_vport_output(struct net *net, struct sock *sk,
  			    struct sk_buff *skb)
7f8a436ea   Joe Stringer   openvswitch: Add ...
689
690
691
692
693
694
695
696
697
698
699
700
  {
  	struct ovs_frag_data *data = this_cpu_ptr(&ovs_frag_data_storage);
  	struct vport *vport = data->vport;
  
  	if (skb_cow_head(skb, data->l2_len) < 0) {
  		kfree_skb(skb);
  		return -ENOMEM;
  	}
  
  	__skb_dst_copy(skb, data->dst);
  	*OVS_CB(skb) = data->cb;
  	skb->inner_protocol = data->inner_protocol;
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
701
702
703
704
  	if (data->vlan_tci & VLAN_CFI_MASK)
  		__vlan_hwaccel_put_tag(skb, data->vlan_proto, data->vlan_tci & ~VLAN_CFI_MASK);
  	else
  		__vlan_hwaccel_clear_tag(skb);
7f8a436ea   Joe Stringer   openvswitch: Add ...
705
706
707
708
  
  	/* Reconstruct the MAC header.  */
  	skb_push(skb, data->l2_len);
  	memcpy(skb->data, &data->l2_data, data->l2_len);
6b83d28a5   Daniel Borkmann   net: use skb_post...
709
  	skb_postpush_rcsum(skb, skb->data, data->l2_len);
7f8a436ea   Joe Stringer   openvswitch: Add ...
710
  	skb_reset_mac_header(skb);
c66549ffd   Jiri Benc   openvswitch: corr...
711
712
713
714
715
  	if (eth_p_mpls(skb->protocol)) {
  		skb->inner_network_header = skb->network_header;
  		skb_set_network_header(skb, data->network_offset);
  		skb_reset_mac_len(skb);
  	}
e2d9d8358   Jiri Benc   openvswitch: pass...
716
  	ovs_vport_send(vport, skb, data->mac_proto);
7f8a436ea   Joe Stringer   openvswitch: Add ...
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
  	return 0;
  }
  
  static unsigned int
  ovs_dst_get_mtu(const struct dst_entry *dst)
  {
  	return dst->dev->mtu;
  }
  
  static struct dst_ops ovs_dst_ops = {
  	.family = AF_UNSPEC,
  	.mtu = ovs_dst_get_mtu,
  };
  
  /* prepare_frag() is called once per (larger-than-MTU) frame; its inverse is
   * ovs_vport_output(), which is called once per fragmented packet.
   */
c66549ffd   Jiri Benc   openvswitch: corr...
734
  static void prepare_frag(struct vport *vport, struct sk_buff *skb,
e2d9d8358   Jiri Benc   openvswitch: pass...
735
  			 u16 orig_network_offset, u8 mac_proto)
7f8a436ea   Joe Stringer   openvswitch: Add ...
736
737
738
739
740
741
742
743
744
  {
  	unsigned int hlen = skb_network_offset(skb);
  	struct ovs_frag_data *data;
  
  	data = this_cpu_ptr(&ovs_frag_data_storage);
  	data->dst = skb->_skb_refdst;
  	data->vport = vport;
  	data->cb = *OVS_CB(skb);
  	data->inner_protocol = skb->inner_protocol;
c66549ffd   Jiri Benc   openvswitch: corr...
745
  	data->network_offset = orig_network_offset;
9df46aefa   MichaÅ‚ MirosÅ‚aw   OVS: remove use o...
746
747
748
749
  	if (skb_vlan_tag_present(skb))
  		data->vlan_tci = skb_vlan_tag_get(skb) | VLAN_CFI_MASK;
  	else
  		data->vlan_tci = 0;
7f8a436ea   Joe Stringer   openvswitch: Add ...
750
  	data->vlan_proto = skb->vlan_proto;
e2d9d8358   Jiri Benc   openvswitch: pass...
751
  	data->mac_proto = mac_proto;
7f8a436ea   Joe Stringer   openvswitch: Add ...
752
753
754
755
756
757
  	data->l2_len = hlen;
  	memcpy(&data->l2_data, skb->data, hlen);
  
  	memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
  	skb_pull(skb, hlen);
  }
c559cd3ad   Eric W. Biederman   openvswitch: Pass...
758
  static void ovs_fragment(struct net *net, struct vport *vport,
e2d9d8358   Jiri Benc   openvswitch: pass...
759
760
  			 struct sk_buff *skb, u16 mru,
  			 struct sw_flow_key *key)
7f8a436ea   Joe Stringer   openvswitch: Add ...
761
  {
c66549ffd   Jiri Benc   openvswitch: corr...
762
763
764
765
766
767
  	u16 orig_network_offset = 0;
  
  	if (eth_p_mpls(skb->protocol)) {
  		orig_network_offset = skb_network_offset(skb);
  		skb->network_header = skb->inner_network_header;
  	}
7f8a436ea   Joe Stringer   openvswitch: Add ...
768
769
  	if (skb_network_offset(skb) > MAX_L2_LEN) {
  		OVS_NLERR(1, "L2 header too long to fragment");
b8f225706   Joe Stringer   openvswitch: Fix ...
770
  		goto err;
7f8a436ea   Joe Stringer   openvswitch: Add ...
771
  	}
e2d9d8358   Jiri Benc   openvswitch: pass...
772
  	if (key->eth.type == htons(ETH_P_IP)) {
7f8a436ea   Joe Stringer   openvswitch: Add ...
773
774
  		struct dst_entry ovs_dst;
  		unsigned long orig_dst;
e2d9d8358   Jiri Benc   openvswitch: pass...
775
776
  		prepare_frag(vport, skb, orig_network_offset,
  			     ovs_key_mac_proto(key));
7f8a436ea   Joe Stringer   openvswitch: Add ...
777
778
779
780
781
782
783
  		dst_init(&ovs_dst, &ovs_dst_ops, NULL, 1,
  			 DST_OBSOLETE_NONE, DST_NOCOUNT);
  		ovs_dst.dev = vport->dev;
  
  		orig_dst = skb->_skb_refdst;
  		skb_dst_set_noref(skb, &ovs_dst);
  		IPCB(skb)->frag_max_size = mru;
694869b3c   Eric W. Biederman   ipv4: Pass struct...
784
  		ip_do_fragment(net, skb->sk, skb, ovs_vport_output);
7f8a436ea   Joe Stringer   openvswitch: Add ...
785
  		refdst_drop(orig_dst);
e2d9d8358   Jiri Benc   openvswitch: pass...
786
  	} else if (key->eth.type == htons(ETH_P_IPV6)) {
7f8a436ea   Joe Stringer   openvswitch: Add ...
787
788
  		unsigned long orig_dst;
  		struct rt6_info ovs_rt;
e2d9d8358   Jiri Benc   openvswitch: pass...
789
790
  		prepare_frag(vport, skb, orig_network_offset,
  			     ovs_key_mac_proto(key));
7f8a436ea   Joe Stringer   openvswitch: Add ...
791
792
793
794
795
796
797
798
  		memset(&ovs_rt, 0, sizeof(ovs_rt));
  		dst_init(&ovs_rt.dst, &ovs_dst_ops, NULL, 1,
  			 DST_OBSOLETE_NONE, DST_NOCOUNT);
  		ovs_rt.dst.dev = vport->dev;
  
  		orig_dst = skb->_skb_refdst;
  		skb_dst_set_noref(skb, &ovs_rt.dst);
  		IP6CB(skb)->frag_max_size = mru;
a7c978c6c   wenxu   openvswitch: usin...
799
  		ipv6_stub->ipv6_fragment(net, skb->sk, skb, ovs_vport_output);
7f8a436ea   Joe Stringer   openvswitch: Add ...
800
801
802
  		refdst_drop(orig_dst);
  	} else {
  		WARN_ONCE(1, "Failed fragment ->%s: eth=%04x, MRU=%d, MTU=%d.",
e2d9d8358   Jiri Benc   openvswitch: pass...
803
  			  ovs_vport_name(vport), ntohs(key->eth.type), mru,
7f8a436ea   Joe Stringer   openvswitch: Add ...
804
  			  vport->dev->mtu);
b8f225706   Joe Stringer   openvswitch: Fix ...
805
  		goto err;
7f8a436ea   Joe Stringer   openvswitch: Add ...
806
  	}
b8f225706   Joe Stringer   openvswitch: Fix ...
807
808
809
810
  
  	return;
  err:
  	kfree_skb(skb);
7f8a436ea   Joe Stringer   openvswitch: Add ...
811
812
813
814
  }
  
  static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
  		      struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
815
  {
738967b8b   Andy Zhou   openvswitch: refa...
816
  	struct vport *vport = ovs_vport_rcu(dp, out_port);
ccb1352e7   Jesse Gross   net: Add Open vSw...
817

7f8a436ea   Joe Stringer   openvswitch: Add ...
818
819
  	if (likely(vport)) {
  		u16 mru = OVS_CB(skb)->mru;
f2a4d086e   William Tu   openvswitch: Add ...
820
821
822
  		u32 cutlen = OVS_CB(skb)->cutlen;
  
  		if (unlikely(cutlen > 0)) {
e2d9d8358   Jiri Benc   openvswitch: pass...
823
  			if (skb->len - cutlen > ovs_mac_header_len(key))
f2a4d086e   William Tu   openvswitch: Add ...
824
825
  				pskb_trim(skb, skb->len - cutlen);
  			else
e2d9d8358   Jiri Benc   openvswitch: pass...
826
  				pskb_trim(skb, ovs_mac_header_len(key));
f2a4d086e   William Tu   openvswitch: Add ...
827
  		}
7f8a436ea   Joe Stringer   openvswitch: Add ...
828

738314a08   Jiri Benc   openvswitch: use ...
829
830
  		if (likely(!mru ||
  		           (skb->len <= mru + vport->dev->hard_header_len))) {
e2d9d8358   Jiri Benc   openvswitch: pass...
831
  			ovs_vport_send(vport, skb, ovs_key_mac_proto(key));
7f8a436ea   Joe Stringer   openvswitch: Add ...
832
  		} else if (mru <= vport->dev->mtu) {
c559cd3ad   Eric W. Biederman   openvswitch: Pass...
833
  			struct net *net = read_pnet(&dp->net);
7f8a436ea   Joe Stringer   openvswitch: Add ...
834

e2d9d8358   Jiri Benc   openvswitch: pass...
835
  			ovs_fragment(net, vport, skb, mru, key);
7f8a436ea   Joe Stringer   openvswitch: Add ...
836
837
838
839
  		} else {
  			kfree_skb(skb);
  		}
  	} else {
ccb1352e7   Jesse Gross   net: Add Open vSw...
840
  		kfree_skb(skb);
7f8a436ea   Joe Stringer   openvswitch: Add ...
841
  	}
ccb1352e7   Jesse Gross   net: Add Open vSw...
842
843
844
  }
  
  static int output_userspace(struct datapath *dp, struct sk_buff *skb,
ccea74457   Neil McKee   openvswitch: incl...
845
  			    struct sw_flow_key *key, const struct nlattr *attr,
f2a4d086e   William Tu   openvswitch: Add ...
846
847
  			    const struct nlattr *actions, int actions_len,
  			    uint32_t cutlen)
ccb1352e7   Jesse Gross   net: Add Open vSw...
848
849
850
851
  {
  	struct dp_upcall_info upcall;
  	const struct nlattr *a;
  	int rem;
ccea74457   Neil McKee   openvswitch: incl...
852
  	memset(&upcall, 0, sizeof(upcall));
ccb1352e7   Jesse Gross   net: Add Open vSw...
853
  	upcall.cmd = OVS_PACKET_CMD_ACTION;
7f8a436ea   Joe Stringer   openvswitch: Add ...
854
  	upcall.mru = OVS_CB(skb)->mru;
ccb1352e7   Jesse Gross   net: Add Open vSw...
855
856
  
  	for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
cf3266ad4   Tonghao Zhang   net: openvswitch:...
857
  	     a = nla_next(a, &rem)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
858
859
860
861
862
863
  		switch (nla_type(a)) {
  		case OVS_USERSPACE_ATTR_USERDATA:
  			upcall.userdata = a;
  			break;
  
  		case OVS_USERSPACE_ATTR_PID:
15e473046   Eric W. Biederman   netlink: Rename p...
864
  			upcall.portid = nla_get_u32(a);
ccb1352e7   Jesse Gross   net: Add Open vSw...
865
  			break;
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
866
867
868
869
870
871
872
873
  
  		case OVS_USERSPACE_ATTR_EGRESS_TUN_PORT: {
  			/* Get out tunnel info. */
  			struct vport *vport;
  
  			vport = ovs_vport_rcu(dp, nla_get_u32(a));
  			if (vport) {
  				int err;
fc4099f17   Pravin B Shelar   openvswitch: Fix ...
874
875
876
  				err = dev_fill_metadata_dst(vport->dev, skb);
  				if (!err)
  					upcall.egress_tun_info = skb_tunnel_info(skb);
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
877
  			}
4c2227984   Pravin B Shelar   ip-tunnel: Use AP...
878

8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
879
  			break;
ccb1352e7   Jesse Gross   net: Add Open vSw...
880
  		}
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
881

ccea74457   Neil McKee   openvswitch: incl...
882
883
884
885
886
887
  		case OVS_USERSPACE_ATTR_ACTIONS: {
  			/* Include actions. */
  			upcall.actions = actions;
  			upcall.actions_len = actions_len;
  			break;
  		}
8f0aad6f3   Wenyu Zhang   openvswitch: Exte...
888
  		} /* End of switch. */
ccb1352e7   Jesse Gross   net: Add Open vSw...
889
  	}
f2a4d086e   William Tu   openvswitch: Add ...
890
  	return ovs_dp_upcall(dp, skb, key, &upcall, cutlen);
ccb1352e7   Jesse Gross   net: Add Open vSw...
891
  }
744676e77   Matteo Croce   openvswitch: add ...
892
893
894
895
896
897
  static int dec_ttl_exception_handler(struct datapath *dp, struct sk_buff *skb,
  				     struct sw_flow_key *key,
  				     const struct nlattr *attr, bool last)
  {
  	/* The first action is always 'OVS_DEC_TTL_ATTR_ARG'. */
  	struct nlattr *dec_ttl_arg = nla_data(attr);
744676e77   Matteo Croce   openvswitch: add ...
898
899
  
  	if (nla_len(dec_ttl_arg)) {
69929d4c4   Eelco Chaudron   net: openvswitch:...
900
  		struct nlattr *actions = nla_data(dec_ttl_arg);
744676e77   Matteo Croce   openvswitch: add ...
901
902
  
  		if (actions)
69929d4c4   Eelco Chaudron   net: openvswitch:...
903
904
  			return clone_execute(dp, skb, key, 0, nla_data(actions),
  					     nla_len(actions), last, false);
744676e77   Matteo Croce   openvswitch: add ...
905
906
907
908
  	}
  	consume_skb(skb);
  	return 0;
  }
798c16617   andy zhou   openvswitch: Opti...
909
910
911
912
  /* When 'last' is true, sample() should always consume the 'skb'.
   * Otherwise, sample() should keep 'skb' intact regardless what
   * actions are executed within sample().
   */
ccb1352e7   Jesse Gross   net: Add Open vSw...
913
  static int sample(struct datapath *dp, struct sk_buff *skb,
ccea74457   Neil McKee   openvswitch: incl...
914
  		  struct sw_flow_key *key, const struct nlattr *attr,
798c16617   andy zhou   openvswitch: Opti...
915
  		  bool last)
ccb1352e7   Jesse Gross   net: Add Open vSw...
916
  {
798c16617   andy zhou   openvswitch: Opti...
917
918
  	struct nlattr *actions;
  	struct nlattr *sample_arg;
798c16617   andy zhou   openvswitch: Opti...
919
  	int rem = nla_len(attr);
798c16617   andy zhou   openvswitch: Opti...
920
  	const struct sample_arg *arg;
bef7f7567   andy zhou   Openvswitch: Refa...
921
  	bool clone_flow_key;
ccb1352e7   Jesse Gross   net: Add Open vSw...
922

798c16617   andy zhou   openvswitch: Opti...
923
924
925
926
  	/* The first action is always 'OVS_SAMPLE_ATTR_ARG'. */
  	sample_arg = nla_data(attr);
  	arg = nla_data(sample_arg);
  	actions = nla_next(sample_arg, &rem);
e05176a32   Wenyu Zhang   openvswitch: Make...
927

798c16617   andy zhou   openvswitch: Opti...
928
929
930
931
932
  	if ((arg->probability != U32_MAX) &&
  	    (!arg->probability || prandom_u32() > arg->probability)) {
  		if (last)
  			consume_skb(skb);
  		return 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
933
  	}
bef7f7567   andy zhou   Openvswitch: Refa...
934
935
936
  	clone_flow_key = !arg->exec;
  	return clone_execute(dp, skb, key, 0, actions, rem, last,
  			     clone_flow_key);
971427f35   Andy Zhou   openvswitch: Add ...
937
  }
b23350403   Yifeng Sun   openvswitch: kern...
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
  /* When 'last' is true, clone() should always consume the 'skb'.
   * Otherwise, clone() should keep 'skb' intact regardless what
   * actions are executed within clone().
   */
  static int clone(struct datapath *dp, struct sk_buff *skb,
  		 struct sw_flow_key *key, const struct nlattr *attr,
  		 bool last)
  {
  	struct nlattr *actions;
  	struct nlattr *clone_arg;
  	int rem = nla_len(attr);
  	bool dont_clone_flow_key;
  
  	/* The first action is always 'OVS_CLONE_ATTR_ARG'. */
  	clone_arg = nla_data(attr);
  	dont_clone_flow_key = nla_get_u32(clone_arg);
  	actions = nla_next(clone_arg, &rem);
  
  	return clone_execute(dp, skb, key, 0, actions, rem, last,
  			     !dont_clone_flow_key);
  }
971427f35   Andy Zhou   openvswitch: Add ...
959
960
961
962
963
964
965
966
967
968
969
970
971
  static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key,
  			 const struct nlattr *attr)
  {
  	struct ovs_action_hash *hash_act = nla_data(attr);
  	u32 hash = 0;
  
  	/* OVS_HASH_ALG_L4 is the only possible hash algorithm.  */
  	hash = skb_get_hash(skb);
  	hash = jhash_1word(hash, hash_act->hash_basis);
  	if (!hash)
  		hash = 0x1;
  
  	key->ovs_flow_hash = hash;
ccb1352e7   Jesse Gross   net: Add Open vSw...
972
  }
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
973
974
975
976
977
978
  static int execute_set_action(struct sk_buff *skb,
  			      struct sw_flow_key *flow_key,
  			      const struct nlattr *a)
  {
  	/* Only tunnel set execution is supported without a mask. */
  	if (nla_type(a) == OVS_KEY_ATTR_TUNNEL_INFO) {
34ae932a4   Thomas Graf   openvswitch: Make...
979
980
981
982
983
  		struct ovs_tunnel_info *tun = nla_data(a);
  
  		skb_dst_drop(skb);
  		dst_hold((struct dst_entry *)tun->tun_dst);
  		skb_dst_set(skb, (struct dst_entry *)tun->tun_dst);
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
984
985
986
987
988
989
990
991
992
993
994
995
  		return 0;
  	}
  
  	return -EINVAL;
  }
  
  /* Mask is at the midpoint of the data. */
  #define get_mask(a, type) ((const type)nla_data(a) + 1)
  
  static int execute_masked_set_action(struct sk_buff *skb,
  				     struct sw_flow_key *flow_key,
  				     const struct nlattr *a)
ccb1352e7   Jesse Gross   net: Add Open vSw...
996
997
  {
  	int err = 0;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
998
  	switch (nla_type(a)) {
ccb1352e7   Jesse Gross   net: Add Open vSw...
999
  	case OVS_KEY_ATTR_PRIORITY:
be26b9a88   Joe Stringer   openvswitch: Move...
1000
1001
  		OVS_SET_MASKED(skb->priority, nla_get_u32(a),
  			       *get_mask(a, u32 *));
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1002
  		flow_key->phy.priority = skb->priority;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1003
  		break;
39c7caebc   Ansis Atteka   openvswitch: add ...
1004
  	case OVS_KEY_ATTR_SKB_MARK:
be26b9a88   Joe Stringer   openvswitch: Move...
1005
  		OVS_SET_MASKED(skb->mark, nla_get_u32(a), *get_mask(a, u32 *));
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1006
  		flow_key->phy.skb_mark = skb->mark;
39c7caebc   Ansis Atteka   openvswitch: add ...
1007
  		break;
f0b128c1e   Jesse Gross   openvswitch: Wrap...
1008
  	case OVS_KEY_ATTR_TUNNEL_INFO:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1009
1010
  		/* Masked data not supported for tunnel. */
  		err = -EINVAL;
7d5437c70   Pravin B Shelar   openvswitch: Add ...
1011
  		break;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1012
  	case OVS_KEY_ATTR_ETHERNET:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1013
1014
  		err = set_eth_addr(skb, flow_key, nla_data(a),
  				   get_mask(a, struct ovs_key_ethernet *));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1015
  		break;
b2d0f5d5d   Yi Yang   openvswitch: enab...
1016
1017
1018
  	case OVS_KEY_ATTR_NSH:
  		err = set_nsh(skb, flow_key, a);
  		break;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1019
  	case OVS_KEY_ATTR_IPV4:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1020
1021
  		err = set_ipv4(skb, flow_key, nla_data(a),
  			       get_mask(a, struct ovs_key_ipv4 *));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1022
  		break;
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
1023
  	case OVS_KEY_ATTR_IPV6:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1024
1025
  		err = set_ipv6(skb, flow_key, nla_data(a),
  			       get_mask(a, struct ovs_key_ipv6 *));
3fdbd1ce1   Ansis Atteka   openvswitch: add ...
1026
  		break;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1027
  	case OVS_KEY_ATTR_TCP:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1028
1029
  		err = set_tcp(skb, flow_key, nla_data(a),
  			      get_mask(a, struct ovs_key_tcp *));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1030
1031
1032
  		break;
  
  	case OVS_KEY_ATTR_UDP:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1033
1034
  		err = set_udp(skb, flow_key, nla_data(a),
  			      get_mask(a, struct ovs_key_udp *));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1035
  		break;
a175a7233   Joe Stringer   openvswitch: Add ...
1036
1037
  
  	case OVS_KEY_ATTR_SCTP:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1038
1039
  		err = set_sctp(skb, flow_key, nla_data(a),
  			       get_mask(a, struct ovs_key_sctp *));
a175a7233   Joe Stringer   openvswitch: Add ...
1040
  		break;
25cd9ba0a   Simon Horman   openvswitch: Add ...
1041
1042
  
  	case OVS_KEY_ATTR_MPLS:
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1043
1044
  		err = set_mpls(skb, flow_key, nla_data(a), get_mask(a,
  								    __be32 *));
25cd9ba0a   Simon Horman   openvswitch: Add ...
1045
  		break;
7f8a436ea   Joe Stringer   openvswitch: Add ...
1046
1047
1048
  
  	case OVS_KEY_ATTR_CT_STATE:
  	case OVS_KEY_ATTR_CT_ZONE:
182e3042e   Joe Stringer   openvswitch: Allo...
1049
  	case OVS_KEY_ATTR_CT_MARK:
33db4125e   Joe Stringer   openvswitch: Rena...
1050
  	case OVS_KEY_ATTR_CT_LABELS:
9dd7f8907   Jarno Rajahalme   openvswitch: Add ...
1051
1052
  	case OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4:
  	case OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6:
7f8a436ea   Joe Stringer   openvswitch: Add ...
1053
1054
  		err = -EINVAL;
  		break;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1055
1056
1057
1058
  	}
  
  	return err;
  }
971427f35   Andy Zhou   openvswitch: Add ...
1059
1060
  static int execute_recirc(struct datapath *dp, struct sk_buff *skb,
  			  struct sw_flow_key *key,
bef7f7567   andy zhou   Openvswitch: Refa...
1061
  			  const struct nlattr *a, bool last)
971427f35   Andy Zhou   openvswitch: Add ...
1062
  {
bef7f7567   andy zhou   Openvswitch: Refa...
1063
  	u32 recirc_id;
971427f35   Andy Zhou   openvswitch: Add ...
1064

fff06c36a   Pravin B Shelar   openvswitch: Opti...
1065
1066
1067
1068
1069
1070
1071
1072
  	if (!is_flow_key_valid(key)) {
  		int err;
  
  		err = ovs_flow_key_update(skb, key);
  		if (err)
  			return err;
  	}
  	BUG_ON(!is_flow_key_valid(key));
971427f35   Andy Zhou   openvswitch: Add ...
1073

bef7f7567   andy zhou   Openvswitch: Refa...
1074
1075
  	recirc_id = nla_get_u32(a);
  	return clone_execute(dp, skb, key, recirc_id, NULL, 0, last, true);
971427f35   Andy Zhou   openvswitch: Add ...
1076
  }
4d5ec89fc   Numan Siddique   net: openvswitch:...
1077
1078
1079
1080
  static int execute_check_pkt_len(struct datapath *dp, struct sk_buff *skb,
  				 struct sw_flow_key *key,
  				 const struct nlattr *attr, bool last)
  {
178436557   Lorenzo Bianconi   openvswitch: take...
1081
  	struct ovs_skb_cb *ovs_cb = OVS_CB(skb);
4d5ec89fc   Numan Siddique   net: openvswitch:...
1082
  	const struct nlattr *actions, *cpl_arg;
178436557   Lorenzo Bianconi   openvswitch: take...
1083
  	int len, max_len, rem = nla_len(attr);
4d5ec89fc   Numan Siddique   net: openvswitch:...
1084
  	const struct check_pkt_len_arg *arg;
4d5ec89fc   Numan Siddique   net: openvswitch:...
1085
1086
1087
1088
1089
1090
1091
  	bool clone_flow_key;
  
  	/* The first netlink attribute in 'attr' is always
  	 * 'OVS_CHECK_PKT_LEN_ATTR_ARG'.
  	 */
  	cpl_arg = nla_data(attr);
  	arg = nla_data(cpl_arg);
178436557   Lorenzo Bianconi   openvswitch: take...
1092
1093
1094
1095
1096
  	len = ovs_cb->mru ? ovs_cb->mru + skb->mac_len : skb->len;
  	max_len = arg->pkt_len;
  
  	if ((skb_is_gso(skb) && skb_gso_validate_mac_len(skb, max_len)) ||
  	    len <= max_len) {
4d5ec89fc   Numan Siddique   net: openvswitch:...
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  		/* Second netlink attribute in 'attr' is always
  		 * 'OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_LESS_EQUAL'.
  		 */
  		actions = nla_next(cpl_arg, &rem);
  		clone_flow_key = !arg->exec_for_lesser_equal;
  	} else {
  		/* Third netlink attribute in 'attr' is always
  		 * 'OVS_CHECK_PKT_LEN_ATTR_ACTIONS_IF_GREATER'.
  		 */
  		actions = nla_next(cpl_arg, &rem);
  		actions = nla_next(actions, &rem);
  		clone_flow_key = !arg->exec_for_greater;
  	}
  
  	return clone_execute(dp, skb, key, 0, nla_data(actions),
  			     nla_len(actions), last, clone_flow_key);
  }
744676e77   Matteo Croce   openvswitch: add ...
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
  static int execute_dec_ttl(struct sk_buff *skb, struct sw_flow_key *key)
  {
  	int err;
  
  	if (skb->protocol == htons(ETH_P_IPV6)) {
  		struct ipv6hdr *nh;
  
  		err = skb_ensure_writable(skb, skb_network_offset(skb) +
  					  sizeof(*nh));
  		if (unlikely(err))
  			return err;
  
  		nh = ipv6_hdr(skb);
  
  		if (nh->hop_limit <= 1)
  			return -EHOSTUNREACH;
  
  		key->ip.ttl = --nh->hop_limit;
  	} else {
  		struct iphdr *nh;
  		u8 old_ttl;
  
  		err = skb_ensure_writable(skb, skb_network_offset(skb) +
  					  sizeof(*nh));
  		if (unlikely(err))
  			return err;
  
  		nh = ip_hdr(skb);
  		if (nh->ttl <= 1)
  			return -EHOSTUNREACH;
  
  		old_ttl = nh->ttl--;
  		csum_replace2(&nh->check, htons(old_ttl << 8),
  			      htons(nh->ttl << 8));
  		key->ip.ttl = nh->ttl;
  	}
  	return 0;
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
1152
1153
  /* Execute a list of actions against 'skb'. */
  static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
2ff3e4e48   Pravin B Shelar   openvswitch: Remo...
1154
  			      struct sw_flow_key *key,
651887b0c   Simon Horman   openvswitch: Samp...
1155
  			      const struct nlattr *attr, int len)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1156
  {
ccb1352e7   Jesse Gross   net: Add Open vSw...
1157
1158
1159
1160
1161
1162
  	const struct nlattr *a;
  	int rem;
  
  	for (a = attr, rem = len; rem > 0;
  	     a = nla_next(a, &rem)) {
  		int err = 0;
5b8784aaf   andy zhou   openvswitch: Simp...
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
  		switch (nla_type(a)) {
  		case OVS_ACTION_ATTR_OUTPUT: {
  			int port = nla_get_u32(a);
  			struct sk_buff *clone;
  
  			/* Every output action needs a separate clone
  			 * of 'skb', In case the output action is the
  			 * last action, cloning can be avoided.
  			 */
  			if (nla_is_last(a, rem)) {
  				do_output(dp, skb, port, key);
  				/* 'skb' has been used for output.
  				 */
  				return 0;
  			}
738967b8b   Andy Zhou   openvswitch: refa...
1178

5b8784aaf   andy zhou   openvswitch: Simp...
1179
1180
1181
  			clone = skb_clone(skb, GFP_ATOMIC);
  			if (clone)
  				do_output(dp, clone, port, key);
f2a4d086e   William Tu   openvswitch: Add ...
1182
  			OVS_CB(skb)->cutlen = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1183
  			break;
5b8784aaf   andy zhou   openvswitch: Simp...
1184
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1185

f2a4d086e   William Tu   openvswitch: Add ...
1186
1187
1188
1189
1190
1191
1192
  		case OVS_ACTION_ATTR_TRUNC: {
  			struct ovs_action_trunc *trunc = nla_data(a);
  
  			if (skb->len > trunc->max_len)
  				OVS_CB(skb)->cutlen = skb->len - trunc->max_len;
  			break;
  		}
ccb1352e7   Jesse Gross   net: Add Open vSw...
1193
  		case OVS_ACTION_ATTR_USERSPACE:
f2a4d086e   William Tu   openvswitch: Add ...
1194
1195
1196
  			output_userspace(dp, skb, key, a, attr,
  						     len, OVS_CB(skb)->cutlen);
  			OVS_CB(skb)->cutlen = 0;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1197
  			break;
971427f35   Andy Zhou   openvswitch: Add ...
1198
1199
1200
  		case OVS_ACTION_ATTR_HASH:
  			execute_hash(skb, key, a);
  			break;
f66b53fdb   Martin Varghese   openvswitch: New ...
1201
1202
1203
1204
1205
  		case OVS_ACTION_ATTR_PUSH_MPLS: {
  			struct ovs_action_push_mpls *mpls = nla_data(a);
  
  			err = push_mpls(skb, key, mpls->mpls_lse,
  					mpls->mpls_ethertype, skb->mac_len);
25cd9ba0a   Simon Horman   openvswitch: Add ...
1206
  			break;
f66b53fdb   Martin Varghese   openvswitch: New ...
1207
1208
1209
1210
1211
1212
1213
  		}
  		case OVS_ACTION_ATTR_ADD_MPLS: {
  			struct ovs_action_add_mpls *mpls = nla_data(a);
  			__u16 mac_len = 0;
  
  			if (mpls->tun_flags & OVS_MPLS_L3_TUNNEL_FLAG_MASK)
  				mac_len = skb->mac_len;
25cd9ba0a   Simon Horman   openvswitch: Add ...
1214

f66b53fdb   Martin Varghese   openvswitch: New ...
1215
1216
1217
1218
  			err = push_mpls(skb, key, mpls->mpls_lse,
  					mpls->mpls_ethertype, mac_len);
  			break;
  		}
25cd9ba0a   Simon Horman   openvswitch: Add ...
1219
  		case OVS_ACTION_ATTR_POP_MPLS:
fff06c36a   Pravin B Shelar   openvswitch: Opti...
1220
  			err = pop_mpls(skb, key, nla_get_be16(a));
25cd9ba0a   Simon Horman   openvswitch: Add ...
1221
  			break;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1222
  		case OVS_ACTION_ATTR_PUSH_VLAN:
fff06c36a   Pravin B Shelar   openvswitch: Opti...
1223
  			err = push_vlan(skb, key, nla_data(a));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1224
1225
1226
  			break;
  
  		case OVS_ACTION_ATTR_POP_VLAN:
fff06c36a   Pravin B Shelar   openvswitch: Opti...
1227
  			err = pop_vlan(skb, key);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1228
  			break;
bef7f7567   andy zhou   Openvswitch: Refa...
1229
1230
1231
1232
1233
  		case OVS_ACTION_ATTR_RECIRC: {
  			bool last = nla_is_last(a, rem);
  
  			err = execute_recirc(dp, skb, key, a, last);
  			if (last) {
971427f35   Andy Zhou   openvswitch: Add ...
1234
1235
1236
1237
1238
1239
1240
  				/* If this is the last action, the skb has
  				 * been consumed or freed.
  				 * Return immediately.
  				 */
  				return err;
  			}
  			break;
bef7f7567   andy zhou   Openvswitch: Refa...
1241
  		}
971427f35   Andy Zhou   openvswitch: Add ...
1242

ccb1352e7   Jesse Gross   net: Add Open vSw...
1243
  		case OVS_ACTION_ATTR_SET:
fff06c36a   Pravin B Shelar   openvswitch: Opti...
1244
  			err = execute_set_action(skb, key, nla_data(a));
ccb1352e7   Jesse Gross   net: Add Open vSw...
1245
  			break;
83d2b9ba1   Jarno Rajahalme   net: openvswitch:...
1246
1247
1248
1249
  		case OVS_ACTION_ATTR_SET_MASKED:
  		case OVS_ACTION_ATTR_SET_TO_MASKED:
  			err = execute_masked_set_action(skb, key, nla_data(a));
  			break;
798c16617   andy zhou   openvswitch: Opti...
1250
1251
1252
1253
1254
1255
  		case OVS_ACTION_ATTR_SAMPLE: {
  			bool last = nla_is_last(a, rem);
  
  			err = sample(dp, skb, key, a, last);
  			if (last)
  				return err;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1256
  			break;
798c16617   andy zhou   openvswitch: Opti...
1257
  		}
7f8a436ea   Joe Stringer   openvswitch: Add ...
1258
1259
  
  		case OVS_ACTION_ATTR_CT:
ec0d043d0   Joe Stringer   openvswitch: Ensu...
1260
1261
1262
1263
1264
  			if (!is_flow_key_valid(key)) {
  				err = ovs_flow_key_update(skb, key);
  				if (err)
  					return err;
  			}
7f8a436ea   Joe Stringer   openvswitch: Add ...
1265
1266
1267
1268
  			err = ovs_ct_execute(ovs_dp_get_net(dp), skb, key,
  					     nla_data(a));
  
  			/* Hide stolen IP fragments from user space. */
74c166181   Joe Stringer   openvswitch: Fix ...
1269
1270
  			if (err)
  				return err == -EINPROGRESS ? 0 : err;
7f8a436ea   Joe Stringer   openvswitch: Add ...
1271
  			break;
91820da6a   Jiri Benc   openvswitch: add ...
1272

b8226962b   Eric Garver   openvswitch: add ...
1273
1274
1275
  		case OVS_ACTION_ATTR_CT_CLEAR:
  			err = ovs_ct_clear(skb, key);
  			break;
91820da6a   Jiri Benc   openvswitch: add ...
1276
1277
1278
1279
1280
1281
1282
  		case OVS_ACTION_ATTR_PUSH_ETH:
  			err = push_eth(skb, key, nla_data(a));
  			break;
  
  		case OVS_ACTION_ATTR_POP_ETH:
  			err = pop_eth(skb, key);
  			break;
b2d0f5d5d   Yi Yang   openvswitch: enab...
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
  
  		case OVS_ACTION_ATTR_PUSH_NSH: {
  			u8 buffer[NSH_HDR_MAX_LEN];
  			struct nshhdr *nh = (struct nshhdr *)buffer;
  
  			err = nsh_hdr_from_nlattr(nla_data(a), nh,
  						  NSH_HDR_MAX_LEN);
  			if (unlikely(err))
  				break;
  			err = push_nsh(skb, key, nh);
  			break;
  		}
  
  		case OVS_ACTION_ATTR_POP_NSH:
  			err = pop_nsh(skb, key);
  			break;
cd8a6c336   Andy Zhou   openvswitch: Add ...
1299
1300
1301
1302
1303
1304
  
  		case OVS_ACTION_ATTR_METER:
  			if (ovs_meter_execute(dp, skb, key, nla_get_u32(a))) {
  				consume_skb(skb);
  				return 0;
  			}
b23350403   Yifeng Sun   openvswitch: kern...
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
  			break;
  
  		case OVS_ACTION_ATTR_CLONE: {
  			bool last = nla_is_last(a, rem);
  
  			err = clone(dp, skb, key, a, last);
  			if (last)
  				return err;
  
  			break;
  		}
4d5ec89fc   Numan Siddique   net: openvswitch:...
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
  
  		case OVS_ACTION_ATTR_CHECK_PKT_LEN: {
  			bool last = nla_is_last(a, rem);
  
  			err = execute_check_pkt_len(dp, skb, key, a, last);
  			if (last)
  				return err;
  
  			break;
  		}
744676e77   Matteo Croce   openvswitch: add ...
1326
1327
1328
1329
1330
1331
1332
1333
1334
  
  		case OVS_ACTION_ATTR_DEC_TTL:
  			err = execute_dec_ttl(skb, key);
  			if (err == -EHOSTUNREACH) {
  				err = dec_ttl_exception_handler(dp, skb, key,
  								a, true);
  				return err;
  			}
  			break;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1335
1336
1337
1338
1339
1340
1341
  		}
  
  		if (unlikely(err)) {
  			kfree_skb(skb);
  			return err;
  		}
  	}
5b8784aaf   andy zhou   openvswitch: Simp...
1342
  	consume_skb(skb);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1343
1344
  	return 0;
  }
bef7f7567   andy zhou   Openvswitch: Refa...
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
  /* Execute the actions on the clone of the packet. The effect of the
   * execution does not affect the original 'skb' nor the original 'key'.
   *
   * The execution may be deferred in case the actions can not be executed
   * immediately.
   */
  static int clone_execute(struct datapath *dp, struct sk_buff *skb,
  			 struct sw_flow_key *key, u32 recirc_id,
  			 const struct nlattr *actions, int len,
  			 bool last, bool clone_flow_key)
  {
  	struct deferred_action *da;
  	struct sw_flow_key *clone;
  
  	skb = last ? skb : skb_clone(skb, GFP_ATOMIC);
  	if (!skb) {
  		/* Out of memory, skip this action.
  		 */
  		return 0;
  	}
  
  	/* When clone_flow_key is false, the 'key' will not be change
  	 * by the actions, then the 'key' can be used directly.
  	 * Otherwise, try to clone key from the next recursion level of
  	 * 'flow_keys'. If clone is successful, execute the actions
  	 * without deferring.
  	 */
  	clone = clone_flow_key ? clone_key(key) : key;
  	if (clone) {
  		int err = 0;
  
  		if (actions) { /* Sample action */
  			if (clone_flow_key)
  				__this_cpu_inc(exec_actions_level);
  
  			err = do_execute_actions(dp, skb, clone,
  						 actions, len);
  
  			if (clone_flow_key)
  				__this_cpu_dec(exec_actions_level);
  		} else { /* Recirc action */
  			clone->recirc_id = recirc_id;
  			ovs_dp_process_packet(skb, clone);
  		}
  		return err;
  	}
  
  	/* Out of 'flow_keys' space. Defer actions */
  	da = add_deferred_actions(skb, key, actions, len);
  	if (da) {
  		if (!actions) { /* Recirc action */
  			key = &da->pkt_key;
  			key->recirc_id = recirc_id;
  		}
  	} else {
  		/* Out of per CPU action FIFO space. Drop the 'skb' and
  		 * log an error.
  		 */
  		kfree_skb(skb);
  
  		if (net_ratelimit()) {
  			if (actions) { /* Sample action */
  				pr_warn("%s: deferred action limit reached, drop sample action
  ",
  					ovs_dp_name(dp));
  			} else {  /* Recirc action */
  				pr_warn("%s: deferred action limit reached, drop recirc action
  ",
  					ovs_dp_name(dp));
  			}
  		}
  	}
  	return 0;
  }
971427f35   Andy Zhou   openvswitch: Add ...
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
  static void process_deferred_actions(struct datapath *dp)
  {
  	struct action_fifo *fifo = this_cpu_ptr(action_fifos);
  
  	/* Do not touch the FIFO in case there is no deferred actions. */
  	if (action_fifo_is_empty(fifo))
  		return;
  
  	/* Finishing executing all deferred actions. */
  	do {
  		struct deferred_action *da = action_fifo_get(fifo);
  		struct sk_buff *skb = da->skb;
  		struct sw_flow_key *key = &da->pkt_key;
  		const struct nlattr *actions = da->actions;
47c697aa2   andy zhou   openvswitch: Defe...
1433
  		int actions_len = da->actions_len;
971427f35   Andy Zhou   openvswitch: Add ...
1434
1435
  
  		if (actions)
47c697aa2   andy zhou   openvswitch: Defe...
1436
  			do_execute_actions(dp, skb, key, actions, actions_len);
971427f35   Andy Zhou   openvswitch: Add ...
1437
1438
1439
1440
1441
1442
1443
  		else
  			ovs_dp_process_packet(skb, key);
  	} while (!action_fifo_is_empty(fifo));
  
  	/* Reset FIFO for the next packet.  */
  	action_fifo_init(fifo);
  }
ccb1352e7   Jesse Gross   net: Add Open vSw...
1444
  /* Execute a list of actions against 'skb'. */
2ff3e4e48   Pravin B Shelar   openvswitch: Remo...
1445
  int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
12eb18f71   Thomas Graf   openvswitch: Cons...
1446
1447
  			const struct sw_flow_actions *acts,
  			struct sw_flow_key *key)
ccb1352e7   Jesse Gross   net: Add Open vSw...
1448
  {
b064d0d88   Hannes Frederic Sowa   ovs: limit ovs re...
1449
1450
1451
  	int err, level;
  
  	level = __this_cpu_inc_return(exec_actions_level);
2679d0404   Lance Richardson   openvswitch: avoi...
1452
  	if (unlikely(level > OVS_RECURSION_LIMIT)) {
b064d0d88   Hannes Frederic Sowa   ovs: limit ovs re...
1453
1454
1455
1456
1457
1458
1459
  		net_crit_ratelimited("ovs: recursion limit reached on datapath %s, probable configuration error
  ",
  				     ovs_dp_name(dp));
  		kfree_skb(skb);
  		err = -ENETDOWN;
  		goto out;
  	}
971427f35   Andy Zhou   openvswitch: Add ...
1460

494bea39f   Liping Zhang   openvswitch: fix ...
1461
  	OVS_CB(skb)->acts_origlen = acts->orig_len;
971427f35   Andy Zhou   openvswitch: Add ...
1462
1463
  	err = do_execute_actions(dp, skb, key,
  				 acts->actions, acts->actions_len);
b064d0d88   Hannes Frederic Sowa   ovs: limit ovs re...
1464
  	if (level == 1)
971427f35   Andy Zhou   openvswitch: Add ...
1465
  		process_deferred_actions(dp);
b064d0d88   Hannes Frederic Sowa   ovs: limit ovs re...
1466
1467
  out:
  	__this_cpu_dec(exec_actions_level);
971427f35   Andy Zhou   openvswitch: Add ...
1468
1469
1470
1471
1472
1473
1474
1475
  	return err;
  }
  
  int action_fifos_init(void)
  {
  	action_fifos = alloc_percpu(struct action_fifo);
  	if (!action_fifos)
  		return -ENOMEM;
ccb1352e7   Jesse Gross   net: Add Open vSw...
1476

4572ef52a   andy zhou   openvswitch: Refa...
1477
1478
  	flow_keys = alloc_percpu(struct action_flow_keys);
  	if (!flow_keys) {
2679d0404   Lance Richardson   openvswitch: avoi...
1479
1480
1481
  		free_percpu(action_fifos);
  		return -ENOMEM;
  	}
971427f35   Andy Zhou   openvswitch: Add ...
1482
1483
1484
1485
1486
1487
  	return 0;
  }
  
  void action_fifos_exit(void)
  {
  	free_percpu(action_fifos);
4572ef52a   andy zhou   openvswitch: Refa...
1488
  	free_percpu(flow_keys);
ccb1352e7   Jesse Gross   net: Add Open vSw...
1489
  }