Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/bnx2x_main.c Merge bnx2x bug fixes in by hand... :-/ Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
bb7e95c8fd
|
@ -863,6 +863,10 @@ struct bnx2x {
|
||||||
|
|
||||||
/* used to synchronize stats collecting */
|
/* used to synchronize stats collecting */
|
||||||
int stats_state;
|
int stats_state;
|
||||||
|
|
||||||
|
/* used for synchronization of concurrent threads statistics handling */
|
||||||
|
spinlock_t stats_lock;
|
||||||
|
|
||||||
/* used by dmae command loader */
|
/* used by dmae command loader */
|
||||||
struct dmae_command stats_dmae;
|
struct dmae_command stats_dmae;
|
||||||
int executer_idx;
|
int executer_idx;
|
||||||
|
|
|
@ -6714,6 +6714,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
|
||||||
|
|
||||||
mutex_init(&bp->port.phy_mutex);
|
mutex_init(&bp->port.phy_mutex);
|
||||||
mutex_init(&bp->fw_mb_mutex);
|
mutex_init(&bp->fw_mb_mutex);
|
||||||
|
spin_lock_init(&bp->stats_lock);
|
||||||
#ifdef BCM_CNIC
|
#ifdef BCM_CNIC
|
||||||
mutex_init(&bp->cnic_mutex);
|
mutex_init(&bp->cnic_mutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -156,6 +156,8 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
|
||||||
struct eth_query_ramrod_data ramrod_data = {0};
|
struct eth_query_ramrod_data ramrod_data = {0};
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
|
||||||
|
spin_lock_bh(&bp->stats_lock);
|
||||||
|
|
||||||
ramrod_data.drv_counter = bp->stats_counter++;
|
ramrod_data.drv_counter = bp->stats_counter++;
|
||||||
ramrod_data.collect_port = bp->port.pmf ? 1 : 0;
|
ramrod_data.collect_port = bp->port.pmf ? 1 : 0;
|
||||||
for_each_queue(bp, i)
|
for_each_queue(bp, i)
|
||||||
|
@ -169,6 +171,8 @@ static void bnx2x_storm_stats_post(struct bnx2x *bp)
|
||||||
bp->spq_left++;
|
bp->spq_left++;
|
||||||
bp->stats_pending = 1;
|
bp->stats_pending = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_unlock_bh(&bp->stats_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,6 +738,14 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
|
||||||
struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
|
struct host_func_stats *fstats = bnx2x_sp(bp, func_stats);
|
||||||
struct bnx2x_eth_stats *estats = &bp->eth_stats;
|
struct bnx2x_eth_stats *estats = &bp->eth_stats;
|
||||||
int i;
|
int i;
|
||||||
|
u16 cur_stats_counter;
|
||||||
|
|
||||||
|
/* Make sure we use the value of the counter
|
||||||
|
* used for sending the last stats ramrod.
|
||||||
|
*/
|
||||||
|
spin_lock_bh(&bp->stats_lock);
|
||||||
|
cur_stats_counter = bp->stats_counter - 1;
|
||||||
|
spin_unlock_bh(&bp->stats_lock);
|
||||||
|
|
||||||
memcpy(&(fstats->total_bytes_received_hi),
|
memcpy(&(fstats->total_bytes_received_hi),
|
||||||
&(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
|
&(bnx2x_sp(bp, func_stats_base)->total_bytes_received_hi),
|
||||||
|
@ -761,25 +773,22 @@ static int bnx2x_storm_stats_update(struct bnx2x *bp)
|
||||||
u32 diff;
|
u32 diff;
|
||||||
|
|
||||||
/* are storm stats valid? */
|
/* are storm stats valid? */
|
||||||
if ((u16)(le16_to_cpu(xclient->stats_counter) + 1) !=
|
if (le16_to_cpu(xclient->stats_counter) != cur_stats_counter) {
|
||||||
bp->stats_counter) {
|
|
||||||
DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm"
|
DP(BNX2X_MSG_STATS, "[%d] stats not updated by xstorm"
|
||||||
" xstorm counter (0x%x) != stats_counter (0x%x)\n",
|
" xstorm counter (0x%x) != stats_counter (0x%x)\n",
|
||||||
i, xclient->stats_counter, bp->stats_counter);
|
i, xclient->stats_counter, cur_stats_counter + 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((u16)(le16_to_cpu(tclient->stats_counter) + 1) !=
|
if (le16_to_cpu(tclient->stats_counter) != cur_stats_counter) {
|
||||||
bp->stats_counter) {
|
|
||||||
DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm"
|
DP(BNX2X_MSG_STATS, "[%d] stats not updated by tstorm"
|
||||||
" tstorm counter (0x%x) != stats_counter (0x%x)\n",
|
" tstorm counter (0x%x) != stats_counter (0x%x)\n",
|
||||||
i, tclient->stats_counter, bp->stats_counter);
|
i, tclient->stats_counter, cur_stats_counter + 1);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
if ((u16)(le16_to_cpu(uclient->stats_counter) + 1) !=
|
if (le16_to_cpu(uclient->stats_counter) != cur_stats_counter) {
|
||||||
bp->stats_counter) {
|
|
||||||
DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm"
|
DP(BNX2X_MSG_STATS, "[%d] stats not updated by ustorm"
|
||||||
" ustorm counter (0x%x) != stats_counter (0x%x)\n",
|
" ustorm counter (0x%x) != stats_counter (0x%x)\n",
|
||||||
i, uclient->stats_counter, bp->stats_counter);
|
i, uclient->stats_counter, cur_stats_counter + 1);
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1216,16 +1225,18 @@ static const struct {
|
||||||
|
|
||||||
void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
|
void bnx2x_stats_handle(struct bnx2x *bp, enum bnx2x_stats_event event)
|
||||||
{
|
{
|
||||||
enum bnx2x_stats_state state = bp->stats_state;
|
enum bnx2x_stats_state state;
|
||||||
|
|
||||||
if (unlikely(bp->panic))
|
if (unlikely(bp->panic))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bnx2x_stats_stm[state][event].action(bp);
|
/* Protect a state change flow */
|
||||||
|
spin_lock_bh(&bp->stats_lock);
|
||||||
|
state = bp->stats_state;
|
||||||
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
|
bp->stats_state = bnx2x_stats_stm[state][event].next_state;
|
||||||
|
spin_unlock_bh(&bp->stats_lock);
|
||||||
|
|
||||||
/* Make sure the state has been "changed" */
|
bnx2x_stats_stm[state][event].action(bp);
|
||||||
smp_wmb();
|
|
||||||
|
|
||||||
if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
|
if ((event != STATS_EVENT_UPDATE) || netif_msg_timer(bp))
|
||||||
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
|
DP(BNX2X_MSG_STATS, "state %d -> event %d -> state %d\n",
|
||||||
|
|
|
@ -815,7 +815,7 @@ static int rlb_initialize(struct bonding *bond)
|
||||||
|
|
||||||
/*initialize packet type*/
|
/*initialize packet type*/
|
||||||
pk_type->type = cpu_to_be16(ETH_P_ARP);
|
pk_type->type = cpu_to_be16(ETH_P_ARP);
|
||||||
pk_type->dev = NULL;
|
pk_type->dev = bond->dev;
|
||||||
pk_type->func = rlb_arp_recv;
|
pk_type->func = rlb_arp_recv;
|
||||||
|
|
||||||
/* register to receive ARPs */
|
/* register to receive ARPs */
|
||||||
|
|
|
@ -1722,6 +1722,15 @@ static int __devinit igb_probe(struct pci_dev *pdev,
|
||||||
u16 eeprom_apme_mask = IGB_EEPROM_APME;
|
u16 eeprom_apme_mask = IGB_EEPROM_APME;
|
||||||
u32 part_num;
|
u32 part_num;
|
||||||
|
|
||||||
|
/* Catch broken hardware that put the wrong VF device ID in
|
||||||
|
* the PCIe SR-IOV capability.
|
||||||
|
*/
|
||||||
|
if (pdev->is_virtfn) {
|
||||||
|
WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n",
|
||||||
|
pci_name(pdev), pdev->vendor, pdev->device);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
err = pci_enable_device_mem(pdev);
|
err = pci_enable_device_mem(pdev);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -6539,6 +6539,15 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
|
||||||
#endif
|
#endif
|
||||||
u32 part_num, eec;
|
u32 part_num, eec;
|
||||||
|
|
||||||
|
/* Catch broken hardware that put the wrong VF device ID in
|
||||||
|
* the PCIe SR-IOV capability.
|
||||||
|
*/
|
||||||
|
if (pdev->is_virtfn) {
|
||||||
|
WARN(1, KERN_ERR "%s (%hx:%hx) should not be a VF!\n",
|
||||||
|
pci_name(pdev), pdev->vendor, pdev->device);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
err = pci_enable_device_mem(pdev);
|
err = pci_enable_device_mem(pdev);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -515,7 +515,7 @@ static const struct net_device_ops macvlan_netdev_ops = {
|
||||||
.ndo_validate_addr = eth_validate_addr,
|
.ndo_validate_addr = eth_validate_addr,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void macvlan_setup(struct net_device *dev)
|
void macvlan_common_setup(struct net_device *dev)
|
||||||
{
|
{
|
||||||
ether_setup(dev);
|
ether_setup(dev);
|
||||||
|
|
||||||
|
@ -524,6 +524,12 @@ static void macvlan_setup(struct net_device *dev)
|
||||||
dev->destructor = free_netdev;
|
dev->destructor = free_netdev;
|
||||||
dev->header_ops = &macvlan_hard_header_ops,
|
dev->header_ops = &macvlan_hard_header_ops,
|
||||||
dev->ethtool_ops = &macvlan_ethtool_ops;
|
dev->ethtool_ops = &macvlan_ethtool_ops;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(macvlan_common_setup);
|
||||||
|
|
||||||
|
static void macvlan_setup(struct net_device *dev)
|
||||||
|
{
|
||||||
|
macvlan_common_setup(dev);
|
||||||
dev->tx_queue_len = 0;
|
dev->tx_queue_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,7 +741,6 @@ int macvlan_link_register(struct rtnl_link_ops *ops)
|
||||||
/* common fields */
|
/* common fields */
|
||||||
ops->priv_size = sizeof(struct macvlan_dev);
|
ops->priv_size = sizeof(struct macvlan_dev);
|
||||||
ops->get_tx_queues = macvlan_get_tx_queues;
|
ops->get_tx_queues = macvlan_get_tx_queues;
|
||||||
ops->setup = macvlan_setup;
|
|
||||||
ops->validate = macvlan_validate;
|
ops->validate = macvlan_validate;
|
||||||
ops->maxtype = IFLA_MACVLAN_MAX;
|
ops->maxtype = IFLA_MACVLAN_MAX;
|
||||||
ops->policy = macvlan_policy;
|
ops->policy = macvlan_policy;
|
||||||
|
@ -749,6 +754,7 @@ EXPORT_SYMBOL_GPL(macvlan_link_register);
|
||||||
|
|
||||||
static struct rtnl_link_ops macvlan_link_ops = {
|
static struct rtnl_link_ops macvlan_link_ops = {
|
||||||
.kind = "macvlan",
|
.kind = "macvlan",
|
||||||
|
.setup = macvlan_setup,
|
||||||
.newlink = macvlan_newlink,
|
.newlink = macvlan_newlink,
|
||||||
.dellink = macvlan_dellink,
|
.dellink = macvlan_dellink,
|
||||||
};
|
};
|
||||||
|
|
|
@ -180,11 +180,18 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct macvtap_queue *q = macvtap_get_queue(dev, skb);
|
struct macvtap_queue *q = macvtap_get_queue(dev, skb);
|
||||||
if (!q)
|
if (!q)
|
||||||
return -ENOLINK;
|
goto drop;
|
||||||
|
|
||||||
|
if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len)
|
||||||
|
goto drop;
|
||||||
|
|
||||||
skb_queue_tail(&q->sk.sk_receive_queue, skb);
|
skb_queue_tail(&q->sk.sk_receive_queue, skb);
|
||||||
wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
|
wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
|
||||||
return 0;
|
return NET_RX_SUCCESS;
|
||||||
|
|
||||||
|
drop:
|
||||||
|
kfree_skb(skb);
|
||||||
|
return NET_RX_DROP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -235,8 +242,15 @@ static void macvtap_dellink(struct net_device *dev,
|
||||||
macvlan_dellink(dev, head);
|
macvlan_dellink(dev, head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void macvtap_setup(struct net_device *dev)
|
||||||
|
{
|
||||||
|
macvlan_common_setup(dev);
|
||||||
|
dev->tx_queue_len = TUN_READQ_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
|
static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
|
||||||
.kind = "macvtap",
|
.kind = "macvtap",
|
||||||
|
.setup = macvtap_setup,
|
||||||
.newlink = macvtap_newlink,
|
.newlink = macvtap_newlink,
|
||||||
.dellink = macvtap_dellink,
|
.dellink = macvtap_dellink,
|
||||||
};
|
};
|
||||||
|
|
|
@ -65,7 +65,7 @@ static int debug_level = ERR_DBG;
|
||||||
|
|
||||||
/* DEBUG message print. */
|
/* DEBUG message print. */
|
||||||
#define DBG_PRINT(dbg_level, fmt, args...) do { \
|
#define DBG_PRINT(dbg_level, fmt, args...) do { \
|
||||||
if (dbg_level >= debug_level) \
|
if (dbg_level <= debug_level) \
|
||||||
pr_info(fmt, ##args); \
|
pr_info(fmt, ##args); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
|
@ -736,8 +736,18 @@ static __inline__ ssize_t tun_put_user(struct tun_struct *tun,
|
||||||
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
||||||
else if (sinfo->gso_type & SKB_GSO_UDP)
|
else if (sinfo->gso_type & SKB_GSO_UDP)
|
||||||
gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
|
gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
|
||||||
else
|
else {
|
||||||
BUG();
|
printk(KERN_ERR "tun: unexpected GSO type: "
|
||||||
|
"0x%x, gso_size %d, hdr_len %d\n",
|
||||||
|
sinfo->gso_type, gso.gso_size,
|
||||||
|
gso.hdr_len);
|
||||||
|
print_hex_dump(KERN_ERR, "tun: ",
|
||||||
|
DUMP_PREFIX_NONE,
|
||||||
|
16, 1, skb->head,
|
||||||
|
min((int)gso.hdr_len, 64), true);
|
||||||
|
WARN_ON_ONCE(1);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
|
if (sinfo->gso_type & SKB_GSO_TCP_ECN)
|
||||||
gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
|
gso.gso_type |= VIRTIO_NET_HDR_GSO_ECN;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -152,6 +152,7 @@ enum {
|
||||||
/* Device IDs */
|
/* Device IDs */
|
||||||
USB_DEVICE_ID_I6050 = 0x0186,
|
USB_DEVICE_ID_I6050 = 0x0186,
|
||||||
USB_DEVICE_ID_I6050_2 = 0x0188,
|
USB_DEVICE_ID_I6050_2 = 0x0188,
|
||||||
|
USB_DEVICE_ID_I6250 = 0x0187,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -491,6 +491,7 @@ int i2400mu_probe(struct usb_interface *iface,
|
||||||
switch (id->idProduct) {
|
switch (id->idProduct) {
|
||||||
case USB_DEVICE_ID_I6050:
|
case USB_DEVICE_ID_I6050:
|
||||||
case USB_DEVICE_ID_I6050_2:
|
case USB_DEVICE_ID_I6050_2:
|
||||||
|
case USB_DEVICE_ID_I6250:
|
||||||
i2400mu->i6050 = 1;
|
i2400mu->i6050 = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -739,6 +740,7 @@ static
|
||||||
struct usb_device_id i2400mu_id_table[] = {
|
struct usb_device_id i2400mu_id_table[] = {
|
||||||
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) },
|
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) },
|
||||||
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) },
|
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) },
|
||||||
|
{ USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) },
|
||||||
{ USB_DEVICE(0x8086, 0x0181) },
|
{ USB_DEVICE(0x8086, 0x0181) },
|
||||||
{ USB_DEVICE(0x8086, 0x1403) },
|
{ USB_DEVICE(0x8086, 0x1403) },
|
||||||
{ USB_DEVICE(0x8086, 0x1405) },
|
{ USB_DEVICE(0x8086, 0x1405) },
|
||||||
|
|
|
@ -72,6 +72,8 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void macvlan_common_setup(struct net_device *dev);
|
||||||
|
|
||||||
extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
extern int macvlan_common_newlink(struct net *src_net, struct net_device *dev,
|
||||||
struct nlattr *tb[], struct nlattr *data[],
|
struct nlattr *tb[], struct nlattr *data[],
|
||||||
int (*receive)(struct sk_buff *skb),
|
int (*receive)(struct sk_buff *skb),
|
||||||
|
|
|
@ -9,6 +9,7 @@ struct tcf_mirred {
|
||||||
int tcfm_ifindex;
|
int tcfm_ifindex;
|
||||||
int tcfm_ok_push;
|
int tcfm_ok_push;
|
||||||
struct net_device *tcfm_dev;
|
struct net_device *tcfm_dev;
|
||||||
|
struct list_head tcfm_list;
|
||||||
};
|
};
|
||||||
#define to_mirred(pc) \
|
#define to_mirred(pc) \
|
||||||
container_of(pc, struct tcf_mirred, common)
|
container_of(pc, struct tcf_mirred, common)
|
||||||
|
|
|
@ -1484,6 +1484,7 @@ static inline void net_timestamp_check(struct sk_buff *skb)
|
||||||
int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
|
int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
skb_orphan(skb);
|
skb_orphan(skb);
|
||||||
|
nf_reset(skb);
|
||||||
|
|
||||||
if (!(dev->flags & IFF_UP) ||
|
if (!(dev->flags & IFF_UP) ||
|
||||||
(skb->len > (dev->mtu + dev->hard_header_len))) {
|
(skb->len > (dev->mtu + dev->hard_header_len))) {
|
||||||
|
|
|
@ -843,7 +843,9 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
|
||||||
skb->network_header += off;
|
skb->network_header += off;
|
||||||
if (skb_mac_header_was_set(skb))
|
if (skb_mac_header_was_set(skb))
|
||||||
skb->mac_header += off;
|
skb->mac_header += off;
|
||||||
skb->csum_start += nhead;
|
/* Only adjust this if it actually is csum_start rather than csum */
|
||||||
|
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
||||||
|
skb->csum_start += nhead;
|
||||||
skb->cloned = 0;
|
skb->cloned = 0;
|
||||||
skb->hdr_len = 0;
|
skb->hdr_len = 0;
|
||||||
skb->nohdr = 0;
|
skb->nohdr = 0;
|
||||||
|
@ -930,7 +932,8 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
|
||||||
copy_skb_header(n, skb);
|
copy_skb_header(n, skb);
|
||||||
|
|
||||||
off = newheadroom - oldheadroom;
|
off = newheadroom - oldheadroom;
|
||||||
n->csum_start += off;
|
if (n->ip_summed == CHECKSUM_PARTIAL)
|
||||||
|
n->csum_start += off;
|
||||||
#ifdef NET_SKBUFF_DATA_USES_OFFSET
|
#ifdef NET_SKBUFF_DATA_USES_OFFSET
|
||||||
n->transport_header += off;
|
n->transport_header += off;
|
||||||
n->network_header += off;
|
n->network_header += off;
|
||||||
|
|
|
@ -1763,7 +1763,10 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
|
||||||
|
|
||||||
idev = ipv6_find_idev(dev);
|
idev = ipv6_find_idev(dev);
|
||||||
if (!idev)
|
if (!idev)
|
||||||
return NULL;
|
return ERR_PTR(-ENOBUFS);
|
||||||
|
|
||||||
|
if (idev->cnf.disable_ipv6)
|
||||||
|
return ERR_PTR(-EACCES);
|
||||||
|
|
||||||
/* Add default multicast route */
|
/* Add default multicast route */
|
||||||
addrconf_add_mroute(dev);
|
addrconf_add_mroute(dev);
|
||||||
|
@ -2132,8 +2135,9 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx,
|
||||||
if (!dev)
|
if (!dev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
if ((idev = addrconf_add_dev(dev)) == NULL)
|
idev = addrconf_add_dev(dev);
|
||||||
return -ENOBUFS;
|
if (IS_ERR(idev))
|
||||||
|
return PTR_ERR(idev);
|
||||||
|
|
||||||
scope = ipv6_addr_scope(pfx);
|
scope = ipv6_addr_scope(pfx);
|
||||||
|
|
||||||
|
@ -2380,7 +2384,7 @@ static void addrconf_dev_config(struct net_device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
idev = addrconf_add_dev(dev);
|
idev = addrconf_add_dev(dev);
|
||||||
if (idev == NULL)
|
if (IS_ERR(idev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(struct in6_addr));
|
memset(&addr, 0, sizeof(struct in6_addr));
|
||||||
|
@ -2471,7 +2475,7 @@ static void addrconf_ip6_tnl_config(struct net_device *dev)
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
idev = addrconf_add_dev(dev);
|
idev = addrconf_add_dev(dev);
|
||||||
if (!idev) {
|
if (IS_ERR(idev)) {
|
||||||
printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n");
|
printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -632,7 +632,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta)
|
||||||
skb->dev = sta->sdata->dev;
|
skb->dev = sta->sdata->dev;
|
||||||
skb->protocol = eth_type_trans(skb, sta->sdata->dev);
|
skb->protocol = eth_type_trans(skb, sta->sdata->dev);
|
||||||
memset(skb->cb, 0, sizeof(skb->cb));
|
memset(skb->cb, 0, sizeof(skb->cb));
|
||||||
netif_rx(skb);
|
netif_rx_ni(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sta_apply_parameters(struct ieee80211_local *local,
|
static void sta_apply_parameters(struct ieee80211_local *local,
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1];
|
static struct tcf_common *tcf_mirred_ht[MIRRED_TAB_MASK + 1];
|
||||||
static u32 mirred_idx_gen;
|
static u32 mirred_idx_gen;
|
||||||
static DEFINE_RWLOCK(mirred_lock);
|
static DEFINE_RWLOCK(mirred_lock);
|
||||||
|
static LIST_HEAD(mirred_list);
|
||||||
|
|
||||||
static struct tcf_hashinfo mirred_hash_info = {
|
static struct tcf_hashinfo mirred_hash_info = {
|
||||||
.htab = tcf_mirred_ht,
|
.htab = tcf_mirred_ht,
|
||||||
|
@ -47,7 +48,9 @@ static inline int tcf_mirred_release(struct tcf_mirred *m, int bind)
|
||||||
m->tcf_bindcnt--;
|
m->tcf_bindcnt--;
|
||||||
m->tcf_refcnt--;
|
m->tcf_refcnt--;
|
||||||
if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
|
if(!m->tcf_bindcnt && m->tcf_refcnt <= 0) {
|
||||||
dev_put(m->tcfm_dev);
|
list_del(&m->tcfm_list);
|
||||||
|
if (m->tcfm_dev)
|
||||||
|
dev_put(m->tcfm_dev);
|
||||||
tcf_hash_destroy(&m->common, &mirred_hash_info);
|
tcf_hash_destroy(&m->common, &mirred_hash_info);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -134,8 +137,10 @@ static int tcf_mirred_init(struct nlattr *nla, struct nlattr *est,
|
||||||
m->tcfm_ok_push = ok_push;
|
m->tcfm_ok_push = ok_push;
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&m->tcf_lock);
|
spin_unlock_bh(&m->tcf_lock);
|
||||||
if (ret == ACT_P_CREATED)
|
if (ret == ACT_P_CREATED) {
|
||||||
|
list_add(&m->tcfm_list, &mirred_list);
|
||||||
tcf_hash_insert(pc, &mirred_hash_info);
|
tcf_hash_insert(pc, &mirred_hash_info);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -164,9 +169,14 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
|
||||||
m->tcf_bstats.packets++;
|
m->tcf_bstats.packets++;
|
||||||
|
|
||||||
dev = m->tcfm_dev;
|
dev = m->tcfm_dev;
|
||||||
|
if (!dev) {
|
||||||
|
printk_once(KERN_NOTICE "tc mirred: target device is gone\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(dev->flags & IFF_UP)) {
|
if (!(dev->flags & IFF_UP)) {
|
||||||
if (net_ratelimit())
|
if (net_ratelimit())
|
||||||
pr_notice("tc mirred to Houston: device %s is gone!\n",
|
pr_notice("tc mirred to Houston: device %s is down\n",
|
||||||
dev->name);
|
dev->name);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -230,6 +240,28 @@ nla_put_failure:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mirred_device_event(struct notifier_block *unused,
|
||||||
|
unsigned long event, void *ptr)
|
||||||
|
{
|
||||||
|
struct net_device *dev = ptr;
|
||||||
|
struct tcf_mirred *m;
|
||||||
|
|
||||||
|
if (event == NETDEV_UNREGISTER)
|
||||||
|
list_for_each_entry(m, &mirred_list, tcfm_list) {
|
||||||
|
if (m->tcfm_dev == dev) {
|
||||||
|
dev_put(dev);
|
||||||
|
m->tcfm_dev = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct notifier_block mirred_device_notifier = {
|
||||||
|
.notifier_call = mirred_device_event,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static struct tc_action_ops act_mirred_ops = {
|
static struct tc_action_ops act_mirred_ops = {
|
||||||
.kind = "mirred",
|
.kind = "mirred",
|
||||||
.hinfo = &mirred_hash_info,
|
.hinfo = &mirred_hash_info,
|
||||||
|
@ -250,12 +282,17 @@ MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
static int __init mirred_init_module(void)
|
static int __init mirred_init_module(void)
|
||||||
{
|
{
|
||||||
|
int err = register_netdevice_notifier(&mirred_device_notifier);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
pr_info("Mirror/redirect action on\n");
|
pr_info("Mirror/redirect action on\n");
|
||||||
return tcf_register_action(&act_mirred_ops);
|
return tcf_register_action(&act_mirred_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit mirred_cleanup_module(void)
|
static void __exit mirred_cleanup_module(void)
|
||||||
{
|
{
|
||||||
|
unregister_netdevice_notifier(&mirred_device_notifier);
|
||||||
tcf_unregister_action(&act_mirred_ops);
|
tcf_unregister_action(&act_mirred_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче