diff options
| -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 | ||
