path: root/net/ipv4/fib_rules.c
diff options
authorAlexander Duyck <alexander.h.duyck@redhat.com>2015-03-06 13:47:00 -0800
committerDavid S. Miller <davem@davemloft.net>2015-03-11 16:22:14 -0400
commit0ddcf43d5d4a03ded1ee3f6b3b72a0cbed4e90b1 (patch)
tree28c93b0c6eb9389182f60736103b6bfc0b61cedc /net/ipv4/fib_rules.c
parenttipc: ensure that idle links are deleted when a bearer is disabled (diff)
ipv4: FIB Local/MAIN table collapse
This patch is meant to collapse local and main into one by converting tb_data from an array to a pointer. Doing this allows us to point the local table into the main while maintaining the same variables in the table. As such the tb_data was converted from an array to a pointer, and a new array called data is added in order to still provide an object for tb_data to point to. In order to track the origin of the fib aliases a tb_id value was added in a hole that existed on 64b systems. Using this we can also reverse the merge in the event that custom FIB rules are enabled. With this patch I am seeing an improvement of 20ns to 30ns for routing lookups as long as custom rules are not enabled, with custom rules enabled we fall back to split tables and the original behavior. Signed-off-by: Alexander Duyck <alexander.h.duyck@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/fib_rules.c')
1 files changed, 16 insertions, 4 deletions
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 190d0d00d744..e9bc5e42cf43 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -174,6 +174,11 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
if (frh->tos & ~IPTOS_TOS_MASK)
goto errout;
+ /* split local/main if they are not already split */
+ err = fib_unmerge(net);
+ if (err)
+ goto errout;
if (rule->table == RT_TABLE_UNSPEC) {
if (rule->action == FR_ACT_TO_TBL) {
struct fib_table *table;
@@ -216,17 +221,24 @@ errout:
return err;
-static void fib4_rule_delete(struct fib_rule *rule)
+static int fib4_rule_delete(struct fib_rule *rule)
struct net *net = rule->fr_net;
- struct fib4_rule *rule4 = (struct fib4_rule *) rule;
+ int err;
- if (rule4->tclassid)
+ /* split local/main if they are not already split */
+ err = fib_unmerge(net);
+ if (err)
+ goto errout;
+ if (((struct fib4_rule *)rule)->tclassid)
net->ipv4.fib_has_custom_rules = true;
+ return err;
static int fib4_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,