diff options
| author | Simon Horman <simon.horman@netronome.com> | 2016-05-30 01:04:25 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-05-31 16:51:42 -0400 |
| commit | bc7cc5999fd392cc799630d7e375b2f4e29cc398 (patch) | |
| tree | 93951297d1c82bdd0d241d6f8385c7f6ff9cea53 /net/openvswitch | |
| parent | 40eb90e9ccc3f96f937ea1db79d0f9cb61553ed5 (diff) | |
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@nicira.com>
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>
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/actions.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index 879185fe183f..9a3eb7a0ebf4 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
| @@ -137,11 +137,23 @@ static bool is_flow_key_valid(const struct sw_flow_key *key) | |||
| 137 | return !!key->eth.type; | 137 | return !!key->eth.type; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr, | ||
| 141 | __be16 ethertype) | ||
| 142 | { | ||
| 143 | if (skb->ip_summed == CHECKSUM_COMPLETE) { | ||
| 144 | __be16 diff[] = { ~(hdr->h_proto), ethertype }; | ||
| 145 | |||
| 146 | skb->csum = ~csum_partial((char *)diff, sizeof(diff), | ||
| 147 | ~skb->csum); | ||
| 148 | } | ||
| 149 | |||
| 150 | hdr->h_proto = ethertype; | ||
| 151 | } | ||
| 152 | |||
| 140 | static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, | 153 | static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, |
| 141 | const struct ovs_action_push_mpls *mpls) | 154 | const struct ovs_action_push_mpls *mpls) |
| 142 | { | 155 | { |
| 143 | __be32 *new_mpls_lse; | 156 | __be32 *new_mpls_lse; |
| 144 | struct ethhdr *hdr; | ||
| 145 | 157 | ||
| 146 | /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ | 158 | /* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ |
| 147 | if (skb->encapsulation) | 159 | if (skb->encapsulation) |
| @@ -160,9 +172,7 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, | |||
| 160 | 172 | ||
| 161 | skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN); | 173 | skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN); |
| 162 | 174 | ||
| 163 | hdr = eth_hdr(skb); | 175 | update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype); |
| 164 | hdr->h_proto = mpls->mpls_ethertype; | ||
| 165 | |||
| 166 | if (!skb->inner_protocol) | 176 | if (!skb->inner_protocol) |
| 167 | skb_set_inner_protocol(skb, skb->protocol); | 177 | skb_set_inner_protocol(skb, skb->protocol); |
| 168 | skb->protocol = mpls->mpls_ethertype; | 178 | skb->protocol = mpls->mpls_ethertype; |
| @@ -193,7 +203,7 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key, | |||
| 193 | * field correctly in the presence of VLAN tags. | 203 | * field correctly in the presence of VLAN tags. |
| 194 | */ | 204 | */ |
| 195 | hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN); | 205 | hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN); |
| 196 | hdr->h_proto = ethertype; | 206 | update_ethertype(skb, hdr, ethertype); |
| 197 | if (eth_p_mpls(skb->protocol)) | 207 | if (eth_p_mpls(skb->protocol)) |
| 198 | skb->protocol = ethertype; | 208 | skb->protocol = ethertype; |
| 199 | 209 | ||
