X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ip%2Fiplink_vxlan.c;h=497affc0c90b36492ddb7c1259e4760679fe1739;hb=25c6339b223f17d1603702c0c87f06b252bb4949;hp=b9c335d3e189ece189600d8fba94a9920ca445a4;hpb=375560c4ab61cae567afbb9a64036a009cfeaecc;p=mirror_iproute2.git diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c index b9c335d3..497affc0 100644 --- a/ip/iplink_vxlan.c +++ b/ip/iplink_vxlan.c @@ -31,6 +31,7 @@ static void print_explain(FILE *f) " [ local ADDR ]\n" " [ ttl TTL ]\n" " [ tos TOS ]\n" + " [ df DF ]\n" " [ flowlabel LABEL ]\n" " [ dev PHYS_DEV ]\n" " [ dstport PORT ]\n" @@ -51,7 +52,8 @@ static void print_explain(FILE *f) "Where: VNI := 0-16777215\n" " ADDR := { IP_ADDRESS | any }\n" " TOS := { NUMBER | inherit }\n" - " TTL := { 1..255 | inherit }\n" + " TTL := { 1..255 | auto | inherit }\n" + " DF := { unset | set | inherit }\n" " LABEL := 0-1048575\n" ); } @@ -74,17 +76,20 @@ static void check_duparg(__u64 *attrs, int type, const char *key, static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { + inet_prefix saddr, daddr; __u32 vni = 0; - __u32 gaddr = 0; - __u32 daddr = 0; - struct in6_addr gaddr6 = IN6ADDR_ANY_INIT; - struct in6_addr daddr6 = IN6ADDR_ANY_INIT; __u8 learning = 1; __u16 dstport = 0; __u8 metadata = 0; __u64 attrs = 0; bool set_op = (n->nlmsg_type == RTM_NEWLINK && !(n->nlmsg_flags & NLM_F_CREATE)); + bool selected_family = false; + + saddr.family = daddr.family = AF_UNSPEC; + + inet_prefix_reset(&saddr); + inet_prefix_reset(&daddr); while (argc > 0) { if (!matches(*argv, "id") || @@ -98,65 +103,41 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, vni >= 1u << 24) invarg("invalid id", *argv); } else if (!matches(*argv, "group")) { - if (daddr || !IN6_IS_ADDR_UNSPECIFIED(&daddr6)) { + if (is_addrtype_inet_not_multi(&daddr)) { fprintf(stderr, "vxlan: both group and remote"); fprintf(stderr, " cannot be specified\n"); return -1; } NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_GROUP, "group", *argv); - if (!inet_get_addr(*argv, &gaddr, &gaddr6)) { - fprintf(stderr, "Invalid address \"%s\"\n", *argv); - return -1; - } - if (!IN6_IS_ADDR_MULTICAST(&gaddr6) && !IN_MULTICAST(ntohl(gaddr))) + get_addr(&daddr, *argv, saddr.family); + if (!is_addrtype_inet_multi(&daddr)) invarg("invalid group address", *argv); } else if (!matches(*argv, "remote")) { - if (gaddr || !IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) { + if (is_addrtype_inet_multi(&daddr)) { fprintf(stderr, "vxlan: both group and remote"); fprintf(stderr, " cannot be specified\n"); return -1; } NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_GROUP, "remote", *argv); - if (!inet_get_addr(*argv, &daddr, &daddr6)) { - fprintf(stderr, "Invalid address \"%s\"\n", *argv); - return -1; - } - if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr))) + get_addr(&daddr, *argv, saddr.family); + if (!is_addrtype_inet_not_multi(&daddr)) invarg("invalid remote address", *argv); } else if (!matches(*argv, "local")) { - __u32 saddr = 0; - struct in6_addr saddr6 = IN6ADDR_ANY_INIT; - NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_LOCAL, "local", *argv); - if (strcmp(*argv, "any")) { - if (!inet_get_addr(*argv, &saddr, &saddr6)) { - fprintf(stderr, "Invalid address \"%s\"\n", *argv); - return -1; - } - } - - if (IN_MULTICAST(ntohl(saddr)) || IN6_IS_ADDR_MULTICAST(&saddr6)) + get_addr(&saddr, *argv, daddr.family); + if (!is_addrtype_inet_not_multi(&saddr)) invarg("invalid local address", *argv); - - if (saddr) - addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4); - else if (!IN6_IS_ADDR_UNSPECIFIED(&saddr6)) - addattr_l(n, 1024, IFLA_VXLAN_LOCAL6, &saddr6, - sizeof(struct in6_addr)); } else if (!matches(*argv, "dev")) { unsigned int link; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_LINK, "dev", *argv); - link = if_nametoindex(*argv); - if (link == 0) { - fprintf(stderr, "Cannot find device \"%s\"\n", - *argv); - exit(-1); - } + link = ll_name_to_index(*argv); + if (!link) + exit(nodev(*argv)); addattr32(n, 1024, IFLA_VXLAN_LINK, link); } else if (!matches(*argv, "ttl") || !matches(*argv, "hoplimit")) { @@ -165,14 +146,18 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_TTL, "ttl", *argv); - if (strcmp(*argv, "inherit") != 0) { + if (strcmp(*argv, "inherit") == 0) { + addattr(n, 1024, IFLA_VXLAN_TTL_INHERIT); + } else if (strcmp(*argv, "auto") == 0) { + addattr8(n, 1024, IFLA_VXLAN_TTL, ttl); + } else { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL", *argv); if (uval > 255) invarg("TTL must be <= 255", *argv); ttl = uval; + addattr8(n, 1024, IFLA_VXLAN_TTL, ttl); } - addattr8(n, 1024, IFLA_VXLAN_TTL, ttl); } else if (!matches(*argv, "tos") || !matches(*argv, "dsfield")) { __u32 uval; @@ -187,6 +172,22 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, } else tos = 1; addattr8(n, 1024, IFLA_VXLAN_TOS, tos); + } else if (!matches(*argv, "df")) { + enum ifla_vxlan_df df; + + NEXT_ARG(); + check_duparg(&attrs, IFLA_VXLAN_DF, "df", *argv); + if (strcmp(*argv, "unset") == 0) + df = VXLAN_DF_UNSET; + else if (strcmp(*argv, "set") == 0) + df = VXLAN_DF_SET; + else if (strcmp(*argv, "inherit") == 0) + df = VXLAN_DF_INHERIT; + else + invarg("DF must be 'unset', 'set' or 'inherit'", + *argv); + + addattr8(n, 1024, IFLA_VXLAN_DF, df); } else if (!matches(*argv, "label") || !matches(*argv, "flowlabel")) { __u32 uval; @@ -350,7 +351,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, return -1; } - if ((gaddr || !IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) && + if (is_addrtype_inet_multi(&daddr) && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_LINK)) { fprintf(stderr, "vxlan: 'group' requires 'dev' to be specified\n"); return -1; @@ -369,18 +370,32 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, if (VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) addattr32(n, 1024, IFLA_VXLAN_ID, vni); - if (gaddr) - addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4); - else if (daddr) - addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4); - else if (!IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) - addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &gaddr6, sizeof(struct in6_addr)); - else if (!IN6_IS_ADDR_UNSPECIFIED(&daddr6)) - addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr)); - else if (preferred_family == AF_INET) - addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4); - else if (preferred_family == AF_INET6) - addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr)); + + if (is_addrtype_inet(&saddr)) { + int type = (saddr.family == AF_INET) ? IFLA_VXLAN_LOCAL + : IFLA_VXLAN_LOCAL6; + addattr_l(n, 1024, type, saddr.data, saddr.bytelen); + selected_family = true; + } + + if (is_addrtype_inet(&daddr)) { + int type = (daddr.family == AF_INET) ? IFLA_VXLAN_GROUP + : IFLA_VXLAN_GROUP6; + addattr_l(n, 1024, type, daddr.data, daddr.bytelen); + selected_family = true; + } + + if (!selected_family) { + if (preferred_family == AF_INET) { + get_addr(&daddr, "default", AF_INET); + addattr_l(n, 1024, IFLA_VXLAN_GROUP, + daddr.data, daddr.bytelen); + } else if (preferred_family == AF_INET6) { + get_addr(&daddr, "default", AF_INET6); + addattr_l(n, 1024, IFLA_VXLAN_GROUP6, + daddr.data, daddr.bytelen); + } + } if (!set_op || VXLAN_ATTRSET(attrs, IFLA_VXLAN_LEARNING)) addattr8(n, 1024, IFLA_VXLAN_LEARNING, learning); @@ -395,12 +410,18 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { __u32 vni; __u8 ttl = 0; - __u8 tos; + __u8 tos = 0; __u32 maxaddr; if (!tb) return; + if (tb[IFLA_VXLAN_COLLECT_METADATA] && + rta_getattr_u8(tb[IFLA_VXLAN_COLLECT_METADATA])) { + print_bool(PRINT_ANY, "external", "external", true); + return; + } + if (!tb[IFLA_VXLAN_ID] || RTA_PAYLOAD(tb[IFLA_VXLAN_ID]) < sizeof(__u32)) return; @@ -515,33 +536,43 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) if (tb[IFLA_VXLAN_L3MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L3MISS])) print_bool(PRINT_ANY, "l3miss", "l3miss ", true); - if (tb[IFLA_VXLAN_TOS] && - (tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]))) { - if (is_json_context()) { - print_0xhex(PRINT_JSON, "tos", "%#x", tos); - } else { - if (tos == 1) - fprintf(f, "tos %s ", "inherit"); - else - fprintf(f, "tos %#x ", tos); - } + if (tb[IFLA_VXLAN_TOS]) + tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]); + if (tos) { + if (is_json_context() || tos != 1) + print_0xhex(PRINT_ANY, "tos", "tos %#llx ", tos); + else + print_string(PRINT_FP, NULL, "tos %s ", "inherit"); } - if (tb[IFLA_VXLAN_TTL]) - ttl = rta_getattr_u8(tb[IFLA_VXLAN_TTL]); - if (is_json_context() || ttl) - print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl); - else + if (tb[IFLA_VXLAN_TTL_INHERIT] && + rta_getattr_u8(tb[IFLA_VXLAN_TTL_INHERIT])) { print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); + } else if (tb[IFLA_VXLAN_TTL]) { + ttl = rta_getattr_u8(tb[IFLA_VXLAN_TTL]); + if (is_json_context() || ttl) + print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl); + else + print_string(PRINT_FP, NULL, "ttl %s ", "auto"); + } + + if (tb[IFLA_VXLAN_DF]) { + enum ifla_vxlan_df df = rta_getattr_u8(tb[IFLA_VXLAN_DF]); + + if (df == VXLAN_DF_UNSET) + print_string(PRINT_JSON, "df", "df %s ", "unset"); + else if (df == VXLAN_DF_SET) + print_string(PRINT_ANY, "df", "df %s ", "set"); + else if (df == VXLAN_DF_INHERIT) + print_string(PRINT_ANY, "df", "df %s ", "inherit"); + } if (tb[IFLA_VXLAN_LABEL]) { __u32 label = rta_getattr_u32(tb[IFLA_VXLAN_LABEL]); if (label) - print_0xhex(PRINT_ANY, - "label", - "flowlabel %#x ", - ntohl(label)); + print_0xhex(PRINT_ANY, "label", + "flowlabel %#llx ", ntohl(label)); } if (tb[IFLA_VXLAN_AGEING]) { @@ -605,10 +636,6 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_RX])) print_bool(PRINT_ANY, "remcsum_rx", "remcsumrx ", true); - if (tb[IFLA_VXLAN_COLLECT_METADATA] && - rta_getattr_u8(tb[IFLA_VXLAN_COLLECT_METADATA])) - print_bool(PRINT_ANY, "collect_metadata", "external ", true); - if (tb[IFLA_VXLAN_GBP]) print_bool(PRINT_ANY, "gbp", "gbp ", true); if (tb[IFLA_VXLAN_GPE])