This work adds support for setting the IPv6 flow label for geneve per device and through collect metadata (ip_tunnel_key) frontends. Also here, the geneve dst cache does not need any special considerations, for the cases where caches can be used, the label is static per cache.
Unified · Split
| @@ -68,6 +68,7 @@ struct geneve_dev { · 67 unmodified lines | ||
| 68 | 68 | u8 tos; /* TOS override */ |
| 69 | 69 | union geneve_addr remote; /* IP address for link partner */ |
| 70 | 70 | struct list_head next; /* geneve's per namespace list */ |
| 71 | + __be32 label; /* IPv6 flowlabel override */ | |
| 71 | 72 | __be16 dst_port; |
| 72 | 73 | bool collect_md; |
| 73 | 74 | struct gro_cells gro_cells; |
| @@ -846,6 +847,7 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, · 772 unmodified lines | ||
| 846 | 847 | fl6->daddr = info->key.u.ipv6.dst; |
| 847 | 848 | fl6->saddr = info->key.u.ipv6.src; |
| 848 | 849 | fl6->flowi6_tos = RT_TOS(info->key.tos); |
| 850 | + fl6->flowlabel = info->key.label; | |
| 849 | 851 | dst_cache = &info->dst_cache; |
| 850 | 852 | } else { |
| 851 | 853 | prio = geneve->tos; |
| @@ -857,6 +859,7 @@ static struct dst_entry *geneve_get_v6_dst(struct sk_buff *skb, · 5 unmodified lines | ||
| 857 | 859 | } |
| 858 | 860 | |
| 859 | 861 | fl6->flowi6_tos = RT_TOS(prio); |
| 862 | + fl6->flowlabel = geneve->label; | |
| 860 | 863 | fl6->daddr = geneve->remote.sin6.sin6_addr; |
| 861 | 864 | dst_cache = &geneve->dst_cache; |
| 862 | 865 | } |
| @@ -998,6 +1001,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, · 135 unmodified lines | ||
| 998 | 1001 | struct flowi6 fl6; |
| 999 | 1002 | __u8 prio, ttl; |
| 1000 | 1003 | __be16 sport; |
| 1004 | + __be32 label; | |
| 1001 | 1005 | bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); |
| 1002 | 1006 | u32 flags = geneve->flags; |
| 1003 | 1007 | |
| @@ -1041,6 +1045,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, · 37 unmodified lines | ||
| 1041 | 1045 | |
| 1042 | 1046 | prio = ip_tunnel_ecn_encap(key->tos, iip, skb); |
| 1043 | 1047 | ttl = key->ttl; |
| 1048 | + label = info->key.label; | |
| 1044 | 1049 | } else { |
| 1045 | 1050 | err = geneve6_build_skb(dst, skb, 0, geneve->vni, |
| 1046 | 1051 | 0, NULL, flags, xnet); |
| @@ -1052,9 +1057,11 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, · 5 unmodified lines | ||
| 1052 | 1057 | if (!ttl && ipv6_addr_is_multicast(&fl6.daddr)) |
| 1053 | 1058 | ttl = 1; |
| 1054 | 1059 | ttl = ttl ? : ip6_dst_hoplimit(dst); |
| 1060 | + label = geneve->label; | |
| 1055 | 1061 | } |
| 1062 | + | |
| 1056 | 1063 | udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev, |
| 1057 | − &fl6.saddr, &fl6.daddr, prio, ttl, 0, | |
| 1064 | + &fl6.saddr, &fl6.daddr, prio, ttl, label, | |
| 1058 | 1065 | sport, geneve->dst_port, |
| 1059 | 1066 | !!(flags & GENEVE_F_UDP_ZERO_CSUM6_TX)); |
| 1060 | 1067 | return NETDEV_TX_OK; |
| @@ -1238,6 +1245,7 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = { · 177 unmodified lines | ||
| 1238 | 1245 | [IFLA_GENEVE_REMOTE6] = { .len = sizeof(struct in6_addr) }, |
| 1239 | 1246 | [IFLA_GENEVE_TTL] = { .type = NLA_U8 }, |
| 1240 | 1247 | [IFLA_GENEVE_TOS] = { .type = NLA_U8 }, |
| 1248 | + [IFLA_GENEVE_LABEL] = { .type = NLA_U32 }, | |
| 1241 | 1249 | [IFLA_GENEVE_PORT] = { .type = NLA_U16 }, |
| 1242 | 1250 | [IFLA_GENEVE_COLLECT_METADATA] = { .type = NLA_FLAG }, |
| 1243 | 1251 | [IFLA_GENEVE_UDP_CSUM] = { .type = NLA_U8 }, |
| @@ -1295,8 +1303,8 @@ static struct geneve_dev *geneve_find_dev(struct geneve_net *gn, · 51 unmodified lines | ||
| 1295 | 1303 | |
| 1296 | 1304 | static int geneve_configure(struct net *net, struct net_device *dev, |
| 1297 | 1305 | union geneve_addr *remote, |
| 1298 | − __u32 vni, __u8 ttl, __u8 tos, __be16 dst_port, | |
| 1299 | − bool metadata, u32 flags) | |
| 1306 | + __u32 vni, __u8 ttl, __u8 tos, __be32 label, | |
| 1307 | + __be16 dst_port, bool metadata, u32 flags) | |
| 1300 | 1308 | { |
| 1301 | 1309 | struct geneve_net *gn = net_generic(net, geneve_net_id); |
| 1302 | 1310 | struct geneve_dev *t, *geneve = netdev_priv(dev); |
| @@ -1306,7 +1314,7 @@ static int geneve_configure(struct net *net, struct net_device *dev, · 3 unmodified lines | ||
| 1306 | 1314 | if (!remote) |
| 1307 | 1315 | return -EINVAL; |
| 1308 | 1316 | if (metadata && |
| 1309 | − (remote->sa.sa_family != AF_UNSPEC || vni || tos || ttl)) | |
| 1317 | + (remote->sa.sa_family != AF_UNSPEC || vni || tos || ttl || label)) | |
| 1310 | 1318 | return -EINVAL; |
| 1311 | 1319 | |
| 1312 | 1320 | geneve->net = net; |
| @@ -1321,10 +1329,14 @@ static int geneve_configure(struct net *net, struct net_device *dev, · 8 unmodified lines | ||
| 1321 | 1329 | (remote->sa.sa_family == AF_INET6 && |
| 1322 | 1330 | ipv6_addr_is_multicast(&remote->sin6.sin6_addr))) |
| 1323 | 1331 | return -EINVAL; |
| 1332 | + if (label && remote->sa.sa_family != AF_INET6) | |
| 1333 | + return -EINVAL; | |
| 1334 | + | |
| 1324 | 1335 | geneve->remote = *remote; |
| 1325 | 1336 | |
| 1326 | 1337 | geneve->ttl = ttl; |
| 1327 | 1338 | geneve->tos = tos; |
| 1339 | + geneve->label = label; | |
| 1328 | 1340 | geneve->dst_port = dst_port; |
| 1329 | 1341 | geneve->collect_md = metadata; |
| 1330 | 1342 | geneve->flags = flags; |
| @@ -1367,6 +1379,7 @@ static int geneve_newlink(struct net *net, struct net_device *dev, · 36 unmodified lines | ||
| 1367 | 1379 | __u8 ttl = 0, tos = 0; |
| 1368 | 1380 | bool metadata = false; |
| 1369 | 1381 | union geneve_addr remote = geneve_remote_unspec; |
| 1382 | + __be32 label = 0; | |
| 1370 | 1383 | __u32 vni = 0; |
| 1371 | 1384 | u32 flags = 0; |
| 1372 | 1385 | |
| @@ -1403,6 +1416,10 @@ static int geneve_newlink(struct net *net, struct net_device *dev, · 30 unmodified lines | ||
| 1403 | 1416 | if (data[IFLA_GENEVE_TOS]) |
| 1404 | 1417 | tos = nla_get_u8(data[IFLA_GENEVE_TOS]); |
| 1405 | 1418 | |
| 1419 | + if (data[IFLA_GENEVE_LABEL]) | |
| 1420 | + label = nla_get_be32(data[IFLA_GENEVE_LABEL]) & | |
| 1421 | + IPV6_FLOWLABEL_MASK; | |
| 1422 | + | |
| 1406 | 1423 | if (data[IFLA_GENEVE_PORT]) |
| 1407 | 1424 | dst_port = nla_get_be16(data[IFLA_GENEVE_PORT]); |
| 1408 | 1425 | |
| @@ -1421,8 +1438,8 @@ static int geneve_newlink(struct net *net, struct net_device *dev, · 12 unmodified lines | ||
| 1421 | 1438 | nla_get_u8(data[IFLA_GENEVE_UDP_ZERO_CSUM6_RX])) |
| 1422 | 1439 | flags |= GENEVE_F_UDP_ZERO_CSUM6_RX; |
| 1423 | 1440 | |
| 1424 | − return geneve_configure(net, dev, &remote, vni, ttl, tos, dst_port, | |
| 1425 | − metadata, flags); | |
| 1441 | + return geneve_configure(net, dev, &remote, vni, ttl, tos, label, | |
| 1442 | + dst_port, metadata, flags); | |
| 1426 | 1443 | } |
| 1427 | 1444 | |
| 1428 | 1445 | static void geneve_dellink(struct net_device *dev, struct list_head *head) |
| @@ -1439,6 +1456,7 @@ static size_t geneve_get_size(const struct net_device *dev) · 10 unmodified lines | ||
| 1439 | 1456 | nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_REMOTE{6} */ |
| 1440 | 1457 | nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL */ |
| 1441 | 1458 | nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TOS */ |
| 1459 | + nla_total_size(sizeof(__be32)) + /* IFLA_GENEVE_LABEL */ | |
| 1442 | 1460 | nla_total_size(sizeof(__be16)) + /* IFLA_GENEVE_PORT */ |
| 1443 | 1461 | nla_total_size(0) + /* IFLA_GENEVE_COLLECT_METADATA */ |
| 1444 | 1462 | nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_CSUM */ |
| @@ -1469,7 +1487,8 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) · 24 unmodified lines | ||
| 1469 | 1487 | } |
| 1470 | 1488 | |
| 1471 | 1489 | if (nla_put_u8(skb, IFLA_GENEVE_TTL, geneve->ttl) || |
| 1472 | − nla_put_u8(skb, IFLA_GENEVE_TOS, geneve->tos)) | |
| 1490 | + nla_put_u8(skb, IFLA_GENEVE_TOS, geneve->tos) || | |
| 1491 | + nla_put_be32(skb, IFLA_GENEVE_LABEL, geneve->label)) | |
| 1473 | 1492 | goto nla_put_failure; |
| 1474 | 1493 | |
| 1475 | 1494 | if (nla_put_be16(skb, IFLA_GENEVE_PORT, geneve->dst_port)) |
| @@ -1521,7 +1540,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, · 45 unmodified lines | ||
| 1521 | 1540 | return dev; |
| 1522 | 1541 | |
| 1523 | 1542 | err = geneve_configure(net, dev, &geneve_remote_unspec, |
| 1524 | − 0, 0, 0, htons(dst_port), true, | |
| 1543 | + 0, 0, 0, 0, htons(dst_port), true, | |
| 1525 | 1544 | GENEVE_F_UDP_ZERO_CSUM6_RX); |
| 1526 | 1545 | if (err) |
| 1527 | 1546 | goto err; |
| @@ -479,6 +479,7 @@ enum { · 478 unmodified lines | ||
| 479 | 479 | IFLA_GENEVE_UDP_CSUM, |
| 480 | 480 | IFLA_GENEVE_UDP_ZERO_CSUM6_TX, |
| 481 | 481 | IFLA_GENEVE_UDP_ZERO_CSUM6_RX, |
| 482 | + IFLA_GENEVE_LABEL, | |
| 482 | 483 | __IFLA_GENEVE_MAX |
| 483 | 484 | }; |
| 484 | 485 | #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) |