forked from mirrors/linux
		
	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: 25cd9ba0ab ("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>
			
			
This commit is contained in:
		
							parent
							
								
									40eb90e9cc
								
							
						
					
					
						commit
						bc7cc5999f
					
				
					 1 changed files with 15 additions and 5 deletions
				
			
		|  | @ -137,11 +137,23 @@ static bool is_flow_key_valid(const struct sw_flow_key *key) | ||||||
| 	return !!key->eth.type; | 	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, | static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, | ||||||
| 		     const struct ovs_action_push_mpls *mpls) | 		     const struct ovs_action_push_mpls *mpls) | ||||||
| { | { | ||||||
| 	__be32 *new_mpls_lse; | 	__be32 *new_mpls_lse; | ||||||
| 	struct ethhdr *hdr; |  | ||||||
| 
 | 
 | ||||||
| 	/* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ | 	/* Networking stack do not allow simultaneous Tunnel and MPLS GSO. */ | ||||||
| 	if (skb->encapsulation) | 	if (skb->encapsulation) | ||||||
|  | @ -160,9 +172,7 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key, | ||||||
| 
 | 
 | ||||||
| 	skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN); | 	skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN); | ||||||
| 
 | 
 | ||||||
| 	hdr = eth_hdr(skb); | 	update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype); | ||||||
| 	hdr->h_proto = mpls->mpls_ethertype; |  | ||||||
| 
 |  | ||||||
| 	if (!skb->inner_protocol) | 	if (!skb->inner_protocol) | ||||||
| 		skb_set_inner_protocol(skb, skb->protocol); | 		skb_set_inner_protocol(skb, skb->protocol); | ||||||
| 	skb->protocol = mpls->mpls_ethertype; | 	skb->protocol = mpls->mpls_ethertype; | ||||||
|  | @ -193,7 +203,7 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key, | ||||||
| 	 * field correctly in the presence of VLAN tags. | 	 * field correctly in the presence of VLAN tags. | ||||||
| 	 */ | 	 */ | ||||||
| 	hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN); | 	hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN); | ||||||
| 	hdr->h_proto = ethertype; | 	update_ethertype(skb, hdr, ethertype); | ||||||
| 	if (eth_p_mpls(skb->protocol)) | 	if (eth_p_mpls(skb->protocol)) | ||||||
| 		skb->protocol = ethertype; | 		skb->protocol = ethertype; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Simon Horman
						Simon Horman