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 | u8 tos; /* TOS override */ | 68 | u8 tos; /* TOS override */ |
| 69 | union geneve_addr remote; /* IP address for link partner */ | 69 | union geneve_addr remote; /* IP address for link partner */ |
| 70 | struct list_head next; /* geneve's per namespace list */ | 70 | struct list_head next; /* geneve's per namespace list */ |
| 71 | __be32 label; /* IPv6 flowlabel override */ | ||
| 71 | __be16 dst_port; | 72 | __be16 dst_port; |
| 72 | bool collect_md; | 73 | bool collect_md; |
| 73 | struct gro_cells gro_cells; | 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 | fl6->daddr = info->key.u.ipv6.dst; | 847 | fl6->daddr = info->key.u.ipv6.dst; |
| 847 | fl6->saddr = info->key.u.ipv6.src; | 848 | fl6->saddr = info->key.u.ipv6.src; |
| 848 | fl6->flowi6_tos = RT_TOS(info->key.tos); | 849 | fl6->flowi6_tos = RT_TOS(info->key.tos); |
| 850 | fl6->flowlabel = info->key.label; | ||
| 849 | dst_cache = &info->dst_cache; | 851 | dst_cache = &info->dst_cache; |
| 850 | } else { | 852 | } else { |
| 851 | prio = geneve->tos; | 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 | fl6->flowi6_tos = RT_TOS(prio); | 861 | fl6->flowi6_tos = RT_TOS(prio); |
| 862 | fl6->flowlabel = geneve->label; | ||
| 860 | fl6->daddr = geneve->remote.sin6.sin6_addr; | 863 | fl6->daddr = geneve->remote.sin6.sin6_addr; |
| 861 | dst_cache = &geneve->dst_cache; | 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 | struct flowi6 fl6; | 1001 | struct flowi6 fl6; |
| 999 | __u8 prio, ttl; | 1002 | __u8 prio, ttl; |
| 1000 | __be16 sport; | 1003 | __be16 sport; |
| 1004 | __be32 label; | ||
| 1001 | bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); | 1005 | bool xnet = !net_eq(geneve->net, dev_net(geneve->dev)); |
| 1002 | u32 flags = geneve->flags; | 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 | prio = ip_tunnel_ecn_encap(key->tos, iip, skb); | 1046 | prio = ip_tunnel_ecn_encap(key->tos, iip, skb); |
| 1043 | ttl = key->ttl; | 1047 | ttl = key->ttl; |
| 1048 | label = info->key.label; | ||
| 1044 | } else { | 1049 | } else { |
| 1045 | err = geneve6_build_skb(dst, skb, 0, geneve->vni, | 1050 | err = geneve6_build_skb(dst, skb, 0, geneve->vni, |
| 1046 | 0, NULL, flags, xnet); | 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 | if (!ttl && ipv6_addr_is_multicast(&fl6.daddr)) | 1057 | if (!ttl && ipv6_addr_is_multicast(&fl6.daddr)) |
| 1053 | ttl = 1; | 1058 | ttl = 1; |
| 1054 | ttl = ttl ? : ip6_dst_hoplimit(dst); | 1059 | ttl = ttl ? : ip6_dst_hoplimit(dst); |
| 1060 | label = geneve->label; | ||
| 1055 | } | 1061 | } |
| 1062 | |||
| 1056 | udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev, | 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 | sport, geneve->dst_port, | 1065 | sport, geneve->dst_port, |
| 1059 | !!(flags & GENEVE_F_UDP_ZERO_CSUM6_TX)); | 1066 | !!(flags & GENEVE_F_UDP_ZERO_CSUM6_TX)); |
| 1060 | return NETDEV_TX_OK; | 1067 | return NETDEV_TX_OK; |
| @@ -1238,6 +1245,7 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = { · 177 unmodified lines | |||
| 1238 | [IFLA_GENEVE_REMOTE6] = { .len = sizeof(struct in6_addr) }, | 1245 | [IFLA_GENEVE_REMOTE6] = { .len = sizeof(struct in6_addr) }, |
| 1239 | [IFLA_GENEVE_TTL] = { .type = NLA_U8 }, | 1246 | [IFLA_GENEVE_TTL] = { .type = NLA_U8 }, |
| 1240 | [IFLA_GENEVE_TOS] = { .type = NLA_U8 }, | 1247 | [IFLA_GENEVE_TOS] = { .type = NLA_U8 }, |
| 1248 | [IFLA_GENEVE_LABEL] = { .type = NLA_U32 }, | ||
| 1241 | [IFLA_GENEVE_PORT] = { .type = NLA_U16 }, | 1249 | [IFLA_GENEVE_PORT] = { .type = NLA_U16 }, |
| 1242 | [IFLA_GENEVE_COLLECT_METADATA] = { .type = NLA_FLAG }, | 1250 | [IFLA_GENEVE_COLLECT_METADATA] = { .type = NLA_FLAG }, |
| 1243 | [IFLA_GENEVE_UDP_CSUM] = { .type = NLA_U8 }, | 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 | static int geneve_configure(struct net *net, struct net_device *dev, | 1304 | static int geneve_configure(struct net *net, struct net_device *dev, |
| 1297 | union geneve_addr *remote, | 1305 | union geneve_addr *remote, |
| 1298 | __u32 vni, __u8 ttl, __u8 tos, __be16 dst_port, | 1306 | __u32 vni, __u8 ttl, __u8 tos, __be32 label, |
| 1299 | bool metadata, u32 flags) | 1307 | __be16 dst_port, bool metadata, u32 flags) |
| 1300 | { | 1308 | { |
| 1301 | struct geneve_net *gn = net_generic(net, geneve_net_id); | 1309 | struct geneve_net *gn = net_generic(net, geneve_net_id); |
| 1302 | struct geneve_dev *t, *geneve = netdev_priv(dev); | 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 | if (!remote) | 1314 | if (!remote) |
| 1307 | return -EINVAL; | 1315 | return -EINVAL; |
| 1308 | if (metadata && | 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 | return -EINVAL; | 1318 | return -EINVAL; |
| 1311 | 1319 | ||
| 1312 | geneve->net = net; | 1320 | geneve->net = net; |
| @@ -1321,10 +1329,14 @@ static int geneve_configure(struct net *net, struct net_device *dev, · 8 unmodified lines | |||
| 1321 | (remote->sa.sa_family == AF_INET6 && | 1329 | (remote->sa.sa_family == AF_INET6 && |
| 1322 | ipv6_addr_is_multicast(&remote->sin6.sin6_addr))) | 1330 | ipv6_addr_is_multicast(&remote->sin6.sin6_addr))) |
| 1323 | return -EINVAL; | 1331 | return -EINVAL; |
| 1332 | if (label && remote->sa.sa_family != AF_INET6) | ||
| 1333 | return -EINVAL; | ||
| 1334 | |||
| 1324 | geneve->remote = *remote; | 1335 | geneve->remote = *remote; |
| 1325 | 1336 | ||
| 1326 | geneve->ttl = ttl; | 1337 | geneve->ttl = ttl; |
| 1327 | geneve->tos = tos; | 1338 | geneve->tos = tos; |
| 1339 | geneve->label = label; | ||
| 1328 | geneve->dst_port = dst_port; | 1340 | geneve->dst_port = dst_port; |
| 1329 | geneve->collect_md = metadata; | 1341 | geneve->collect_md = metadata; |
| 1330 | geneve->flags = flags; | 1342 | geneve->flags = flags; |
| @@ -1367,6 +1379,7 @@ static int geneve_newlink(struct net *net, struct net_device *dev, · 36 unmodified lines | |||
| 1367 | __u8 ttl = 0, tos = 0; | 1379 | __u8 ttl = 0, tos = 0; |
| 1368 | bool metadata = false; | 1380 | bool metadata = false; |
| 1369 | union geneve_addr remote = geneve_remote_unspec; | 1381 | union geneve_addr remote = geneve_remote_unspec; |
| 1382 | __be32 label = 0; | ||
| 1370 | __u32 vni = 0; | 1383 | __u32 vni = 0; |
| 1371 | u32 flags = 0; | 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 | if (data[IFLA_GENEVE_TOS]) | 1416 | if (data[IFLA_GENEVE_TOS]) |
| 1404 | tos = nla_get_u8(data[IFLA_GENEVE_TOS]); | 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 | if (data[IFLA_GENEVE_PORT]) | 1423 | if (data[IFLA_GENEVE_PORT]) |
| 1407 | dst_port = nla_get_be16(data[IFLA_GENEVE_PORT]); | 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 | nla_get_u8(data[IFLA_GENEVE_UDP_ZERO_CSUM6_RX])) | 1438 | nla_get_u8(data[IFLA_GENEVE_UDP_ZERO_CSUM6_RX])) |
| 1422 | flags |= GENEVE_F_UDP_ZERO_CSUM6_RX; | 1439 | flags |= GENEVE_F_UDP_ZERO_CSUM6_RX; |
| 1423 | 1440 | ||
| 1424 | return geneve_configure(net, dev, &remote, vni, ttl, tos, dst_port, | 1441 | return geneve_configure(net, dev, &remote, vni, ttl, tos, label, |
| 1425 | metadata, flags); | 1442 | dst_port, metadata, flags); |
| 1426 | } | 1443 | } |
| 1427 | 1444 | ||
| 1428 | static void geneve_dellink(struct net_device *dev, struct list_head *head) | 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 | nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_REMOTE{6} */ | 1456 | nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_REMOTE{6} */ |
| 1440 | nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL */ | 1457 | nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL */ |
| 1441 | nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TOS */ | 1458 | nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TOS */ |
| 1459 | nla_total_size(sizeof(__be32)) + /* IFLA_GENEVE_LABEL */ | ||
| 1442 | nla_total_size(sizeof(__be16)) + /* IFLA_GENEVE_PORT */ | 1460 | nla_total_size(sizeof(__be16)) + /* IFLA_GENEVE_PORT */ |
| 1443 | nla_total_size(0) + /* IFLA_GENEVE_COLLECT_METADATA */ | 1461 | nla_total_size(0) + /* IFLA_GENEVE_COLLECT_METADATA */ |
| 1444 | nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_CSUM */ | 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 | if (nla_put_u8(skb, IFLA_GENEVE_TTL, geneve->ttl) || | 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 | goto nla_put_failure; | 1492 | goto nla_put_failure; |
| 1474 | 1493 | ||
| 1475 | if (nla_put_be16(skb, IFLA_GENEVE_PORT, geneve->dst_port)) | 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 | return dev; | 1540 | return dev; |
| 1522 | 1541 | ||
| 1523 | err = geneve_configure(net, dev, &geneve_remote_unspec, | 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 | GENEVE_F_UDP_ZERO_CSUM6_RX); | 1544 | GENEVE_F_UDP_ZERO_CSUM6_RX); |
| 1526 | if (err) | 1545 | if (err) |
| 1527 | goto err; | 1546 | goto err; |
| @@ -479,6 +479,7 @@ enum { · 478 unmodified lines | |||
| 479 | IFLA_GENEVE_UDP_CSUM, | 479 | IFLA_GENEVE_UDP_CSUM, |
| 480 | IFLA_GENEVE_UDP_ZERO_CSUM6_TX, | 480 | IFLA_GENEVE_UDP_ZERO_CSUM6_TX, |
| 481 | IFLA_GENEVE_UDP_ZERO_CSUM6_RX, | 481 | IFLA_GENEVE_UDP_ZERO_CSUM6_RX, |
| 482 | IFLA_GENEVE_LABEL, | ||
| 482 | __IFLA_GENEVE_MAX | 483 | __IFLA_GENEVE_MAX |
| 483 | }; | 484 | }; |
| 484 | #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) | 485 | #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) |