mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
bonding, ipv4, ipv6, vlan: Handle NETDEV_BONDING_FAILOVER like NETDEV_NOTIFY_PEERS
It is undesirable for the bonding driver to be poking into higher level protocols, and notifiers provide a way to avoid that. This does mean removing the ability to configure reptitition of gratuitous ARPs and unsolicited NAs. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
99606477a5
commit
7c89943236
@ -9,6 +9,3 @@ bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_debugfs.o
|
|||||||
proc-$(CONFIG_PROC_FS) += bond_procfs.o
|
proc-$(CONFIG_PROC_FS) += bond_procfs.o
|
||||||
bonding-objs += $(proc-y)
|
bonding-objs += $(proc-y)
|
||||||
|
|
||||||
ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
|
|
||||||
bonding-objs += $(ipv6-y)
|
|
||||||
|
|
||||||
|
@ -89,8 +89,6 @@
|
|||||||
|
|
||||||
static int max_bonds = BOND_DEFAULT_MAX_BONDS;
|
static int max_bonds = BOND_DEFAULT_MAX_BONDS;
|
||||||
static int tx_queues = BOND_DEFAULT_TX_QUEUES;
|
static int tx_queues = BOND_DEFAULT_TX_QUEUES;
|
||||||
static int num_grat_arp = 1;
|
|
||||||
static int num_unsol_na = 1;
|
|
||||||
static int miimon = BOND_LINK_MON_INTERV;
|
static int miimon = BOND_LINK_MON_INTERV;
|
||||||
static int updelay;
|
static int updelay;
|
||||||
static int downdelay;
|
static int downdelay;
|
||||||
@ -113,10 +111,6 @@ module_param(max_bonds, int, 0);
|
|||||||
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
|
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
|
||||||
module_param(tx_queues, int, 0);
|
module_param(tx_queues, int, 0);
|
||||||
MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)");
|
MODULE_PARM_DESC(tx_queues, "Max number of transmit queues (default = 16)");
|
||||||
module_param(num_grat_arp, int, 0644);
|
|
||||||
MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event");
|
|
||||||
module_param(num_unsol_na, int, 0644);
|
|
||||||
MODULE_PARM_DESC(num_unsol_na, "Number of unsolicited IPv6 Neighbor Advertisements packets to send on failover event");
|
|
||||||
module_param(miimon, int, 0);
|
module_param(miimon, int, 0);
|
||||||
MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
|
MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
|
||||||
module_param(updelay, int, 0);
|
module_param(updelay, int, 0);
|
||||||
@ -234,7 +228,6 @@ struct bond_parm_tbl ad_select_tbl[] = {
|
|||||||
|
|
||||||
/*-------------------------- Forward declarations ---------------------------*/
|
/*-------------------------- Forward declarations ---------------------------*/
|
||||||
|
|
||||||
static void bond_send_gratuitous_arp(struct bonding *bond);
|
|
||||||
static int bond_init(struct net_device *bond_dev);
|
static int bond_init(struct net_device *bond_dev);
|
||||||
static void bond_uninit(struct net_device *bond_dev);
|
static void bond_uninit(struct net_device *bond_dev);
|
||||||
|
|
||||||
@ -1162,14 +1155,6 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
|
|||||||
bond_do_fail_over_mac(bond, new_active,
|
bond_do_fail_over_mac(bond, new_active,
|
||||||
old_active);
|
old_active);
|
||||||
|
|
||||||
if (netif_running(bond->dev)) {
|
|
||||||
bond->send_grat_arp = bond->params.num_grat_arp;
|
|
||||||
bond_send_gratuitous_arp(bond);
|
|
||||||
|
|
||||||
bond->send_unsol_na = bond->params.num_unsol_na;
|
|
||||||
bond_send_unsolicited_na(bond);
|
|
||||||
}
|
|
||||||
|
|
||||||
write_unlock_bh(&bond->curr_slave_lock);
|
write_unlock_bh(&bond->curr_slave_lock);
|
||||||
read_unlock(&bond->lock);
|
read_unlock(&bond->lock);
|
||||||
|
|
||||||
@ -2580,18 +2565,6 @@ void bond_mii_monitor(struct work_struct *work)
|
|||||||
if (bond->slave_cnt == 0)
|
if (bond->slave_cnt == 0)
|
||||||
goto re_arm;
|
goto re_arm;
|
||||||
|
|
||||||
if (bond->send_grat_arp) {
|
|
||||||
read_lock(&bond->curr_slave_lock);
|
|
||||||
bond_send_gratuitous_arp(bond);
|
|
||||||
read_unlock(&bond->curr_slave_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bond->send_unsol_na) {
|
|
||||||
read_lock(&bond->curr_slave_lock);
|
|
||||||
bond_send_unsolicited_na(bond);
|
|
||||||
read_unlock(&bond->curr_slave_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bond_miimon_inspect(bond)) {
|
if (bond_miimon_inspect(bond)) {
|
||||||
read_unlock(&bond->lock);
|
read_unlock(&bond->lock);
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
@ -2753,42 +2726,6 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Kick out a gratuitous ARP for an IP on the bonding master plus one
|
|
||||||
* for each VLAN above us.
|
|
||||||
*
|
|
||||||
* Caller must hold curr_slave_lock for read or better
|
|
||||||
*/
|
|
||||||
static void bond_send_gratuitous_arp(struct bonding *bond)
|
|
||||||
{
|
|
||||||
struct slave *slave = bond->curr_active_slave;
|
|
||||||
struct vlan_entry *vlan;
|
|
||||||
|
|
||||||
pr_debug("bond_send_grat_arp: bond %s slave %s\n",
|
|
||||||
bond->dev->name, slave ? slave->dev->name : "NULL");
|
|
||||||
|
|
||||||
if (!slave || !bond->send_grat_arp ||
|
|
||||||
test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
|
|
||||||
return;
|
|
||||||
|
|
||||||
bond->send_grat_arp--;
|
|
||||||
|
|
||||||
if (bond->master_ip) {
|
|
||||||
bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip,
|
|
||||||
bond->master_ip, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bond->vlgrp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
|
||||||
if (vlan->vlan_ip) {
|
|
||||||
bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip,
|
|
||||||
vlan->vlan_ip, vlan->vlan_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip)
|
static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32 sip, __be32 tip)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -3255,18 +3192,6 @@ void bond_activebackup_arp_mon(struct work_struct *work)
|
|||||||
if (bond->slave_cnt == 0)
|
if (bond->slave_cnt == 0)
|
||||||
goto re_arm;
|
goto re_arm;
|
||||||
|
|
||||||
if (bond->send_grat_arp) {
|
|
||||||
read_lock(&bond->curr_slave_lock);
|
|
||||||
bond_send_gratuitous_arp(bond);
|
|
||||||
read_unlock(&bond->curr_slave_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bond->send_unsol_na) {
|
|
||||||
read_lock(&bond->curr_slave_lock);
|
|
||||||
bond_send_unsolicited_na(bond);
|
|
||||||
read_unlock(&bond->curr_slave_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
|
if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
|
||||||
read_unlock(&bond->lock);
|
read_unlock(&bond->lock);
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
@ -3645,9 +3570,6 @@ static int bond_close(struct net_device *bond_dev)
|
|||||||
|
|
||||||
write_lock_bh(&bond->lock);
|
write_lock_bh(&bond->lock);
|
||||||
|
|
||||||
bond->send_grat_arp = 0;
|
|
||||||
bond->send_unsol_na = 0;
|
|
||||||
|
|
||||||
/* signal timers not to re-arm */
|
/* signal timers not to re-arm */
|
||||||
bond->kill_timers = 1;
|
bond->kill_timers = 1;
|
||||||
|
|
||||||
@ -4724,18 +4646,6 @@ static int bond_check_params(struct bond_params *params)
|
|||||||
use_carrier = 1;
|
use_carrier = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_grat_arp < 0 || num_grat_arp > 255) {
|
|
||||||
pr_warning("Warning: num_grat_arp (%d) not in range 0-255 so it was reset to 1\n",
|
|
||||||
num_grat_arp);
|
|
||||||
num_grat_arp = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_unsol_na < 0 || num_unsol_na > 255) {
|
|
||||||
pr_warning("Warning: num_unsol_na (%d) not in range 0-255 so it was reset to 1\n",
|
|
||||||
num_unsol_na);
|
|
||||||
num_unsol_na = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* reset values for 802.3ad */
|
/* reset values for 802.3ad */
|
||||||
if (bond_mode == BOND_MODE_8023AD) {
|
if (bond_mode == BOND_MODE_8023AD) {
|
||||||
if (!miimon) {
|
if (!miimon) {
|
||||||
@ -4925,8 +4835,6 @@ static int bond_check_params(struct bond_params *params)
|
|||||||
params->mode = bond_mode;
|
params->mode = bond_mode;
|
||||||
params->xmit_policy = xmit_hashtype;
|
params->xmit_policy = xmit_hashtype;
|
||||||
params->miimon = miimon;
|
params->miimon = miimon;
|
||||||
params->num_grat_arp = num_grat_arp;
|
|
||||||
params->num_unsol_na = num_unsol_na;
|
|
||||||
params->arp_interval = arp_interval;
|
params->arp_interval = arp_interval;
|
||||||
params->arp_validate = arp_validate_value;
|
params->arp_validate = arp_validate_value;
|
||||||
params->updelay = updelay;
|
params->updelay = updelay;
|
||||||
@ -5121,7 +5029,6 @@ static int __init bonding_init(void)
|
|||||||
|
|
||||||
register_netdevice_notifier(&bond_netdev_notifier);
|
register_netdevice_notifier(&bond_netdev_notifier);
|
||||||
register_inetaddr_notifier(&bond_inetaddr_notifier);
|
register_inetaddr_notifier(&bond_inetaddr_notifier);
|
||||||
bond_register_ipv6_notifier();
|
|
||||||
out:
|
out:
|
||||||
return res;
|
return res;
|
||||||
err:
|
err:
|
||||||
@ -5136,7 +5043,6 @@ static void __exit bonding_exit(void)
|
|||||||
{
|
{
|
||||||
unregister_netdevice_notifier(&bond_netdev_notifier);
|
unregister_netdevice_notifier(&bond_netdev_notifier);
|
||||||
unregister_inetaddr_notifier(&bond_inetaddr_notifier);
|
unregister_inetaddr_notifier(&bond_inetaddr_notifier);
|
||||||
bond_unregister_ipv6_notifier();
|
|
||||||
|
|
||||||
bond_destroy_sysfs();
|
bond_destroy_sysfs();
|
||||||
bond_destroy_debugfs();
|
bond_destroy_debugfs();
|
||||||
|
@ -873,84 +873,6 @@ out:
|
|||||||
static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
|
static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR,
|
||||||
bonding_show_ad_select, bonding_store_ad_select);
|
bonding_show_ad_select, bonding_store_ad_select);
|
||||||
|
|
||||||
/*
|
|
||||||
* Show and set the number of grat ARP to send after a failover event.
|
|
||||||
*/
|
|
||||||
static ssize_t bonding_show_n_grat_arp(struct device *d,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct bonding *bond = to_bond(d);
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", bond->params.num_grat_arp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t bonding_store_n_grat_arp(struct device *d,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
int new_value, ret = count;
|
|
||||||
struct bonding *bond = to_bond(d);
|
|
||||||
|
|
||||||
if (sscanf(buf, "%d", &new_value) != 1) {
|
|
||||||
pr_err("%s: no num_grat_arp value specified.\n",
|
|
||||||
bond->dev->name);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (new_value < 0 || new_value > 255) {
|
|
||||||
pr_err("%s: Invalid num_grat_arp value %d not in range 0-255; rejected.\n",
|
|
||||||
bond->dev->name, new_value);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
} else {
|
|
||||||
bond->params.num_grat_arp = new_value;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR,
|
|
||||||
bonding_show_n_grat_arp, bonding_store_n_grat_arp);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Show and set the number of unsolicited NA's to send after a failover event.
|
|
||||||
*/
|
|
||||||
static ssize_t bonding_show_n_unsol_na(struct device *d,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
char *buf)
|
|
||||||
{
|
|
||||||
struct bonding *bond = to_bond(d);
|
|
||||||
|
|
||||||
return sprintf(buf, "%d\n", bond->params.num_unsol_na);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t bonding_store_n_unsol_na(struct device *d,
|
|
||||||
struct device_attribute *attr,
|
|
||||||
const char *buf, size_t count)
|
|
||||||
{
|
|
||||||
int new_value, ret = count;
|
|
||||||
struct bonding *bond = to_bond(d);
|
|
||||||
|
|
||||||
if (sscanf(buf, "%d", &new_value) != 1) {
|
|
||||||
pr_err("%s: no num_unsol_na value specified.\n",
|
|
||||||
bond->dev->name);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_value < 0 || new_value > 255) {
|
|
||||||
pr_err("%s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
|
|
||||||
bond->dev->name, new_value);
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto out;
|
|
||||||
} else
|
|
||||||
bond->params.num_unsol_na = new_value;
|
|
||||||
out:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR,
|
|
||||||
bonding_show_n_unsol_na, bonding_store_n_unsol_na);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Show and set the MII monitor interval. There are two tricky bits
|
* Show and set the MII monitor interval. There are two tricky bits
|
||||||
* here. First, if MII monitoring is activated, then we must disable
|
* here. First, if MII monitoring is activated, then we must disable
|
||||||
@ -1650,8 +1572,6 @@ static struct attribute *per_bond_attrs[] = {
|
|||||||
&dev_attr_lacp_rate.attr,
|
&dev_attr_lacp_rate.attr,
|
||||||
&dev_attr_ad_select.attr,
|
&dev_attr_ad_select.attr,
|
||||||
&dev_attr_xmit_hash_policy.attr,
|
&dev_attr_xmit_hash_policy.attr,
|
||||||
&dev_attr_num_grat_arp.attr,
|
|
||||||
&dev_attr_num_unsol_na.attr,
|
|
||||||
&dev_attr_miimon.attr,
|
&dev_attr_miimon.attr,
|
||||||
&dev_attr_primary.attr,
|
&dev_attr_primary.attr,
|
||||||
&dev_attr_primary_reselect.attr,
|
&dev_attr_primary_reselect.attr,
|
||||||
|
@ -149,8 +149,6 @@ struct bond_params {
|
|||||||
int mode;
|
int mode;
|
||||||
int xmit_policy;
|
int xmit_policy;
|
||||||
int miimon;
|
int miimon;
|
||||||
int num_grat_arp;
|
|
||||||
int num_unsol_na;
|
|
||||||
int arp_interval;
|
int arp_interval;
|
||||||
int arp_validate;
|
int arp_validate;
|
||||||
int use_carrier;
|
int use_carrier;
|
||||||
@ -178,9 +176,6 @@ struct vlan_entry {
|
|||||||
struct list_head vlan_list;
|
struct list_head vlan_list;
|
||||||
__be32 vlan_ip;
|
__be32 vlan_ip;
|
||||||
unsigned short vlan_id;
|
unsigned short vlan_id;
|
||||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
||||||
struct in6_addr vlan_ipv6;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct slave {
|
struct slave {
|
||||||
@ -234,8 +229,6 @@ struct bonding {
|
|||||||
rwlock_t lock;
|
rwlock_t lock;
|
||||||
rwlock_t curr_slave_lock;
|
rwlock_t curr_slave_lock;
|
||||||
s8 kill_timers;
|
s8 kill_timers;
|
||||||
s8 send_grat_arp;
|
|
||||||
s8 send_unsol_na;
|
|
||||||
s8 setup_by_slave;
|
s8 setup_by_slave;
|
||||||
s8 igmp_retrans;
|
s8 igmp_retrans;
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
@ -260,9 +253,6 @@ struct bonding {
|
|||||||
struct delayed_work alb_work;
|
struct delayed_work alb_work;
|
||||||
struct delayed_work ad_work;
|
struct delayed_work ad_work;
|
||||||
struct delayed_work mcast_work;
|
struct delayed_work mcast_work;
|
||||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
||||||
struct in6_addr master_ipv6;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
#ifdef CONFIG_DEBUG_FS
|
||||||
/* debugging suport via debugfs */
|
/* debugging suport via debugfs */
|
||||||
struct dentry *debug_dir;
|
struct dentry *debug_dir;
|
||||||
@ -460,23 +450,4 @@ extern const struct bond_parm_tbl fail_over_mac_tbl[];
|
|||||||
extern const struct bond_parm_tbl pri_reselect_tbl[];
|
extern const struct bond_parm_tbl pri_reselect_tbl[];
|
||||||
extern struct bond_parm_tbl ad_select_tbl[];
|
extern struct bond_parm_tbl ad_select_tbl[];
|
||||||
|
|
||||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
||||||
void bond_send_unsolicited_na(struct bonding *bond);
|
|
||||||
void bond_register_ipv6_notifier(void);
|
|
||||||
void bond_unregister_ipv6_notifier(void);
|
|
||||||
#else
|
|
||||||
static inline void bond_send_unsolicited_na(struct bonding *bond)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static inline void bond_register_ipv6_notifier(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
static inline void bond_unregister_ipv6_notifier(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _LINUX_BONDING_H */
|
#endif /* _LINUX_BONDING_H */
|
||||||
|
@ -501,13 +501,14 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
|
|||||||
return NOTIFY_BAD;
|
return NOTIFY_BAD;
|
||||||
|
|
||||||
case NETDEV_NOTIFY_PEERS:
|
case NETDEV_NOTIFY_PEERS:
|
||||||
|
case NETDEV_BONDING_FAILOVER:
|
||||||
/* Propagate to vlan devices */
|
/* Propagate to vlan devices */
|
||||||
for (i = 0; i < VLAN_N_VID; i++) {
|
for (i = 0; i < VLAN_N_VID; i++) {
|
||||||
vlandev = vlan_group_get_device(grp, i);
|
vlandev = vlan_group_get_device(grp, i);
|
||||||
if (!vlandev)
|
if (!vlandev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, vlandev);
|
call_netdevice_notifiers(event, vlandev);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1203,6 +1203,7 @@ static int inetdev_event(struct notifier_block *this, unsigned long event,
|
|||||||
break;
|
break;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case NETDEV_NOTIFY_PEERS:
|
case NETDEV_NOTIFY_PEERS:
|
||||||
|
case NETDEV_BONDING_FAILOVER:
|
||||||
/* Send gratuitous ARP to notify of link change */
|
/* Send gratuitous ARP to notify of link change */
|
||||||
inetdev_send_gratuitous_arp(dev, in_dev);
|
inetdev_send_gratuitous_arp(dev, in_dev);
|
||||||
break;
|
break;
|
||||||
|
@ -1747,6 +1747,7 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
|
|||||||
fib6_run_gc(~0UL, net);
|
fib6_run_gc(~0UL, net);
|
||||||
break;
|
break;
|
||||||
case NETDEV_NOTIFY_PEERS:
|
case NETDEV_NOTIFY_PEERS:
|
||||||
|
case NETDEV_BONDING_FAILOVER:
|
||||||
ndisc_send_unsol_na(dev);
|
ndisc_send_unsol_na(dev);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user