diff options
Diffstat (limited to 'net/openvswitch/actions.c')
| -rw-r--r-- | net/openvswitch/actions.c | 30 | 
1 files changed, 24 insertions, 6 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 4c8395462303..7fbfe2adfffa 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c @@ -161,16 +161,17 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,  			      const struct nlattr *attr, int len);  static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, -		     const struct ovs_action_push_mpls *mpls) +		     __be32 mpls_lse, __be16 mpls_ethertype, __u16 mac_len)  {  	int err; -	err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype, -			    skb->mac_len, -			    ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET); +	err = skb_mpls_push(skb, mpls_lse, mpls_ethertype, mac_len, !!mac_len);  	if (err)  		return err; +	if (!mac_len) +		key->mac_proto = MAC_PROTO_NONE; +  	invalidate_flow_key(key);  	return 0;  } @@ -185,6 +186,9 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,  	if (err)  		return err; +	if (ethertype == htons(ETH_P_TEB)) +		key->mac_proto = MAC_PROTO_ETHERNET; +  	invalidate_flow_key(key);  	return 0;  } @@ -1229,10 +1233,24 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,  			execute_hash(skb, key, a);  			break; -		case OVS_ACTION_ATTR_PUSH_MPLS: -			err = push_mpls(skb, key, nla_data(a)); +		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);  			break; +		} +		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; +			err = push_mpls(skb, key, mpls->mpls_lse, +					mpls->mpls_ethertype, mac_len); +			break; +		}  		case OVS_ACTION_ATTR_POP_MPLS:  			err = pop_mpls(skb, key, nla_get_be16(a));  			break;  |