Skip to content

Commit 0e9a709

Browse files
petedawsdavem330
authored andcommitted
ip6_tunnel, ip6_gre: fix setting of DSCP on encapsulated packets
This fix addresses two problems in the way the DSCP field is formulated on the encapsulating header of IPv6 tunnels. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=195661 1) The IPv6 tunneling code was manipulating the DSCP field of the encapsulating packet using the 32b flowlabel. Since the flowlabel is only the lower 20b it was incorrect to assume that the upper 12b containing the DSCP and ECN fields would remain intact when formulating the encapsulating header. This fix handles the 'inherit' and 'fixed-value' DSCP cases explicitly using the extant dsfield u8 variable. 2) The use of INET_ECN_encapsulate(0, dsfield) in ip6_tnl_xmit was incorrect and resulted in the DSCP value always being set to 0. Commit 90427ef ("ipv6: fix flow labels when the traffic class is non-0") caused the regression by masking out the flowlabel which exposed the incorrect handling of the DSCP portion of the flowlabel in ip6_tunnel and ip6_gre. Fixes: 90427ef ("ipv6: fix flow labels when the traffic class is non-0") Signed-off-by: Peter Dawson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 804ec7e commit 0e9a709

File tree

2 files changed

+20
-14
lines changed

2 files changed

+20
-14
lines changed

net/ipv6/ip6_gre.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -537,11 +537,10 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
537537

538538
memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
539539

540-
dsfield = ipv4_get_dsfield(iph);
541-
542540
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
543-
fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
544-
& IPV6_TCLASS_MASK;
541+
dsfield = ipv4_get_dsfield(iph);
542+
else
543+
dsfield = ip6_tclass(t->parms.flowinfo);
545544
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
546545
fl6.flowi6_mark = skb->mark;
547546
else
@@ -598,9 +597,11 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
598597

599598
memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
600599

601-
dsfield = ipv6_get_dsfield(ipv6h);
602600
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
603-
fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
601+
dsfield = ipv6_get_dsfield(ipv6h);
602+
else
603+
dsfield = ip6_tclass(t->parms.flowinfo);
604+
604605
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
605606
fl6.flowlabel |= ip6_flowlabel(ipv6h);
606607
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)

net/ipv6/ip6_tunnel.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
11961196
skb_push(skb, sizeof(struct ipv6hdr));
11971197
skb_reset_network_header(skb);
11981198
ipv6h = ipv6_hdr(skb);
1199-
ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield),
1199+
ip6_flow_hdr(ipv6h, dsfield,
12001200
ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6));
12011201
ipv6h->hop_limit = hop_limit;
12021202
ipv6h->nexthdr = proto;
@@ -1231,8 +1231,6 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
12311231
if (tproto != IPPROTO_IPIP && tproto != 0)
12321232
return -1;
12331233

1234-
dsfield = ipv4_get_dsfield(iph);
1235-
12361234
if (t->parms.collect_md) {
12371235
struct ip_tunnel_info *tun_info;
12381236
const struct ip_tunnel_key *key;
@@ -1246,6 +1244,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
12461244
fl6.flowi6_proto = IPPROTO_IPIP;
12471245
fl6.daddr = key->u.ipv6.dst;
12481246
fl6.flowlabel = key->label;
1247+
dsfield = ip6_tclass(key->label);
12491248
} else {
12501249
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
12511250
encap_limit = t->parms.encap_limit;
@@ -1254,8 +1253,9 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
12541253
fl6.flowi6_proto = IPPROTO_IPIP;
12551254

12561255
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
1257-
fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
1258-
& IPV6_TCLASS_MASK;
1256+
dsfield = ipv4_get_dsfield(iph);
1257+
else
1258+
dsfield = ip6_tclass(t->parms.flowinfo);
12591259
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
12601260
fl6.flowi6_mark = skb->mark;
12611261
else
@@ -1267,6 +1267,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
12671267
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
12681268
return -1;
12691269

1270+
dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
1271+
12701272
skb_set_inner_ipproto(skb, IPPROTO_IPIP);
12711273

12721274
err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1300,8 +1302,6 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
13001302
ip6_tnl_addr_conflict(t, ipv6h))
13011303
return -1;
13021304

1303-
dsfield = ipv6_get_dsfield(ipv6h);
1304-
13051305
if (t->parms.collect_md) {
13061306
struct ip_tunnel_info *tun_info;
13071307
const struct ip_tunnel_key *key;
@@ -1315,6 +1315,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
13151315
fl6.flowi6_proto = IPPROTO_IPV6;
13161316
fl6.daddr = key->u.ipv6.dst;
13171317
fl6.flowlabel = key->label;
1318+
dsfield = ip6_tclass(key->label);
13181319
} else {
13191320
offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
13201321
/* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
@@ -1337,7 +1338,9 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
13371338
fl6.flowi6_proto = IPPROTO_IPV6;
13381339

13391340
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
1340-
fl6.flowlabel |= (*(__be32 *)ipv6h & IPV6_TCLASS_MASK);
1341+
dsfield = ipv6_get_dsfield(ipv6h);
1342+
else
1343+
dsfield = ip6_tclass(t->parms.flowinfo);
13411344
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
13421345
fl6.flowlabel |= ip6_flowlabel(ipv6h);
13431346
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
@@ -1351,6 +1354,8 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
13511354
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
13521355
return -1;
13531356

1357+
dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
1358+
13541359
skb_set_inner_ipproto(skb, IPPROTO_IPV6);
13551360

13561361
err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,

0 commit comments

Comments
 (0)