]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
iplink_geneve: Support IFLA_GENEVE_LOCAL and IFLA_GENEVE_LOCAL6.
authorKuniyuki Iwashima <kuniyu@google.com>
Mon, 8 Jun 2026 03:16:58 +0000 (03:16 +0000)
committerDavid Ahern <dsahern@kernel.org>
Thu, 11 Jun 2026 18:59:06 +0000 (12:59 -0600)
IFLA_GENEVE_LOCAL and IFLA_GENEVE_LOCAL6 allow specifying a local
IPv4/IPv6 address for the backend UDP socket of a GENEVE devcie.

Let's support the attributes with the "local" keyword.

  # for i in $(seq 1 2);
  do
          ip link add geneve4_${i} type geneve local 192.168.0.${i} external
          ip addr add 192.168.0.${i}/24 dev geneve4_${i}
          ip link set geneve4_${i} up

          ip link add geneve6_${i} type geneve local 2001:9292::${i} external
          ip addr add 2001:9292::${i}/64 dev geneve6_${i} nodad
          ip link set geneve6_${i} up
  done

  # ip -d l | grep geneve
  9: geneve4_1: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
      geneve external id 0 local 192.168.0.1 ...
  10: geneve6_1: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
      geneve external id 0 local 2001:9292::1 ...
  11: geneve4_2: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
      geneve external id 0 local 192.168.0.2 ...
  12: geneve6_2: <BROADCAST,MULTICAST,UP,LOWER_UP> ...
      geneve external id 0 local 2001:9292::2 ...

  # ss -ua | grep geneve
  UNCONN 0      0         192.168.0.2:geneve      0.0.0.0:*
  UNCONN 0      0         192.168.0.1:geneve      0.0.0.0:*
  UNCONN 0      0      [2001:9292::2]:geneve            *:*
  UNCONN 0      0      [2001:9292::1]:geneve            *:*

Note that kernel dumps the wildcard address if the device created
with IFLA_GENEVE_COLLECT_METADATA is not dualstack.

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
ip/iplink_geneve.c
man/man8/ip-link.8.in

index 62c61bce138bb6169c9e695913e4853cca37598c..da4ae83266fa1e3ba151bd8adef7fa2fd260510f 100644 (file)
@@ -18,6 +18,7 @@ static void print_explain(FILE *f)
        fprintf(f,
                "Usage: ... geneve id VNI\n"
                "               remote ADDR\n"
+               "               [ local ADDR ]\n"
                "               [ ttl TTL ]\n"
                "               [ tos TOS ]\n"
                "               [ df DF ]\n"
@@ -56,7 +57,7 @@ static void check_duparg(__u64 *attrs, int type, const char *key,
 static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
                          struct nlmsghdr *n)
 {
-       inet_prefix daddr;
+       inet_prefix daddr, saddr;
        __u32 vni = 0;
        __u32 label = 0;
        __u8 ttl = 0;
@@ -72,6 +73,7 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
        bool inner_proto_inherit = false;
 
        inet_prefix_reset(&daddr);
+       inet_prefix_reset(&saddr);
 
        while (argc > 0) {
                if (!matches(*argv, "id") ||
@@ -88,6 +90,13 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
                        get_addr(&daddr, *argv, AF_UNSPEC);
                        if (!is_addrtype_inet_not_multi(&daddr))
                                invarg("invalid remote address", *argv);
+               } else if (!strcmp(*argv, "local")) {
+                       NEXT_ARG();
+                       check_duparg(&attrs, IFLA_GENEVE_LOCAL, "local",
+                                    *argv);
+                       get_addr(&saddr, *argv, AF_UNSPEC);
+                       if (!is_addrtype_inet_not_multi(&saddr))
+                               invarg("invalid local address", *argv);
                } else if (!matches(*argv, "ttl") ||
                           !matches(*argv, "hoplimit")) {
                        unsigned int uval;
@@ -221,8 +230,17 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
        if (is_addrtype_inet(&daddr)) {
                int type = (daddr.family == AF_INET) ? IFLA_GENEVE_REMOTE :
                                                       IFLA_GENEVE_REMOTE6;
+
                addattr_l(n, 1024, type, daddr.data, daddr.bytelen);
        }
+
+       if (is_addrtype_inet(&saddr)) {
+               int type = (saddr.family == AF_INET) ? IFLA_GENEVE_LOCAL :
+                                                      IFLA_GENEVE_LOCAL6;
+
+               addattr_l(n, 1024, type, saddr.data, saddr.bytelen);
+       }
+
        if (!set_op || GENEVE_ATTRSET(attrs, IFLA_GENEVE_LABEL))
                addattr32(n, 1024, IFLA_GENEVE_LABEL, label);
        if (!set_op || GENEVE_ATTRSET(attrs, IFLA_GENEVE_TTL))
@@ -285,6 +303,28 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
                }
        }
 
+       if (tb[IFLA_GENEVE_LOCAL]) {
+               __be32 addr = rta_getattr_u32(tb[IFLA_GENEVE_LOCAL]);
+
+               print_color_string(PRINT_ANY, COLOR_INET,
+                                  "local",
+                                  "local %s ",
+                                  format_host(AF_INET, 4, &addr));
+       } else if (tb[IFLA_GENEVE_LOCAL6]) {
+               struct in6_addr addr;
+
+               memcpy(&addr, RTA_DATA(tb[IFLA_GENEVE_LOCAL6]),
+                      sizeof(struct in6_addr));
+               if (!IN6_IS_ADDR_UNSPECIFIED(&addr)) {
+                       print_color_string(PRINT_ANY, COLOR_INET6,
+                                          "local6",
+                                          "local %s ",
+                                          format_host(AF_INET6,
+                                                      sizeof(struct in6_addr),
+                                                      &addr));
+               }
+       }
+
        if (tb[IFLA_GENEVE_TTL_INHERIT] &&
            rta_getattr_u8(tb[IFLA_GENEVE_TTL_INHERIT])) {
                print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
index d4f9f0621c8f0298954102a46b26632569842c6d..fc7f02482036bde3dd98df0043c23cbe634567a2 100644 (file)
@@ -1435,6 +1435,8 @@ the following additional arguments are supported:
 .BI "ip link add " DEVICE
 .BI type " geneve " id " VNI " remote " IPADDR"
 [
+.BI local " IPADDR "
+] [
 .BI ttl " TTL "
 ] [
 .BI tos " TOS "
@@ -1465,6 +1467,10 @@ the following additional arguments are supported:
 .BI remote " IPADDR"
 - specifies the unicast destination IP address to use in outgoing packets.
 
+.sp
+.BI local " IPADDR"
+- specifies the source IP address to listen on.
+
 .sp
 .BI ttl " TTL"
 - specifies the TTL value to use in outgoing packets. "0" or "auto" means