[PATCH libnl 2/2] rule: Add support for l3mdev in FIB rules

David Ahern dsahern at gmail.com
Wed May 3 16:21:10 PDT 2017


Add support for the l3mdev option in FIB rules. If l3mdev is set
then the lookup is directed to the table associated with the l3mdev
(e.g., VRF) device.

If the l3mev attribute is set the table id is not, so update the table
id attribute to make sure r_table is non-0.

iproute2 shows the rule as:
    1000:	from all lookup [l3mdev-table]

where [l3mdev-table] infers the dynamic nature of the table id. Keep
that notation for libnl.

Signed-off-by: David Ahern <dsahern at gmail.com>
---
 include/netlink-private/types.h |  2 +-
 include/netlink/route/rule.h    |  2 ++
 lib/route/rule.c                | 32 +++++++++++++++++++++++++++++---
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h
index 83d6d459ca50..0842fc648ebf 100644
--- a/include/netlink-private/types.h
+++ b/include/netlink-private/types.h
@@ -347,7 +347,7 @@ struct rtnl_rule
 	uint8_t		r_family;
 	uint8_t		r_action;
 	uint8_t		r_dsfield; /* ipv4 only */
-	uint8_t		r_unused;
+	uint8_t		r_l3mdev;
 	uint32_t	r_table;
 	uint32_t	r_flags;
 	uint32_t	r_prio;
diff --git a/include/netlink/route/rule.h b/include/netlink/route/rule.h
index 760b782ad09e..ec24269e12fc 100644
--- a/include/netlink/route/rule.h
+++ b/include/netlink/route/rule.h
@@ -67,6 +67,8 @@ extern void		rtnl_rule_set_realms(struct rtnl_rule *, uint32_t);
 extern uint32_t		rtnl_rule_get_realms(struct rtnl_rule *);
 extern void		rtnl_rule_set_goto(struct rtnl_rule *, uint32_t);
 extern uint32_t		rtnl_rule_get_goto(struct rtnl_rule *);
+extern void		rtnl_rule_set_l3mdev(struct rtnl_rule *);
+extern uint8_t		rtnl_rule_get_l3mdev(struct rtnl_rule *);
 
 #ifdef __cplusplus
 }
diff --git a/lib/route/rule.c b/lib/route/rule.c
index 2e40bb195102..76d9fe8e635b 100644
--- a/lib/route/rule.c
+++ b/lib/route/rule.c
@@ -39,6 +39,7 @@
 #define RULE_ATTR_DST		0x0800
 #define RULE_ATTR_DSFIELD	0x1000
 #define RULE_ATTR_FLOW		0x2000
+#define RULE_ATTR_L3MDEV	0x4000
 
 static struct nl_cache_ops rtnl_rule_ops;
 static struct nl_object_ops rule_obj_ops;
@@ -80,6 +81,7 @@ static struct nla_policy rule_policy[FRA_MAX+1] = {
 	[FRA_FWMASK]	= { .type = NLA_U32 },
 	[FRA_GOTO]	= { .type = NLA_U32 },
 	[FRA_FLOW]	= { .type = NLA_U32 },
+	[FRA_L3MDEV]	= { .type = NLA_U8 },
 };
 
 static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
@@ -108,8 +110,9 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
 	rule->r_action = frh->action;
 	rule->r_flags = frh->flags;
 
-	rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION |
-			 RULE_ATTR_FLAGS);
+	rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_ACTION | RULE_ATTR_FLAGS);
+	if (rule->r_table)
+		rule->ce_mask |= RULE_ATTR_TABLE;
 
 	/* ipv4 only */
 	if (frh->tos) {
@@ -119,7 +122,8 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
 
 	if (tb[FRA_TABLE]) {
 		rule->r_table = nla_get_u32(tb[FRA_TABLE]);
-		rule->ce_mask |= RULE_ATTR_TABLE;
+		if (rule->r_table)
+			rule->ce_mask |= RULE_ATTR_TABLE;
 	}
 
 	if (tb[FRA_IIFNAME]) {
@@ -173,6 +177,11 @@ static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
 		rule->ce_mask |= RULE_ATTR_FLOW;
 	}
 
+	if (tb[FRA_L3MDEV]) {
+		rule->r_l3mdev = nla_get_u8(tb[FRA_L3MDEV]);
+		rule->ce_mask |= RULE_ATTR_L3MDEV;
+	}
+
 	err = pp->pp_cb((struct nl_object *) rule, pp);
 errout:
 	rtnl_rule_put(rule);
@@ -220,6 +229,9 @@ static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p)
 		nl_dump(p, "lookup %s ",
 			rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
 
+	if (r->ce_mask & RULE_ATTR_L3MDEV)
+		nl_dump(p, "lookup [l3mdev-table] ");
+
 	if (r->ce_mask & RULE_ATTR_FLOW)
 		nl_dump(p, "flow %s ",
 			rtnl_realms2str(r->r_flow, buf, sizeof(buf)));
@@ -415,6 +427,9 @@ static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags,
 	if (tmpl->ce_mask & RULE_ATTR_FLOW)
 		NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow);
 
+	if (tmpl->ce_mask & RULE_ATTR_L3MDEV)
+		NLA_PUT_U8(msg, FRA_L3MDEV, tmpl->r_l3mdev);
+
 
 	*result = msg;
 	return 0;
@@ -691,6 +706,17 @@ uint8_t rtnl_rule_get_action(struct rtnl_rule *rule)
 	return rule->r_action;
 }
 
+void rtnl_rule_set_l3mdev(struct rtnl_rule *rule)
+{
+	rule->r_l3mdev = 1;
+	rule->ce_mask |= RULE_ATTR_L3MDEV;
+}
+
+uint8_t rtnl_rule_get_l3mdev(struct rtnl_rule *rule)
+{
+	return rule->r_l3mdev;
+}
+
 void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms)
 {
 	rule->r_flow = realms;
-- 
2.1.4




More information about the libnl mailing list