netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iproute2-next] ip: geneve: Add support for IFLA_GENEVE_PORT_RANGE
@ 2025-09-17 16:24 Alasdair McWilliam
  2025-09-17 19:20 ` Stephen Hemminger
  0 siblings, 1 reply; 2+ messages in thread
From: Alasdair McWilliam @ 2025-09-17 16:24 UTC (permalink / raw)
  To: David Ahern; +Cc: netdev, Alasdair McWilliam, Daniel Borkmann

The IFLA_GENEVE_PORT_RANGE attribute was added in Linux kernel commit
e1f95b1992b8 ("geneve: Allow users to specify source port range") [0] to
facilitate programmatic tuning of the UDP source port range of geneve
tunnel interfaces.

This patch provides support for this attribute in iproute2 such that the
source port range can be set when adding new devices and queried on
existing devices. Implementation is consistent with VXLAN.

Example:

$ ip link add test_geneve type geneve id 100 dstport 6082 \
      remote 192.0.2.1 ttl auto srcport 32000 33000

$ ip -j -d link show dev test_geneve | jq -r '.[].linkinfo'
{
  "info_kind": "geneve",
  "info_data": {
    "id": 100,
    "remote": "192.0.2.1",
    "ttl": 0,
    "df": "unset",
    "port": 6082,
    "udp_csum": false,
    "udp_zero_csum6_rx": true,
    "port_range": {
      "low": 32000,
      "high": 33000
    }
  }
}

Link: https://lore.kernel.org/all/20250226182030.89440-1-daniel@iogearbox.net/ [0]
Signed-off-by: Alasdair McWilliam <alasdair@mcwilliam.dev>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
---
 ip/iplink_geneve.c    | 30 ++++++++++++++++++++++++++++++
 man/man8/ip-link.8.in |  7 +++++++
 2 files changed, 37 insertions(+)

diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c
index 62c61bce..2ef72ab9 100644
--- a/ip/iplink_geneve.c
+++ b/ip/iplink_geneve.c
@@ -23,6 +23,7 @@ static void print_explain(FILE *f)
 		"		[ df DF ]\n"
 		"		[ flowlabel LABEL ]\n"
 		"		[ dstport PORT ]\n"
+		"		[ srcport MIN MAX ]\n"
 		"		[ [no]external ]\n"
 		"		[ [no]udpcsum ]\n"
 		"		[ [no]udp6zerocsumtx ]\n"
@@ -142,6 +143,22 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
 			    (uval & ~LABEL_MAX_MASK))
 				invarg("invalid flowlabel", *argv);
 			label = htonl(uval);
+		} else if (!matches(*argv, "port")
+			|| !matches(*argv, "srcport")) {
+			struct ifla_geneve_port_range range = { 0, 0 };
+
+			NEXT_ARG();
+			check_duparg(&attrs, IFLA_GENEVE_PORT_RANGE, "srcport",
+				     *argv);
+			if (get_be16(&range.low, *argv, 0))
+				invarg("min port", *argv);
+			NEXT_ARG();
+			if (get_be16(&range.high, *argv, 0))
+				invarg("max port", *argv);
+			if (range.low || range.high) {
+				addattr_l(n, 1024, IFLA_GENEVE_PORT_RANGE,
+					  &range, sizeof(range));
+			}
 		} else if (!matches(*argv, "dstport")) {
 			NEXT_ARG();
 			check_duparg(&attrs, IFLA_GENEVE_PORT, "dstport",
@@ -374,6 +391,19 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 		print_bool(PRINT_ANY, "inner_proto_inherit",
 			   "innerprotoinherit ", true);
 	}
+
+	if (tb[IFLA_GENEVE_PORT_RANGE]) {
+		const struct ifla_geneve_port_range *r
+			= RTA_DATA(tb[IFLA_GENEVE_PORT_RANGE]);
+		if (is_json_context()) {
+			open_json_object("port_range");
+			print_uint(PRINT_JSON, "low", NULL, ntohs(r->low));
+			print_uint(PRINT_JSON, "high", NULL, ntohs(r->high));
+			close_json_object();
+		} else {
+			fprintf(f, "srcport %u %u ", ntohs(r->low), ntohs(r->high));
+		}
+	}
 }
 
 static void geneve_print_help(struct link_util *lu, int argc, char **argv,
diff --git a/man/man8/ip-link.8.in b/man/man8/ip-link.8.in
index 7995943a..662f49d5 100644
--- a/man/man8/ip-link.8.in
+++ b/man/man8/ip-link.8.in
@@ -1408,6 +1408,8 @@ the following additional arguments are supported:
 ] [
 .BI dstport " PORT"
 ] [
+.BI srcport " MIN MAX "
+] [
 .RB [ no ] external
 ] [
 .RB [ no ] udpcsum
@@ -1458,6 +1460,11 @@ bit is not set.
 .BI dstport " PORT"
 - select a destination port other than the default of 6081.
 
+.sp
+.BI srcport " MIN MAX"
+- specifies the range of port numbers to use as UDP
+source ports to communicate to the remote tunnel endpoint.
+
 .sp
 .RB [ no ] external
 - make this tunnel externally controlled (or not, which is the default). This
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH iproute2-next] ip: geneve: Add support for IFLA_GENEVE_PORT_RANGE
  2025-09-17 16:24 [PATCH iproute2-next] ip: geneve: Add support for IFLA_GENEVE_PORT_RANGE Alasdair McWilliam
@ 2025-09-17 19:20 ` Stephen Hemminger
  0 siblings, 0 replies; 2+ messages in thread
From: Stephen Hemminger @ 2025-09-17 19:20 UTC (permalink / raw)
  To: Alasdair McWilliam; +Cc: David Ahern, netdev, Daniel Borkmann

On Wed, 17 Sep 2025 17:24:49 +0100
Alasdair McWilliam <alasdair@mcwilliam.dev> wrote:
> @@ -142,6 +143,22 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
>  			    (uval & ~LABEL_MAX_MASK))
>  				invarg("invalid flowlabel", *argv);
>  			label = htonl(uval);
> +		} else if (!matches(*argv, "port")
> +			|| !matches(*argv, "srcport")) {
> +			struct ifla_geneve_port_range range = { 0, 0 };
> +

Do not use matches(), it leads to confusion because of duplicate prefixes.
It is only allowed in legacy iproute parts. I.e no new additions.

> +	if (tb[IFLA_GENEVE_PORT_RANGE]) {
> +		const struct ifla_geneve_port_range *r
> +			= RTA_DATA(tb[IFLA_GENEVE_PORT_RANGE]);
> +		if (is_json_context()) {
> +			open_json_object("port_range");
> +			print_uint(PRINT_JSON, "low", NULL, ntohs(r->low));
> +			print_uint(PRINT_JSON, "high", NULL, ntohs(r->high));
> +			close_json_object();
> +		} else {
> +			fprintf(f, "srcport %u %u ", ntohs(r->low), ntohs(r->high));
> +		}

Do not use fprintf directly instead use multiple calls to print_uint like:

		open_json_object("port_range");
		print_uint(PRINT_ANY, "low", "srcport %u", ntohs(r->low));
		print_uint(PRINT_ANY, "high", " %u ", ntohs(r->high));
		close_json_object();

Avoid having json specific code with is_json_context() if possible.
It leads to untested code paths.


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-09-17 19:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-17 16:24 [PATCH iproute2-next] ip: geneve: Add support for IFLA_GENEVE_PORT_RANGE Alasdair McWilliam
2025-09-17 19:20 ` Stephen Hemminger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).