Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7030878 authored by Thomas Graf's avatar Thomas Graf Committed by David S. Miller
Browse files

fib: Add fib rule match on tunnel id



This add the ability to select a routing table based on the tunnel
id which allows to maintain separate routing tables for each virtual
tunnel network.

ip rule add from all tunnel-id 100 lookup 100
ip rule add from all tunnel-id 200 lookup 200

A new static key controls the collection of metadata at tunnel level
upon demand.

Signed-off-by: default avatarThomas Graf <tgraf@suug.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3093fbe7
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -143,7 +143,8 @@ static struct workqueue_struct *vxlan_wq;

static inline bool vxlan_collect_metadata(struct vxlan_sock *vs)
{
	return vs->flags & VXLAN_F_COLLECT_METADATA;
	return vs->flags & VXLAN_F_COLLECT_METADATA ||
	       ip_tunnel_collect_metadata();
}

#if IS_ENABLED(CONFIG_IPV6)
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ struct fib_rule {
	u8			action;
	/* 3 bytes hole, try to use */
	u32			target;
	__be64			tun_id;
	struct fib_rule __rcu	*ctarget;
	struct net		*fr_net;

+11 −0
Original line number Diff line number Diff line
@@ -303,6 +303,17 @@ static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstat
	return (struct ip_tunnel_info *)lwtstate->data;
}

extern struct static_key ip_tunnel_metadata_cnt;

/* Returns > 0 if metadata should be collected */
static inline int ip_tunnel_collect_metadata(void)
{
	return static_key_false(&ip_tunnel_metadata_cnt);
}

void ip_tunnel_need_metadata(void);
void ip_tunnel_unneed_metadata(void);

#endif /* CONFIG_INET */

#endif /* __NET_IP_TUNNELS_H */
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ enum {
	FRA_UNUSED5,
	FRA_FWMARK,	/* mark */
	FRA_FLOW,	/* flow/class id */
	FRA_UNUSED6,
	FRA_TUN_ID,
	FRA_SUPPRESS_IFGROUP,
	FRA_SUPPRESS_PREFIXLEN,
	FRA_TABLE,	/* Extended table id */
+22 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/fib_rules.h>
#include <net/ip_tunnels.h>

int fib_default_rule_add(struct fib_rules_ops *ops,
			 u32 pref, u32 table, u32 flags)
@@ -186,6 +187,9 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
	if ((rule->mark ^ fl->flowi_mark) & rule->mark_mask)
		goto out;

	if (rule->tun_id && (rule->tun_id != fl->flowi_tun_key.tun_id))
		goto out;

	ret = ops->match(rule, fl, flags);
out:
	return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
@@ -330,6 +334,9 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
	if (tb[FRA_FWMASK])
		rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]);

	if (tb[FRA_TUN_ID])
		rule->tun_id = nla_get_be64(tb[FRA_TUN_ID]);

	rule->action = frh->action;
	rule->flags = frh->flags;
	rule->table = frh_get_table(frh, tb);
@@ -407,6 +414,9 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
	if (unresolved)
		ops->unresolved_rules++;

	if (rule->tun_id)
		ip_tunnel_need_metadata();

	notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).portid);
	flush_route_cache(ops);
	rules_ops_put(ops);
@@ -473,6 +483,10 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
		    (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK])))
			continue;

		if (tb[FRA_TUN_ID] &&
		    (rule->tun_id != nla_get_be64(tb[FRA_TUN_ID])))
			continue;

		if (!ops->compare(rule, frh, tb))
			continue;

@@ -487,6 +501,9 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
				goto errout;
		}

		if (rule->tun_id)
			ip_tunnel_unneed_metadata();

		list_del_rcu(&rule->list);

		if (rule->action == FR_ACT_GOTO) {
@@ -535,7 +552,8 @@ static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
			 + nla_total_size(4) /* FRA_SUPPRESS_PREFIXLEN */
			 + nla_total_size(4) /* FRA_SUPPRESS_IFGROUP */
			 + nla_total_size(4) /* FRA_FWMARK */
			 + nla_total_size(4); /* FRA_FWMASK */
			 + nla_total_size(4) /* FRA_FWMASK */
			 + nla_total_size(8); /* FRA_TUN_ID */

	if (ops->nlmsg_payload)
		payload += ops->nlmsg_payload(rule);
@@ -591,7 +609,9 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
	    ((rule->mark_mask || rule->mark) &&
	     nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) ||
	    (rule->target &&
	     nla_put_u32(skb, FRA_GOTO, rule->target)))
	     nla_put_u32(skb, FRA_GOTO, rule->target)) ||
	    (rule->tun_id &&
	     nla_put_be64(skb, FRA_TUN_ID, rule->tun_id)))
		goto nla_put_failure;

	if (rule->suppress_ifgroup != -1) {
Loading