aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/actions.c
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2014-11-19 08:05:02 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-21 14:20:18 -0500
commit93515d53b133d66f01aec7b231fa3e40e3d2fd9a (patch)
tree6b3bc7c1e38c90eeacdbfb4ddce02d208ae66d63 /net/openvswitch/actions.c
parente21951212f03b8d805795d8f71206853b2ab344d (diff)
net: move vlan pop/push functions into common code
So it can be used from out of openvswitch code. Did couple of cosmetic changes on the way, namely variable naming and adding support for 8021AD proto. Signed-off-by: Jiri Pirko <jiri@resnulli.us> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch/actions.c')
-rw-r--r--net/openvswitch/actions.c86
1 files changed, 9 insertions, 77 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 7ffa37716265..4e05ea1c2d11 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -206,93 +206,27 @@ static int set_mpls(struct sk_buff *skb, struct sw_flow_key *key,
206 return 0; 206 return 0;
207} 207}
208 208
209/* remove VLAN header from packet and update csum accordingly. */
210static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
211{
212 struct vlan_hdr *vhdr;
213 int err;
214
215 err = skb_ensure_writable(skb, VLAN_ETH_HLEN);
216 if (unlikely(err))
217 return err;
218
219 skb_postpull_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
220
221 vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN);
222 *current_tci = vhdr->h_vlan_TCI;
223
224 memmove(skb->data + VLAN_HLEN, skb->data, 2 * ETH_ALEN);
225 __skb_pull(skb, VLAN_HLEN);
226
227 vlan_set_encap_proto(skb, vhdr);
228 skb->mac_header += VLAN_HLEN;
229
230 if (skb_network_offset(skb) < ETH_HLEN)
231 skb_set_network_header(skb, ETH_HLEN);
232
233 /* Update mac_len for subsequent MPLS actions */
234 skb_reset_mac_len(skb);
235 return 0;
236}
237
238static int pop_vlan(struct sk_buff *skb, struct sw_flow_key *key) 209static int pop_vlan(struct sk_buff *skb, struct sw_flow_key *key)
239{ 210{
240 __be16 tci;
241 int err; 211 int err;
242 212
243 if (likely(vlan_tx_tag_present(skb))) { 213 err = skb_vlan_pop(skb);
244 skb->vlan_tci = 0; 214 if (vlan_tx_tag_present(skb))
245 } else { 215 invalidate_flow_key(key);
246 if (unlikely(skb->protocol != htons(ETH_P_8021Q) || 216 else
247 skb->len < VLAN_ETH_HLEN))
248 return 0;
249
250 err = __pop_vlan_tci(skb, &tci);
251 if (err)
252 return err;
253 }
254 /* move next vlan tag to hw accel tag */
255 if (likely(skb->protocol != htons(ETH_P_8021Q) ||
256 skb->len < VLAN_ETH_HLEN)) {
257 key->eth.tci = 0; 217 key->eth.tci = 0;
258 return 0; 218 return err;
259 }
260
261 invalidate_flow_key(key);
262 err = __pop_vlan_tci(skb, &tci);
263 if (unlikely(err))
264 return err;
265
266 __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), ntohs(tci));
267 return 0;
268} 219}
269 220
270static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key, 221static int push_vlan(struct sk_buff *skb, struct sw_flow_key *key,
271 const struct ovs_action_push_vlan *vlan) 222 const struct ovs_action_push_vlan *vlan)
272{ 223{
273 if (unlikely(vlan_tx_tag_present(skb))) { 224 if (vlan_tx_tag_present(skb))
274 u16 current_tag;
275
276 /* push down current VLAN tag */
277 current_tag = vlan_tx_tag_get(skb);
278
279 skb = vlan_insert_tag_set_proto(skb, skb->vlan_proto,
280 current_tag);
281 if (!skb)
282 return -ENOMEM;
283 /* Update mac_len for subsequent MPLS actions */
284 skb->mac_len += VLAN_HLEN;
285
286 if (skb->ip_summed == CHECKSUM_COMPLETE)
287 skb->csum = csum_add(skb->csum, csum_partial(skb->data
288 + (2 * ETH_ALEN), VLAN_HLEN, 0));
289
290 invalidate_flow_key(key); 225 invalidate_flow_key(key);
291 } else { 226 else
292 key->eth.tci = vlan->vlan_tci; 227 key->eth.tci = vlan->vlan_tci;
293 } 228 return skb_vlan_push(skb, vlan->vlan_tpid,
294 __vlan_hwaccel_put_tag(skb, vlan->vlan_tpid, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT); 229 ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
295 return 0;
296} 230}
297 231
298static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *key, 232static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *key,
@@ -858,8 +792,6 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
858 792
859 case OVS_ACTION_ATTR_PUSH_VLAN: 793 case OVS_ACTION_ATTR_PUSH_VLAN:
860 err = push_vlan(skb, key, nla_data(a)); 794 err = push_vlan(skb, key, nla_data(a));
861 if (unlikely(err)) /* skb already freed. */
862 return err;
863 break; 795 break;
864 796
865 case OVS_ACTION_ATTR_POP_VLAN: 797 case OVS_ACTION_ATTR_POP_VLAN: