aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Dawson <petedaws@gmail.com>2017-05-25 16:35:18 -0400
committerDavid S. Miller <davem@davemloft.net>2017-05-26 14:54:39 -0400
commit0e9a709560dbcfbace8bf4019dc5298619235891 (patch)
tree47fbb75e52124db162f54e605912f60a36caf20f
parent804ec7ebe8ea003999ca8d1bfc499edc6a9e07df (diff)
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 90427ef5d2a4 ("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: 90427ef5d2a4 ("ipv6: fix flow labels when the traffic class is non-0") Signed-off-by: Peter Dawson <peter.a.dawson@boeing.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/ip6_gre.c13
-rw-r--r--net/ipv6/ip6_tunnel.c21
2 files changed, 20 insertions, 14 deletions
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 8d128ba79b66..0c5b4caa1949 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -537,11 +537,10 @@ static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev)
537 537
538 memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); 538 memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
539 539
540 dsfield = ipv4_get_dsfield(iph);
541
542 if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) 540 if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
543 fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) 541 dsfield = ipv4_get_dsfield(iph);
544 & IPV6_TCLASS_MASK; 542 else
543 dsfield = ip6_tclass(t->parms.flowinfo);
545 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) 544 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
546 fl6.flowi6_mark = skb->mark; 545 fl6.flowi6_mark = skb->mark;
547 else 546 else
@@ -598,9 +597,11 @@ static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev)
598 597
599 memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); 598 memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
600 599
601 dsfield = ipv6_get_dsfield(ipv6h);
602 if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) 600 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
604 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) 605 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
605 fl6.flowlabel |= ip6_flowlabel(ipv6h); 606 fl6.flowlabel |= ip6_flowlabel(ipv6h);
606 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) 607 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 6eb2ae507500..7ae6c503f1ca 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1196,7 +1196,7 @@ route_lookup:
1196 skb_push(skb, sizeof(struct ipv6hdr)); 1196 skb_push(skb, sizeof(struct ipv6hdr));
1197 skb_reset_network_header(skb); 1197 skb_reset_network_header(skb);
1198 ipv6h = ipv6_hdr(skb); 1198 ipv6h = ipv6_hdr(skb);
1199 ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), 1199 ip6_flow_hdr(ipv6h, dsfield,
1200 ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6)); 1200 ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6));
1201 ipv6h->hop_limit = hop_limit; 1201 ipv6h->hop_limit = hop_limit;
1202 ipv6h->nexthdr = proto; 1202 ipv6h->nexthdr = proto;
@@ -1231,8 +1231,6 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1231 if (tproto != IPPROTO_IPIP && tproto != 0) 1231 if (tproto != IPPROTO_IPIP && tproto != 0)
1232 return -1; 1232 return -1;
1233 1233
1234 dsfield = ipv4_get_dsfield(iph);
1235
1236 if (t->parms.collect_md) { 1234 if (t->parms.collect_md) {
1237 struct ip_tunnel_info *tun_info; 1235 struct ip_tunnel_info *tun_info;
1238 const struct ip_tunnel_key *key; 1236 const struct ip_tunnel_key *key;
@@ -1246,6 +1244,7 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1246 fl6.flowi6_proto = IPPROTO_IPIP; 1244 fl6.flowi6_proto = IPPROTO_IPIP;
1247 fl6.daddr = key->u.ipv6.dst; 1245 fl6.daddr = key->u.ipv6.dst;
1248 fl6.flowlabel = key->label; 1246 fl6.flowlabel = key->label;
1247 dsfield = ip6_tclass(key->label);
1249 } else { 1248 } else {
1250 if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) 1249 if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
1251 encap_limit = t->parms.encap_limit; 1250 encap_limit = t->parms.encap_limit;
@@ -1254,8 +1253,9 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1254 fl6.flowi6_proto = IPPROTO_IPIP; 1253 fl6.flowi6_proto = IPPROTO_IPIP;
1255 1254
1256 if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) 1255 if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
1257 fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) 1256 dsfield = ipv4_get_dsfield(iph);
1258 & IPV6_TCLASS_MASK; 1257 else
1258 dsfield = ip6_tclass(t->parms.flowinfo);
1259 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) 1259 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
1260 fl6.flowi6_mark = skb->mark; 1260 fl6.flowi6_mark = skb->mark;
1261 else 1261 else
@@ -1267,6 +1267,8 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1267 if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) 1267 if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
1268 return -1; 1268 return -1;
1269 1269
1270 dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
1271
1270 skb_set_inner_ipproto(skb, IPPROTO_IPIP); 1272 skb_set_inner_ipproto(skb, IPPROTO_IPIP);
1271 1273
1272 err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, 1274 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)
1300 ip6_tnl_addr_conflict(t, ipv6h)) 1302 ip6_tnl_addr_conflict(t, ipv6h))
1301 return -1; 1303 return -1;
1302 1304
1303 dsfield = ipv6_get_dsfield(ipv6h);
1304
1305 if (t->parms.collect_md) { 1305 if (t->parms.collect_md) {
1306 struct ip_tunnel_info *tun_info; 1306 struct ip_tunnel_info *tun_info;
1307 const struct ip_tunnel_key *key; 1307 const struct ip_tunnel_key *key;
@@ -1315,6 +1315,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1315 fl6.flowi6_proto = IPPROTO_IPV6; 1315 fl6.flowi6_proto = IPPROTO_IPV6;
1316 fl6.daddr = key->u.ipv6.dst; 1316 fl6.daddr = key->u.ipv6.dst;
1317 fl6.flowlabel = key->label; 1317 fl6.flowlabel = key->label;
1318 dsfield = ip6_tclass(key->label);
1318 } else { 1319 } else {
1319 offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); 1320 offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
1320 /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */ 1321 /* 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)
1337 fl6.flowi6_proto = IPPROTO_IPV6; 1338 fl6.flowi6_proto = IPPROTO_IPV6;
1338 1339
1339 if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) 1340 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);
1341 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) 1344 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
1342 fl6.flowlabel |= ip6_flowlabel(ipv6h); 1345 fl6.flowlabel |= ip6_flowlabel(ipv6h);
1343 if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) 1346 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)
1351 if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) 1354 if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
1352 return -1; 1355 return -1;
1353 1356
1357 dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
1358
1354 skb_set_inner_ipproto(skb, IPPROTO_IPV6); 1359 skb_set_inner_ipproto(skb, IPPROTO_IPV6);
1355 1360
1356 err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, 1361 err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,