[v2] iplink_rmnet: Allow passing IFLA_RMNET_FLAGS

Message ID 20210315154629.652824-1-bjorn.andersson@linaro.org
State Superseded
Headers show
Series
  • [v2] iplink_rmnet: Allow passing IFLA_RMNET_FLAGS
Related show

Commit Message

Bjorn Andersson March 15, 2021, 3:46 p.m.
Parse and pass IFLA_RMNET_FLAGS to the kernel, to allow changing the
flags from the default of ingress-aggregate only.

Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

---

Changes since v1:
- s/ifla_vlan_flags/ifla_rmnet_flags/ in print_opt

 ip/iplink_rmnet.c | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

-- 
2.28.0

Comments

Alex Elder March 15, 2021, 4:16 p.m. | #1
On 3/15/21 10:46 AM, Bjorn Andersson wrote:
> Parse and pass IFLA_RMNET_FLAGS to the kernel, to allow changing the

> flags from the default of ingress-aggregate only.


To be clear, this default is implemented in the kernel RMNet
driver, not in "iproute2".  And it is ingress deaggregation
(unpacking of aggregated packets from a buffer), not aggregation
(which would be supplying a buffer of aggregated packets to the
hardware).

> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>


I have some suggestions on your help text (and flag names).
The code looks good to me otherwise.  I trust you've
confirmed the RMNet driver uses the flags exactly as
you intend when they're provided this way.

					-Alex
> ---

> 

> Changes since v1:

> - s/ifla_vlan_flags/ifla_rmnet_flags/ in print_opt

> 

>   ip/iplink_rmnet.c | 42 ++++++++++++++++++++++++++++++++++++++++++

>   1 file changed, 42 insertions(+)

> 

> diff --git a/ip/iplink_rmnet.c b/ip/iplink_rmnet.c

> index 1d16440c6900..a847c838def2 100644

> --- a/ip/iplink_rmnet.c

> +++ b/ip/iplink_rmnet.c

> @@ -16,6 +16,10 @@ static void print_explain(FILE *f)

>   {

>   	fprintf(f,

>   		"Usage: ... rmnet mux_id MUXID\n"

> +		"                 [ingress-deaggregation]\n"

> +		"                 [ingress-commands]\n"

> +		"                 [ingress-chksumv4]\n"

> +		"                 [egress-chksumv4]\n"


Other help output (in print_explain()) put spaces after
the '[' and before the ']'; so you'd be better to stay
consistent with that.

And I know the name is based on the C symbol, but I think
you should follow the convention that seems to be used for
all others, and use "csum" to mean checksum.

Also it's not clear what the "v4" means.  I'm not sure I
like this suggestion, but...  It comes from QMAP version 4,
as opposed to QMAP version 5, so maybe use "csum-qmap4"
in place of "csumv4?"

Is there any way to disable ingress deaggregation?  Since
it's on by default, you might want to use a "[ on | off ]"
type option for that case (or all of them for that matter).
Otherwise, the deaggregation parameter doesn't really help
anything.

>   		"\n"

>   		"MUXID := 1-254\n"

>   	);

> @@ -29,6 +33,7 @@ static void explain(void)

>   static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,

>   			   struct nlmsghdr *n)

>   {

> +	struct ifla_rmnet_flags flags = { };

>   	__u16 mux_id;


Do you know why this is __u16?  Is it because it's exposed
to user space?  Not a problem... just curious.

>   	while (argc > 0) {

> @@ -37,6 +42,18 @@ static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,

>   			if (get_u16(&mux_id, *argv, 0))

>   				invarg("mux_id is invalid", *argv);

>   			addattr16(n, 1024, IFLA_RMNET_MUX_ID, mux_id);

> +		} else if (matches(*argv, "ingress-deaggregation") == 0) {

> +			flags.mask = ~0;

> +			flags.flags |= RMNET_FLAGS_INGRESS_DEAGGREGATION;

> +		} else if (matches(*argv, "ingress-commands") == 0) {

> +			flags.mask = ~0;

> +			flags.flags |= RMNET_FLAGS_INGRESS_MAP_COMMANDS;

> +		} else if (matches(*argv, "ingress-chksumv4") == 0) {

> +			flags.mask = ~0;

> +			flags.flags |= RMNET_FLAGS_INGRESS_MAP_CKSUMV4;

> +		} else if (matches(*argv, "egress-chksumv4") == 0) {

> +			flags.mask = ~0;

> +			flags.flags |= RMNET_FLAGS_EGRESS_MAP_CKSUMV4;

>   		} else if (matches(*argv, "help") == 0) {

>   			explain();

>   			return -1;

> @@ -48,11 +65,28 @@ static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,

>   		argc--, argv++;

>   	}

>   

> +	if (flags.mask)

> +		addattr_l(n, 1024, IFLA_RMNET_FLAGS, &flags, sizeof(flags));

> +

>   	return 0;

>   }

>   

> +static void rmnet_print_flags(FILE *fp, __u32 flags)

> +{

> +	if (flags & RMNET_FLAGS_INGRESS_DEAGGREGATION)

> +		print_string(PRINT_ANY, NULL, "%s ", "ingress-deaggregation");

> +	if (flags & RMNET_FLAGS_INGRESS_MAP_COMMANDS)

> +		print_string(PRINT_ANY, NULL, "%s ", "ingress-commands");

> +	if (flags & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)

> +		print_string(PRINT_ANY, NULL, "%s ", "ingress-chksumv4");

> +	if (flags & RMNET_FLAGS_EGRESS_MAP_CKSUMV4)

> +		print_string(PRINT_ANY, NULL, "%s ", "egress-cksumv4");

> +}

> +

>   static void rmnet_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])

>   {

> +	struct ifla_rmnet_flags *flags;

> +

>   	if (!tb)

>   		return;

>   

> @@ -64,6 +98,14 @@ static void rmnet_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])

>   		   "mux_id",

>   		   "mux_id %u ",

>   		   rta_getattr_u16(tb[IFLA_RMNET_MUX_ID]));

> +

> +	if (tb[IFLA_RMNET_FLAGS]) {

> +		if (RTA_PAYLOAD(tb[IFLA_RMNET_FLAGS]) < sizeof(*flags))

> +			return;

> +		flags = RTA_DATA(tb[IFLA_RMNET_FLAGS]);

> +

> +		rmnet_print_flags(f, flags->flags);

> +	}

>   }

>   

>   static void rmnet_print_help(struct link_util *lu, int argc, char **argv,

>
Bjorn Andersson April 2, 2021, 5:30 p.m. | #2
On Mon 15 Mar 11:16 CDT 2021, Alex Elder wrote:

> On 3/15/21 10:46 AM, Bjorn Andersson wrote:

> > Parse and pass IFLA_RMNET_FLAGS to the kernel, to allow changing the

> > flags from the default of ingress-aggregate only.

> 

> To be clear, this default is implemented in the kernel RMNet

> driver, not in "iproute2".  And it is ingress deaggregation

> (unpacking of aggregated packets from a buffer), not aggregation

> (which would be supplying a buffer of aggregated packets to the

> hardware).

> 


Thanks, I'll update the commit message to clarify this point.

> > Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>

> 

> I have some suggestions on your help text (and flag names).

> The code looks good to me otherwise.  I trust you've

> confirmed the RMNet driver uses the flags exactly as

> you intend when they're provided this way.

> 


I've confirmed that it flips the bits in the rmnet driver and that
flipping the right bit(s) my laptop starts deaggregating messages.

> 					-Alex

> > ---

> > 

> > Changes since v1:

> > - s/ifla_vlan_flags/ifla_rmnet_flags/ in print_opt

> > 

> >   ip/iplink_rmnet.c | 42 ++++++++++++++++++++++++++++++++++++++++++

> >   1 file changed, 42 insertions(+)

> > 

> > diff --git a/ip/iplink_rmnet.c b/ip/iplink_rmnet.c

> > index 1d16440c6900..a847c838def2 100644

> > --- a/ip/iplink_rmnet.c

> > +++ b/ip/iplink_rmnet.c

> > @@ -16,6 +16,10 @@ static void print_explain(FILE *f)

> >   {

> >   	fprintf(f,

> >   		"Usage: ... rmnet mux_id MUXID\n"

> > +		"                 [ingress-deaggregation]\n"

> > +		"                 [ingress-commands]\n"

> > +		"                 [ingress-chksumv4]\n"

> > +		"                 [egress-chksumv4]\n"

> 

> Other help output (in print_explain()) put spaces after

> the '[' and before the ']'; so you'd be better to stay

> consistent with that.

> 


I had missed that, thanks.

> And I know the name is based on the C symbol, but I think

> you should follow the convention that seems to be used for

> all others, and use "csum" to mean checksum.

> 

> Also it's not clear what the "v4" means.  I'm not sure I

> like this suggestion, but...  It comes from QMAP version 4,

> as opposed to QMAP version 5, so maybe use "csum-qmap4"

> in place of "csumv4?"

> 


Make sense, I'll update this to ingress-csum-qmap4 etc.

> Is there any way to disable ingress deaggregation?  Since

> it's on by default, you might want to use a "[ on | off ]"

> type option for that case (or all of them for that matter).

> Otherwise, the deaggregation parameter doesn't really help

> anything.

> 


Unfortunately, in contrast to other implementers of IFLAG_x_FLAGS we
find the following snippet in the rmnet driver:

  data_format = flags->flags & flags->mask;

So rather than flags->mask specifying which bits to update, it masks
flags->flags and whatever is left is your new flags. And given that this
is non-standard, the iplink flow doesn't support read/modify/write on
the tool side.

As such it's not possible to toggle individual bits, you always pass the
new flags. So the way to disable a particular feature, is to issue an
change link request without the particular feature specified.

> >   		"\n"

> >   		"MUXID := 1-254\n"

> >   	);

> > @@ -29,6 +33,7 @@ static void explain(void)

> >   static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,

> >   			   struct nlmsghdr *n)

> >   {

> > +	struct ifla_rmnet_flags flags = { };

> >   	__u16 mux_id;

> 

> Do you know why this is __u16?  Is it because it's exposed

> to user space?  Not a problem... just curious.

> 


This seems to be the data type used throughout the project to denote
16 bit unsigned integers, so it seems to me that Daniele just followed
the coding standard of the project here - and it's defined in the kernel
to be a 16 bit unsigned integer...

Regards,
Bjorn

> >   	while (argc > 0) {

> > @@ -37,6 +42,18 @@ static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,

> >   			if (get_u16(&mux_id, *argv, 0))

> >   				invarg("mux_id is invalid", *argv);

> >   			addattr16(n, 1024, IFLA_RMNET_MUX_ID, mux_id);

> > +		} else if (matches(*argv, "ingress-deaggregation") == 0) {

> > +			flags.mask = ~0;

> > +			flags.flags |= RMNET_FLAGS_INGRESS_DEAGGREGATION;

> > +		} else if (matches(*argv, "ingress-commands") == 0) {

> > +			flags.mask = ~0;

> > +			flags.flags |= RMNET_FLAGS_INGRESS_MAP_COMMANDS;

> > +		} else if (matches(*argv, "ingress-chksumv4") == 0) {

> > +			flags.mask = ~0;

> > +			flags.flags |= RMNET_FLAGS_INGRESS_MAP_CKSUMV4;

> > +		} else if (matches(*argv, "egress-chksumv4") == 0) {

> > +			flags.mask = ~0;

> > +			flags.flags |= RMNET_FLAGS_EGRESS_MAP_CKSUMV4;

> >   		} else if (matches(*argv, "help") == 0) {

> >   			explain();

> >   			return -1;

> > @@ -48,11 +65,28 @@ static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,

> >   		argc--, argv++;

> >   	}

> > +	if (flags.mask)

> > +		addattr_l(n, 1024, IFLA_RMNET_FLAGS, &flags, sizeof(flags));

> > +

> >   	return 0;

> >   }

> > +static void rmnet_print_flags(FILE *fp, __u32 flags)

> > +{

> > +	if (flags & RMNET_FLAGS_INGRESS_DEAGGREGATION)

> > +		print_string(PRINT_ANY, NULL, "%s ", "ingress-deaggregation");

> > +	if (flags & RMNET_FLAGS_INGRESS_MAP_COMMANDS)

> > +		print_string(PRINT_ANY, NULL, "%s ", "ingress-commands");

> > +	if (flags & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)

> > +		print_string(PRINT_ANY, NULL, "%s ", "ingress-chksumv4");

> > +	if (flags & RMNET_FLAGS_EGRESS_MAP_CKSUMV4)

> > +		print_string(PRINT_ANY, NULL, "%s ", "egress-cksumv4");

> > +}

> > +

> >   static void rmnet_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])

> >   {

> > +	struct ifla_rmnet_flags *flags;

> > +

> >   	if (!tb)

> >   		return;

> > @@ -64,6 +98,14 @@ static void rmnet_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])

> >   		   "mux_id",

> >   		   "mux_id %u ",

> >   		   rta_getattr_u16(tb[IFLA_RMNET_MUX_ID]));

> > +

> > +	if (tb[IFLA_RMNET_FLAGS]) {

> > +		if (RTA_PAYLOAD(tb[IFLA_RMNET_FLAGS]) < sizeof(*flags))

> > +			return;

> > +		flags = RTA_DATA(tb[IFLA_RMNET_FLAGS]);

> > +

> > +		rmnet_print_flags(f, flags->flags);

> > +	}

> >   }

> >   static void rmnet_print_help(struct link_util *lu, int argc, char **argv,

> > 

>

Patch

diff --git a/ip/iplink_rmnet.c b/ip/iplink_rmnet.c
index 1d16440c6900..a847c838def2 100644
--- a/ip/iplink_rmnet.c
+++ b/ip/iplink_rmnet.c
@@ -16,6 +16,10 @@  static void print_explain(FILE *f)
 {
 	fprintf(f,
 		"Usage: ... rmnet mux_id MUXID\n"
+		"                 [ingress-deaggregation]\n"
+		"                 [ingress-commands]\n"
+		"                 [ingress-chksumv4]\n"
+		"                 [egress-chksumv4]\n"
 		"\n"
 		"MUXID := 1-254\n"
 	);
@@ -29,6 +33,7 @@  static void explain(void)
 static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,
 			   struct nlmsghdr *n)
 {
+	struct ifla_rmnet_flags flags = { };
 	__u16 mux_id;
 
 	while (argc > 0) {
@@ -37,6 +42,18 @@  static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,
 			if (get_u16(&mux_id, *argv, 0))
 				invarg("mux_id is invalid", *argv);
 			addattr16(n, 1024, IFLA_RMNET_MUX_ID, mux_id);
+		} else if (matches(*argv, "ingress-deaggregation") == 0) {
+			flags.mask = ~0;
+			flags.flags |= RMNET_FLAGS_INGRESS_DEAGGREGATION;
+		} else if (matches(*argv, "ingress-commands") == 0) {
+			flags.mask = ~0;
+			flags.flags |= RMNET_FLAGS_INGRESS_MAP_COMMANDS;
+		} else if (matches(*argv, "ingress-chksumv4") == 0) {
+			flags.mask = ~0;
+			flags.flags |= RMNET_FLAGS_INGRESS_MAP_CKSUMV4;
+		} else if (matches(*argv, "egress-chksumv4") == 0) {
+			flags.mask = ~0;
+			flags.flags |= RMNET_FLAGS_EGRESS_MAP_CKSUMV4;
 		} else if (matches(*argv, "help") == 0) {
 			explain();
 			return -1;
@@ -48,11 +65,28 @@  static int rmnet_parse_opt(struct link_util *lu, int argc, char **argv,
 		argc--, argv++;
 	}
 
+	if (flags.mask)
+		addattr_l(n, 1024, IFLA_RMNET_FLAGS, &flags, sizeof(flags));
+
 	return 0;
 }
 
+static void rmnet_print_flags(FILE *fp, __u32 flags)
+{
+	if (flags & RMNET_FLAGS_INGRESS_DEAGGREGATION)
+		print_string(PRINT_ANY, NULL, "%s ", "ingress-deaggregation");
+	if (flags & RMNET_FLAGS_INGRESS_MAP_COMMANDS)
+		print_string(PRINT_ANY, NULL, "%s ", "ingress-commands");
+	if (flags & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)
+		print_string(PRINT_ANY, NULL, "%s ", "ingress-chksumv4");
+	if (flags & RMNET_FLAGS_EGRESS_MAP_CKSUMV4)
+		print_string(PRINT_ANY, NULL, "%s ", "egress-cksumv4");
+}
+
 static void rmnet_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 {
+	struct ifla_rmnet_flags *flags;
+
 	if (!tb)
 		return;
 
@@ -64,6 +98,14 @@  static void rmnet_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
 		   "mux_id",
 		   "mux_id %u ",
 		   rta_getattr_u16(tb[IFLA_RMNET_MUX_ID]));
+
+	if (tb[IFLA_RMNET_FLAGS]) {
+		if (RTA_PAYLOAD(tb[IFLA_RMNET_FLAGS]) < sizeof(*flags))
+			return;
+		flags = RTA_DATA(tb[IFLA_RMNET_FLAGS]);
+
+		rmnet_print_flags(f, flags->flags);
+	}
 }
 
 static void rmnet_print_help(struct link_util *lu, int argc, char **argv,