summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--include/net/neighbour.h1
-rw-r--r--net/core/neighbour.c10
3 files changed, 12 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 6b9d4edb7c2..603730804da 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -974,6 +974,7 @@ struct net_device_ops {
int (*ndo_set_features)(struct net_device *dev,
netdev_features_t features);
int (*ndo_neigh_construct)(struct neighbour *n);
+ void (*ndo_neigh_destroy)(struct neighbour *n);
};
/*
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 6814c4d61c1..e31f0a86f9b 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -43,6 +43,7 @@ struct neigh_parms {
#endif
struct net_device *dev;
struct neigh_parms *next;
+ int (*neigh_setup)(struct neighbour *);
void (*neigh_cleanup)(struct neighbour *);
struct neigh_table *tbl;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index d57a40a2598..4af151e1bf5 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -497,6 +497,13 @@ struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
}
}
+ /* Device specific setup. */
+ if (n->parms->neigh_setup &&
+ (error = n->parms->neigh_setup(n)) < 0) {
+ rc = ERR_PTR(error);
+ goto out_neigh_release;
+ }
+
n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
write_lock_bh(&tbl->lock);
@@ -710,6 +717,9 @@ void neigh_destroy(struct neighbour *neigh)
skb_queue_purge(&neigh->arp_queue);
neigh->arp_queue_len_bytes = 0;
+ if (dev->netdev_ops->ndo_neigh_destroy)
+ dev->netdev_ops->ndo_neigh_destroy(neigh);
+
dev_put(dev);
neigh_parms_put(neigh->parms);