|
@@ -124,6 +124,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
|
|
|
static struct kmem_cache *mrt_cachep __read_mostly;
|
|
|
|
|
|
static struct mr_table *ipmr_new_table(struct net *net, u32 id);
|
|
|
+static void ipmr_free_table(struct mr_table *mrt);
|
|
|
+
|
|
|
static int ip_mr_forward(struct net *net, struct mr_table *mrt,
|
|
|
struct sk_buff *skb, struct mfc_cache *cache,
|
|
|
int local);
|
|
@@ -131,6 +133,7 @@ static int ipmr_cache_report(struct mr_table *mrt,
|
|
|
struct sk_buff *pkt, vifi_t vifi, int assert);
|
|
|
static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
|
|
|
struct mfc_cache *c, struct rtmsg *rtm);
|
|
|
+static void mroute_clean_tables(struct mr_table *mrt);
|
|
|
static void ipmr_expire_process(unsigned long arg);
|
|
|
|
|
|
#ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
|
|
@@ -271,7 +274,7 @@ static void __net_exit ipmr_rules_exit(struct net *net)
|
|
|
|
|
|
list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
|
|
|
list_del(&mrt->list);
|
|
|
- kfree(mrt);
|
|
|
+ ipmr_free_table(mrt);
|
|
|
}
|
|
|
fib_rules_unregister(net->ipv4.mr_rules_ops);
|
|
|
}
|
|
@@ -299,7 +302,7 @@ static int __net_init ipmr_rules_init(struct net *net)
|
|
|
|
|
|
static void __net_exit ipmr_rules_exit(struct net *net)
|
|
|
{
|
|
|
- kfree(net->ipv4.mrt);
|
|
|
+ ipmr_free_table(net->ipv4.mrt);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -336,6 +339,13 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
|
|
|
return mrt;
|
|
|
}
|
|
|
|
|
|
+static void ipmr_free_table(struct mr_table *mrt)
|
|
|
+{
|
|
|
+ del_timer_sync(&mrt->ipmr_expire_timer);
|
|
|
+ mroute_clean_tables(mrt);
|
|
|
+ kfree(mrt);
|
|
|
+}
|
|
|
+
|
|
|
/* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */
|
|
|
|
|
|
static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
|