Skip to content

Commit

Permalink
switchdev: don't support custom ip rules, for now
Browse files Browse the repository at this point in the history
Keep switchdev FIB offload model simple for now and don't allow custom ip
rules.

Signed-off-by: Scott Feldman <sfeldma@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
scottfeldman authored and davem330 committed Mar 6, 2015
1 parent 5e8d904 commit 104616e
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/net/ip_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ int fib_table_delete(struct fib_table *, struct fib_config *);
int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
struct netlink_callback *cb);
int fib_table_flush(struct fib_table *table);
void fib_table_flush_external(struct fib_table *table);
void fib_free_table(struct fib_table *tb);


Expand Down Expand Up @@ -308,6 +309,7 @@ static inline int fib_num_tclassid_users(struct net *net)
return 0;
}
#endif
void fib_flush_external(struct net *net);

/* Exported by fib_semantics.c */
int ip_fib_check_default(__be32 gw, struct net_device *dev);
Expand Down
13 changes: 13 additions & 0 deletions net/ipv4/fib_frontend.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,19 @@ static void fib_flush(struct net *net)
rt_cache_flush(net);
}

void fib_flush_external(struct net *net)
{
struct fib_table *tb;
struct hlist_head *head;
unsigned int h;

for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
head = &net->ipv4.fib_table_hash[h];
hlist_for_each_entry(tb, head, tb_hlist)
fib_table_flush_external(tb);
}
}

/*
* Find address type as if only "dev" was present in the system. If
* on_dev is NULL then all interfaces are taken into consideration.
Expand Down
3 changes: 3 additions & 0 deletions net/ipv4/fib_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
rule4->tos = frh->tos;

net->ipv4.fib_has_custom_rules = true;
fib_flush_external(rule->fr_net);

err = 0;
errout:
return err;
Expand All @@ -224,6 +226,7 @@ static void fib4_rule_delete(struct fib_rule *rule)
net->ipv4.fib_num_tclassid_users--;
#endif
net->ipv4.fib_has_custom_rules = true;
fib_flush_external(rule->fr_net);
}

static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
Expand Down
61 changes: 61 additions & 0 deletions net/ipv4/fib_trie.c
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,67 @@ static struct tnode *leaf_walk_rcu(struct tnode **tn, t_key key)
return n;
}

/* Caller must hold RTNL */
void fib_table_flush_external(struct fib_table *tb)
{
struct trie *t = (struct trie *)tb->tb_data;
struct fib_alias *fa;
struct tnode *n, *pn;
unsigned long cindex;
unsigned char slen;
int found = 0;

n = rcu_dereference(t->trie);
if (!n)
return;

pn = NULL;
cindex = 0;

while (IS_TNODE(n)) {
/* record pn and cindex for leaf walking */
pn = n;
cindex = 1ul << n->bits;
backtrace:
/* walk trie in reverse order */
do {
while (!(cindex--)) {
t_key pkey = pn->key;

n = pn;
pn = node_parent(n);

/* resize completed node */
resize(t, n);

/* if we got the root we are done */
if (!pn)
return;

cindex = get_index(pkey, pn);
}

/* grab the next available node */
n = tnode_get_child(pn, cindex);
} while (!n);
}

hlist_for_each_entry(fa, &n->leaf, fa_list) {
struct fib_info *fi = fa->fa_info;

if (fi && (fi->fib_flags & RTNH_F_EXTERNAL)) {
netdev_switch_fib_ipv4_del(n->key,
KEYLENGTH - fa->fa_slen,
fi, fa->fa_tos,
fa->fa_type, tb->tb_id);
}
}

/* if trie is leaf only loop is completed */
if (pn)
goto backtrace;
}

/* Caller must hold RTNL. */
int fib_table_flush(struct fib_table *tb)
{
Expand Down
4 changes: 4 additions & 0 deletions net/switchdev/switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ EXPORT_SYMBOL(ndo_dflt_netdev_switch_port_bridge_dellink);
int netdev_switch_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
u8 tos, u8 type, u32 tb_id)
{
/* Don't offload route if using custom ip rules */
if (fi->fib_net->ipv4.fib_has_custom_rules)
return 0;

return 0;
}
EXPORT_SYMBOL(netdev_switch_fib_ipv4_add);
Expand Down

0 comments on commit 104616e

Please sign in to comment.