Skip to content

Commit e703087

Browse files
tgrafdavem330
authored andcommitted
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: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 3093fbe commit e703087

File tree

6 files changed

+53
-4
lines changed

6 files changed

+53
-4
lines changed

drivers/net/vxlan.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ static struct workqueue_struct *vxlan_wq;
143143

144144
static inline bool vxlan_collect_metadata(struct vxlan_sock *vs)
145145
{
146-
return vs->flags & VXLAN_F_COLLECT_METADATA;
146+
return vs->flags & VXLAN_F_COLLECT_METADATA ||
147+
ip_tunnel_collect_metadata();
147148
}
148149

149150
#if IS_ENABLED(CONFIG_IPV6)

include/net/fib_rules.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ struct fib_rule {
1919
u8 action;
2020
/* 3 bytes hole, try to use */
2121
u32 target;
22+
__be64 tun_id;
2223
struct fib_rule __rcu *ctarget;
2324
struct net *fr_net;
2425

include/net/ip_tunnels.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,17 @@ static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstat
303303
return (struct ip_tunnel_info *)lwtstate->data;
304304
}
305305

306+
extern struct static_key ip_tunnel_metadata_cnt;
307+
308+
/* Returns > 0 if metadata should be collected */
309+
static inline int ip_tunnel_collect_metadata(void)
310+
{
311+
return static_key_false(&ip_tunnel_metadata_cnt);
312+
}
313+
314+
void ip_tunnel_need_metadata(void);
315+
void ip_tunnel_unneed_metadata(void);
316+
306317
#endif /* CONFIG_INET */
307318

308319
#endif /* __NET_IP_TUNNELS_H */

include/uapi/linux/fib_rules.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ enum {
4343
FRA_UNUSED5,
4444
FRA_FWMARK, /* mark */
4545
FRA_FLOW, /* flow/class id */
46-
FRA_UNUSED6,
46+
FRA_TUN_ID,
4747
FRA_SUPPRESS_IFGROUP,
4848
FRA_SUPPRESS_PREFIXLEN,
4949
FRA_TABLE, /* Extended table id */

net/core/fib_rules.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <net/net_namespace.h>
1717
#include <net/sock.h>
1818
#include <net/fib_rules.h>
19+
#include <net/ip_tunnels.h>
1920

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

190+
if (rule->tun_id && (rule->tun_id != fl->flowi_tun_key.tun_id))
191+
goto out;
192+
189193
ret = ops->match(rule, fl, flags);
190194
out:
191195
return (rule->flags & FIB_RULE_INVERT) ? !ret : ret;
@@ -330,6 +334,9 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
330334
if (tb[FRA_FWMASK])
331335
rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]);
332336

337+
if (tb[FRA_TUN_ID])
338+
rule->tun_id = nla_get_be64(tb[FRA_TUN_ID]);
339+
333340
rule->action = frh->action;
334341
rule->flags = frh->flags;
335342
rule->table = frh_get_table(frh, tb);
@@ -407,6 +414,9 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh)
407414
if (unresolved)
408415
ops->unresolved_rules++;
409416

417+
if (rule->tun_id)
418+
ip_tunnel_need_metadata();
419+
410420
notify_rule_change(RTM_NEWRULE, rule, ops, nlh, NETLINK_CB(skb).portid);
411421
flush_route_cache(ops);
412422
rules_ops_put(ops);
@@ -473,6 +483,10 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh)
473483
(rule->mark_mask != nla_get_u32(tb[FRA_FWMASK])))
474484
continue;
475485

486+
if (tb[FRA_TUN_ID] &&
487+
(rule->tun_id != nla_get_be64(tb[FRA_TUN_ID])))
488+
continue;
489+
476490
if (!ops->compare(rule, frh, tb))
477491
continue;
478492

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

504+
if (rule->tun_id)
505+
ip_tunnel_unneed_metadata();
506+
490507
list_del_rcu(&rule->list);
491508

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

540558
if (ops->nlmsg_payload)
541559
payload += ops->nlmsg_payload(rule);
@@ -591,7 +609,9 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
591609
((rule->mark_mask || rule->mark) &&
592610
nla_put_u32(skb, FRA_FWMASK, rule->mark_mask)) ||
593611
(rule->target &&
594-
nla_put_u32(skb, FRA_GOTO, rule->target)))
612+
nla_put_u32(skb, FRA_GOTO, rule->target)) ||
613+
(rule->tun_id &&
614+
nla_put_be64(skb, FRA_TUN_ID, rule->tun_id)))
595615
goto nla_put_failure;
596616

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

net/ipv4/ip_tunnel_core.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/etherdevice.h>
3333
#include <linux/if_ether.h>
3434
#include <linux/if_vlan.h>
35+
#include <linux/static_key.h>
3536

3637
#include <net/ip.h>
3738
#include <net/icmp.h>
@@ -304,3 +305,18 @@ static void __exit ip_tunnel_core_exit(void)
304305
lwtunnel_encap_del_ops(&ip_tun_lwt_ops, LWTUNNEL_ENCAP_IP);
305306
}
306307
module_exit(ip_tunnel_core_exit);
308+
309+
struct static_key ip_tunnel_metadata_cnt = STATIC_KEY_INIT_FALSE;
310+
EXPORT_SYMBOL(ip_tunnel_metadata_cnt);
311+
312+
void ip_tunnel_need_metadata(void)
313+
{
314+
static_key_slow_inc(&ip_tunnel_metadata_cnt);
315+
}
316+
EXPORT_SYMBOL_GPL(ip_tunnel_need_metadata);
317+
318+
void ip_tunnel_unneed_metadata(void)
319+
{
320+
static_key_slow_dec(&ip_tunnel_metadata_cnt);
321+
}
322+
EXPORT_SYMBOL_GPL(ip_tunnel_unneed_metadata);

0 commit comments

Comments
 (0)