struct fib_table *fib_new_table(struct net *net, u32 id) { struct fib_table *tb, *alias = NULL; unsigned int h; if (id == 0) id = RT_TABLE_MAIN; tb = fib_get_table(net, id); if (tb) return tb; if (id == RT_TABLE_LOCAL) alias = fib_new_table(net, RT_TABLE_MAIN); tb = fib_trie_table(id, alias); if (!tb) return NULL; switch (id) { case RT_TABLE_MAIN: rcu_assign_pointer(net->ipv4.fib_main, tb); break; case RT_TABLE_DEFAULT: rcu_assign_pointer(net->ipv4.fib_default, tb); break; default: break; } h = id & (FIB_TABLE_HASHSZ - 1); hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]); return tb; }
static int vrf_rtable_create(struct net_device *dev) { struct net_vrf *vrf = netdev_priv(dev); struct rtable *rth, *rth_local; if (!fib_new_table(dev_net(dev), vrf->tb_id)) return -ENOMEM; /* create a dst for routing packets out through a VRF device */ rth = rt_dst_alloc(dev, 0, RTN_UNICAST, 1, 1, 0); if (!rth) return -ENOMEM; /* create a dst for local ingress routing - packets sent locally * to local address via the VRF device as a loopback */ rth_local = rt_dst_alloc(dev, RTCF_LOCAL, RTN_LOCAL, 1, 1, 0); if (!rth_local) { dst_release(&rth->dst); return -ENOMEM; } rth->dst.output = vrf_output; rth->rt_table_id = vrf->tb_id; rth_local->rt_table_id = vrf->tb_id; rcu_assign_pointer(vrf->rth, rth); rcu_assign_pointer(vrf->rth_local, rth_local); return 0; }
static struct fib_table *fib_empty_table(struct net *net) { u32 id; for (id = 1; id <= RT_TABLE_MAX; id++) if (fib_get_table(net, id) == NULL) return fib_new_table(net, id); return NULL; }
static struct fib_table *fib_empty_table(struct net *net) { u32 id; #ifdef FIB_RULE_DEBUG printk(KERN_DEBUG "[NET][IPV4][RULE] %s \n", __func__); #endif for (id = 1; id <= RT_TABLE_MAX; id++) if (fib_get_table(net, id) == NULL) return fib_new_table(net, id); return NULL; }
static int vrf_rtable_create(struct net_device *dev) { struct net_vrf *vrf = netdev_priv(dev); struct rtable *rth; if (!fib_new_table(dev_net(dev), vrf->tb_id)) return -ENOMEM; rth = rt_dst_alloc(dev, 0, RTN_UNICAST, 1, 1, 0); if (!rth) return -ENOMEM; rth->dst.output = vrf_output; rth->rt_table_id = vrf->tb_id; rcu_assign_pointer(vrf->rth, rth); return 0; }