diff options
author | Pravin B Shelar <pshelar@ovn.org> | 2016-07-17 09:52:11 -0700 |
---|---|---|
committer | Pravin B Shelar <pshelar@ovn.org> | 2016-07-17 10:25:09 -0700 |
commit | b51367aad315985c3d6cf7782bb72438e3b270d8 (patch) | |
tree | 297fb7e9704ae68a042c3ed9fb277a672132480c /datapath | |
parent | c1eb18c44daba87d62ed2ac5cfd99d0871c8a4f0 (diff) | |
download | openvswitch-b51367aad315985c3d6cf7782bb72438e3b270d8.tar.gz |
datapath: openvswitch: update checksum in {push,pop}_mpls
Upstream commit:
commit bc7cc5999fd392cc799630d7e375b2f4e29cc398
Author: Simon Horman <simon.horman@netronome.com>
openvswitch: update checksum in {push,pop}_mpls
In the case of CHECKSUM_COMPLETE the skb checksum should be updated in
{push,pop}_mpls() as they the type in the ethernet header.
As suggested by Pravin Shelar.
Cc: Pravin Shelar <pshelar@ovn.org>
Fixes: 25cd9ba0abc0 ("openvswitch: Add basic MPLS support to kernel")
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Acked-by: Pravin B Shelar <pshelar@ovn.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Pravin B Shelar <pshelar@ovn.org>
Acked-by: Jesse Gross <jesse@kernel.org>
Diffstat (limited to 'datapath')
-rw-r--r-- | datapath/actions.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/datapath/actions.c b/datapath/actions.c index fb5fa8a95..abf7e3bdf 100644 --- a/datapath/actions.c +++ b/datapath/actions.c @@ -139,11 +139,23 @@ static bool is_flow_key_valid(const struct sw_flow_key *key) return !!key->eth.type; } +static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr, + __be16 ethertype) +{ + if (skb->ip_summed == CHECKSUM_COMPLETE) { + __be16 diff[] = { ~(hdr->h_proto), ethertype }; + + skb->csum = ~csum_partial((char *)diff, sizeof(diff), + ~skb->csum); + } + + hdr->h_proto = ethertype; +} + static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, const struct ovs_action_push_mpls *mpls) { __be32 *new_mpls_lse; - struct ethhdr *hdr; /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ if (skb->encapsulation) @@ -162,8 +174,7 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN); - hdr = eth_hdr(skb); - hdr->h_proto = mpls->mpls_ethertype; + update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype); if (!ovs_skb_get_inner_protocol(skb)) ovs_skb_set_inner_protocol(skb, skb->protocol); skb->protocol = mpls->mpls_ethertype; @@ -194,7 +205,7 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key, * field correctly in the presence of VLAN tags. */ hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN); - hdr->h_proto = ethertype; + update_ethertype(skb, hdr, ethertype); if (eth_p_mpls(skb->protocol)) skb->protocol = ethertype; |