Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (28 commits) ipheth: remove incorrect devtype to WWAN MAINTAINERS: Add CAIF sctp: fix test for end of loop KS8851: Correct RX packet allocation udp: add rehash on connect() net: blackhole route should always be recalculated ipv4: Suppress lockdep-RCU false positive in FIB trie (3) niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL ipvs: fix active FTP gro: Re-fix different skb headrooms via-velocity: Turn scatter-gather support back off. ipv4: Fix reverse path filtering with multipath routing. UNIX: Do not loop forever at unix_autobind(). PATCH: b44 Handle RX FIFO overflow better (simplified) irda: off by one 3c59x: Fix deadlock in vortex_error() netfilter: discard overlapping IPv6 fragment ipv6: discard overlapping fragment net: fix tx queue selection for bridged devices implementing select_queue bonding: Fix jiffies overflow problems (again) ... Fix up trivial conflicts due to the same cgroup API thinko fix going through both Andrew and the networking tree. However, there were small differences between the two, with Andrew's version generally being the nicer one, and the one I merged first. So pick that one. Conflicts in: include/linux/cgroup.h and kernel/cgroup.c
This commit is contained in:
commit
002e473d1c
37 changed files with 384 additions and 304 deletions
10
MAINTAINERS
10
MAINTAINERS
|
@ -1445,6 +1445,16 @@ S: Maintained
|
|||
F: Documentation/video4linux/cafe_ccic
|
||||
F: drivers/media/video/cafe_ccic*
|
||||
|
||||
CAIF NETWORK LAYER
|
||||
M: Sjur Braendeland <sjur.brandeland@stericsson.com>
|
||||
L: netdev@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/networking/caif/
|
||||
F: drivers/net/caif/
|
||||
F: include/linux/caif/
|
||||
F: include/net/caif/
|
||||
F: net/caif/
|
||||
|
||||
CALGARY x86-64 IOMMU
|
||||
M: Muli Ben-Yehuda <muli@il.ibm.com>
|
||||
M: "Jon D. Mason" <jdmason@kudzu.us>
|
||||
|
|
|
@ -1994,10 +1994,9 @@ vortex_error(struct net_device *dev, int status)
|
|||
}
|
||||
}
|
||||
|
||||
if (status & RxEarly) { /* Rx early is unused. */
|
||||
vortex_rx(dev);
|
||||
if (status & RxEarly) /* Rx early is unused. */
|
||||
iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD);
|
||||
}
|
||||
|
||||
if (status & StatsFull) { /* Empty statistics. */
|
||||
static int DoneDidThat;
|
||||
if (vortex_debug > 4)
|
||||
|
@ -2298,7 +2297,12 @@ vortex_interrupt(int irq, void *dev_id)
|
|||
if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
|
||||
if (status == 0xffff)
|
||||
break;
|
||||
if (status & RxEarly)
|
||||
vortex_rx(dev);
|
||||
spin_unlock(&vp->window_lock);
|
||||
vortex_error(dev, status);
|
||||
spin_lock(&vp->window_lock);
|
||||
window_set(vp, 7);
|
||||
}
|
||||
|
||||
if (--work_done < 0) {
|
||||
|
|
|
@ -848,6 +848,15 @@ static int b44_poll(struct napi_struct *napi, int budget)
|
|||
b44_tx(bp);
|
||||
/* spin_unlock(&bp->tx_lock); */
|
||||
}
|
||||
if (bp->istat & ISTAT_RFO) { /* fast recovery, in ~20msec */
|
||||
bp->istat &= ~ISTAT_RFO;
|
||||
b44_disable_ints(bp);
|
||||
ssb_device_enable(bp->sdev, 0); /* resets ISTAT_RFO */
|
||||
b44_init_rings(bp);
|
||||
b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
|
||||
netif_wake_queue(bp->dev);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&bp->lock, flags);
|
||||
|
||||
work_done = 0;
|
||||
|
|
|
@ -181,6 +181,7 @@ struct be_drvr_stats {
|
|||
u64 be_rx_bytes_prev;
|
||||
u64 be_rx_pkts;
|
||||
u32 be_rx_rate;
|
||||
u32 be_rx_mcast_pkt;
|
||||
/* number of non ether type II frames dropped where
|
||||
* frame len > length field of Mac Hdr */
|
||||
u32 be_802_3_dropped_frames;
|
||||
|
|
|
@ -140,10 +140,8 @@ int be_process_mcc(struct be_adapter *adapter, int *status)
|
|||
while ((compl = be_mcc_compl_get(adapter))) {
|
||||
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
|
||||
/* Interpret flags as an async trailer */
|
||||
BUG_ON(!is_link_state_evt(compl->flags));
|
||||
|
||||
/* Interpret compl as a async link evt */
|
||||
be_async_link_state_process(adapter,
|
||||
if (is_link_state_evt(compl->flags))
|
||||
be_async_link_state_process(adapter,
|
||||
(struct be_async_event_link_state *) compl);
|
||||
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
|
||||
*status = be_mcc_compl_process(adapter, compl);
|
||||
|
@ -207,7 +205,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
|
|||
|
||||
if (msecs > 4000) {
|
||||
dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
|
||||
be_dump_ue(adapter);
|
||||
be_detect_dump_ue(adapter);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -992,5 +992,5 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
|
|||
extern int be_cmd_get_phy_info(struct be_adapter *adapter,
|
||||
struct be_dma_mem *cmd);
|
||||
extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
|
||||
extern void be_dump_ue(struct be_adapter *adapter);
|
||||
extern void be_detect_dump_ue(struct be_adapter *adapter);
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ static const struct be_ethtool_stat et_stats[] = {
|
|||
{DRVSTAT_INFO(be_rx_events)},
|
||||
{DRVSTAT_INFO(be_tx_compl)},
|
||||
{DRVSTAT_INFO(be_rx_compl)},
|
||||
{DRVSTAT_INFO(be_rx_mcast_pkt)},
|
||||
{DRVSTAT_INFO(be_ethrx_post_fail)},
|
||||
{DRVSTAT_INFO(be_802_3_dropped_frames)},
|
||||
{DRVSTAT_INFO(be_802_3_malformed_frames)},
|
||||
|
|
|
@ -167,8 +167,11 @@
|
|||
#define FLASH_FCoE_BIOS_START_g3 (13631488)
|
||||
#define FLASH_REDBOOT_START_g3 (262144)
|
||||
|
||||
|
||||
|
||||
/************* Rx Packet Type Encoding **************/
|
||||
#define BE_UNICAST_PACKET 0
|
||||
#define BE_MULTICAST_PACKET 1
|
||||
#define BE_BROADCAST_PACKET 2
|
||||
#define BE_RSVD_PACKET 3
|
||||
|
||||
/*
|
||||
* BE descriptors: host memory data structures whose formats
|
||||
|
|
|
@ -247,6 +247,7 @@ void netdev_stats_update(struct be_adapter *adapter)
|
|||
dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts;
|
||||
dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes;
|
||||
dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes;
|
||||
dev_stats->multicast = drvr_stats(adapter)->be_rx_mcast_pkt;
|
||||
|
||||
/* bad pkts received */
|
||||
dev_stats->rx_errors = port_stats->rx_crc_errors +
|
||||
|
@ -294,7 +295,6 @@ void netdev_stats_update(struct be_adapter *adapter)
|
|||
/* no space available in linux */
|
||||
dev_stats->tx_dropped = 0;
|
||||
|
||||
dev_stats->multicast = port_stats->rx_multicast_frames;
|
||||
dev_stats->collisions = 0;
|
||||
|
||||
/* detailed tx_errors */
|
||||
|
@ -848,7 +848,7 @@ static void be_rx_rate_update(struct be_adapter *adapter)
|
|||
}
|
||||
|
||||
static void be_rx_stats_update(struct be_adapter *adapter,
|
||||
u32 pktsize, u16 numfrags)
|
||||
u32 pktsize, u16 numfrags, u8 pkt_type)
|
||||
{
|
||||
struct be_drvr_stats *stats = drvr_stats(adapter);
|
||||
|
||||
|
@ -856,6 +856,9 @@ static void be_rx_stats_update(struct be_adapter *adapter,
|
|||
stats->be_rx_frags += numfrags;
|
||||
stats->be_rx_bytes += pktsize;
|
||||
stats->be_rx_pkts++;
|
||||
|
||||
if (pkt_type == BE_MULTICAST_PACKET)
|
||||
stats->be_rx_mcast_pkt++;
|
||||
}
|
||||
|
||||
static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
|
||||
|
@ -925,9 +928,11 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
|
|||
u16 rxq_idx, i, j;
|
||||
u32 pktsize, hdr_len, curr_frag_len, size;
|
||||
u8 *start;
|
||||
u8 pkt_type;
|
||||
|
||||
rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
|
||||
pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
|
||||
pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
|
||||
|
||||
page_info = get_rx_page_info(adapter, rxq_idx);
|
||||
|
||||
|
@ -993,7 +998,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
|
|||
BUG_ON(j > MAX_SKB_FRAGS);
|
||||
|
||||
done:
|
||||
be_rx_stats_update(adapter, pktsize, num_rcvd);
|
||||
be_rx_stats_update(adapter, pktsize, num_rcvd, pkt_type);
|
||||
}
|
||||
|
||||
/* Process the RX completion indicated by rxcp when GRO is disabled */
|
||||
|
@ -1060,6 +1065,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
|
|||
u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
|
||||
u16 i, rxq_idx = 0, vid, j;
|
||||
u8 vtm;
|
||||
u8 pkt_type;
|
||||
|
||||
num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
|
||||
/* Is it a flush compl that has no data */
|
||||
|
@ -1070,6 +1076,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
|
|||
vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
|
||||
rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
|
||||
vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
|
||||
pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
|
||||
|
||||
/* vlanf could be wrongly set in some cards.
|
||||
* ignore if vtm is not set */
|
||||
|
@ -1125,7 +1132,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
|
|||
vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid);
|
||||
}
|
||||
|
||||
be_rx_stats_update(adapter, pkt_size, num_rcvd);
|
||||
be_rx_stats_update(adapter, pkt_size, num_rcvd, pkt_type);
|
||||
}
|
||||
|
||||
static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter)
|
||||
|
@ -1743,26 +1750,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static inline bool be_detect_ue(struct be_adapter *adapter)
|
||||
{
|
||||
u32 online0 = 0, online1 = 0;
|
||||
|
||||
pci_read_config_dword(adapter->pdev, PCICFG_ONLINE0, &online0);
|
||||
|
||||
pci_read_config_dword(adapter->pdev, PCICFG_ONLINE1, &online1);
|
||||
|
||||
if (!online0 || !online1) {
|
||||
adapter->ue_detected = true;
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"UE Detected!! online0=%d online1=%d\n",
|
||||
online0, online1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void be_dump_ue(struct be_adapter *adapter)
|
||||
void be_detect_dump_ue(struct be_adapter *adapter)
|
||||
{
|
||||
u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask;
|
||||
u32 i;
|
||||
|
@ -1779,6 +1767,11 @@ void be_dump_ue(struct be_adapter *adapter)
|
|||
ue_status_lo = (ue_status_lo & (~ue_status_lo_mask));
|
||||
ue_status_hi = (ue_status_hi & (~ue_status_hi_mask));
|
||||
|
||||
if (ue_status_lo || ue_status_hi) {
|
||||
adapter->ue_detected = true;
|
||||
dev_err(&adapter->pdev->dev, "UE Detected!!\n");
|
||||
}
|
||||
|
||||
if (ue_status_lo) {
|
||||
for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) {
|
||||
if (ue_status_lo & 1)
|
||||
|
@ -1814,10 +1807,8 @@ static void be_worker(struct work_struct *work)
|
|||
adapter->rx_post_starved = false;
|
||||
be_post_rx_frags(adapter);
|
||||
}
|
||||
if (!adapter->ue_detected) {
|
||||
if (be_detect_ue(adapter))
|
||||
be_dump_ue(adapter);
|
||||
}
|
||||
if (!adapter->ue_detected)
|
||||
be_detect_dump_ue(adapter);
|
||||
|
||||
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
|
||||
}
|
||||
|
|
|
@ -2797,9 +2797,15 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
|
|||
* so it can wait
|
||||
*/
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
unsigned long trans_start = dev_trans_start(slave->dev);
|
||||
|
||||
if (slave->link != BOND_LINK_UP) {
|
||||
if (time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks) &&
|
||||
time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) {
|
||||
if (time_in_range(jiffies,
|
||||
trans_start - delta_in_ticks,
|
||||
trans_start + delta_in_ticks) &&
|
||||
time_in_range(jiffies,
|
||||
slave->dev->last_rx - delta_in_ticks,
|
||||
slave->dev->last_rx + delta_in_ticks)) {
|
||||
|
||||
slave->link = BOND_LINK_UP;
|
||||
slave->state = BOND_STATE_ACTIVE;
|
||||
|
@ -2827,8 +2833,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
|
|||
* when the source ip is 0, so don't take the link down
|
||||
* if we don't know our ip yet
|
||||
*/
|
||||
if (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2*delta_in_ticks) ||
|
||||
(time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks))) {
|
||||
if (!time_in_range(jiffies,
|
||||
trans_start - delta_in_ticks,
|
||||
trans_start + 2 * delta_in_ticks) ||
|
||||
!time_in_range(jiffies,
|
||||
slave->dev->last_rx - delta_in_ticks,
|
||||
slave->dev->last_rx + 2 * delta_in_ticks)) {
|
||||
|
||||
slave->link = BOND_LINK_DOWN;
|
||||
slave->state = BOND_STATE_BACKUP;
|
||||
|
@ -2883,13 +2893,16 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
|
|||
{
|
||||
struct slave *slave;
|
||||
int i, commit = 0;
|
||||
unsigned long trans_start;
|
||||
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
slave->new_link = BOND_LINK_NOCHANGE;
|
||||
|
||||
if (slave->link != BOND_LINK_UP) {
|
||||
if (time_before_eq(jiffies, slave_last_rx(bond, slave) +
|
||||
delta_in_ticks)) {
|
||||
if (time_in_range(jiffies,
|
||||
slave_last_rx(bond, slave) - delta_in_ticks,
|
||||
slave_last_rx(bond, slave) + delta_in_ticks)) {
|
||||
|
||||
slave->new_link = BOND_LINK_UP;
|
||||
commit++;
|
||||
}
|
||||
|
@ -2902,8 +2915,9 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
|
|||
* active. This avoids bouncing, as the last receive
|
||||
* times need a full ARP monitor cycle to be updated.
|
||||
*/
|
||||
if (!time_after_eq(jiffies, slave->jiffies +
|
||||
2 * delta_in_ticks))
|
||||
if (time_in_range(jiffies,
|
||||
slave->jiffies - delta_in_ticks,
|
||||
slave->jiffies + 2 * delta_in_ticks))
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
@ -2921,8 +2935,10 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
|
|||
*/
|
||||
if (slave->state == BOND_STATE_BACKUP &&
|
||||
!bond->current_arp_slave &&
|
||||
time_after(jiffies, slave_last_rx(bond, slave) +
|
||||
3 * delta_in_ticks)) {
|
||||
!time_in_range(jiffies,
|
||||
slave_last_rx(bond, slave) - delta_in_ticks,
|
||||
slave_last_rx(bond, slave) + 3 * delta_in_ticks)) {
|
||||
|
||||
slave->new_link = BOND_LINK_DOWN;
|
||||
commit++;
|
||||
}
|
||||
|
@ -2933,11 +2949,15 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
|
|||
* - (more than 2*delta since receive AND
|
||||
* the bond has an IP address)
|
||||
*/
|
||||
trans_start = dev_trans_start(slave->dev);
|
||||
if ((slave->state == BOND_STATE_ACTIVE) &&
|
||||
(time_after_eq(jiffies, dev_trans_start(slave->dev) +
|
||||
2 * delta_in_ticks) ||
|
||||
(time_after_eq(jiffies, slave_last_rx(bond, slave)
|
||||
+ 2 * delta_in_ticks)))) {
|
||||
(!time_in_range(jiffies,
|
||||
trans_start - delta_in_ticks,
|
||||
trans_start + 2 * delta_in_ticks) ||
|
||||
!time_in_range(jiffies,
|
||||
slave_last_rx(bond, slave) - delta_in_ticks,
|
||||
slave_last_rx(bond, slave) + 2 * delta_in_ticks))) {
|
||||
|
||||
slave->new_link = BOND_LINK_DOWN;
|
||||
commit++;
|
||||
}
|
||||
|
@ -2956,6 +2976,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
|
|||
{
|
||||
struct slave *slave;
|
||||
int i;
|
||||
unsigned long trans_start;
|
||||
|
||||
bond_for_each_slave(bond, slave, i) {
|
||||
switch (slave->new_link) {
|
||||
|
@ -2963,10 +2984,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
|
|||
continue;
|
||||
|
||||
case BOND_LINK_UP:
|
||||
trans_start = dev_trans_start(slave->dev);
|
||||
if ((!bond->curr_active_slave &&
|
||||
time_before_eq(jiffies,
|
||||
dev_trans_start(slave->dev) +
|
||||
delta_in_ticks)) ||
|
||||
time_in_range(jiffies,
|
||||
trans_start - delta_in_ticks,
|
||||
trans_start + delta_in_ticks)) ||
|
||||
bond->curr_active_slave != slave) {
|
||||
slave->link = BOND_LINK_UP;
|
||||
bond->current_arp_slave = NULL;
|
||||
|
|
|
@ -503,30 +503,33 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
|
|||
ks8851_wrreg16(ks, KS_RXQCR,
|
||||
ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE);
|
||||
|
||||
if (rxlen > 0) {
|
||||
skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8);
|
||||
if (!skb) {
|
||||
/* todo - dump frame and move on */
|
||||
if (rxlen > 4) {
|
||||
unsigned int rxalign;
|
||||
|
||||
rxlen -= 4;
|
||||
rxalign = ALIGN(rxlen, 4);
|
||||
skb = netdev_alloc_skb_ip_align(ks->netdev, rxalign);
|
||||
if (skb) {
|
||||
|
||||
/* 4 bytes of status header + 4 bytes of
|
||||
* garbage: we put them before ethernet
|
||||
* header, so that they are copied,
|
||||
* but ignored.
|
||||
*/
|
||||
|
||||
rxpkt = skb_put(skb, rxlen) - 8;
|
||||
|
||||
ks8851_rdfifo(ks, rxpkt, rxalign + 8);
|
||||
|
||||
if (netif_msg_pktdata(ks))
|
||||
ks8851_dbg_dumpkkt(ks, rxpkt);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, ks->netdev);
|
||||
netif_rx(skb);
|
||||
|
||||
ks->netdev->stats.rx_packets++;
|
||||
ks->netdev->stats.rx_bytes += rxlen;
|
||||
}
|
||||
|
||||
/* two bytes to ensure ip is aligned, and four bytes
|
||||
* for the status header and 4 bytes of garbage */
|
||||
skb_reserve(skb, 2 + 4 + 4);
|
||||
|
||||
rxpkt = skb_put(skb, rxlen - 4) - 8;
|
||||
|
||||
/* align the packet length to 4 bytes, and add 4 bytes
|
||||
* as we're getting the rx status header as well */
|
||||
ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8);
|
||||
|
||||
if (netif_msg_pktdata(ks))
|
||||
ks8851_dbg_dumpkkt(ks, rxpkt);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, ks->netdev);
|
||||
netif_rx(skb);
|
||||
|
||||
ks->netdev->stats.rx_packets++;
|
||||
ks->netdev->stats.rx_bytes += rxlen - 4;
|
||||
}
|
||||
|
||||
ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);
|
||||
|
|
|
@ -7269,32 +7269,28 @@ static int niu_get_ethtool_tcam_all(struct niu *np,
|
|||
struct niu_parent *parent = np->parent;
|
||||
struct niu_tcam_entry *tp;
|
||||
int i, idx, cnt;
|
||||
u16 n_entries;
|
||||
unsigned long flags;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
/* put the tcam size here */
|
||||
nfc->data = tcam_get_size(np);
|
||||
|
||||
niu_lock_parent(np, flags);
|
||||
n_entries = nfc->rule_cnt;
|
||||
for (cnt = 0, i = 0; i < nfc->data; i++) {
|
||||
idx = tcam_get_index(np, i);
|
||||
tp = &parent->tcam[idx];
|
||||
if (!tp->valid)
|
||||
continue;
|
||||
if (cnt == nfc->rule_cnt) {
|
||||
ret = -EMSGSIZE;
|
||||
break;
|
||||
}
|
||||
rule_locs[cnt] = i;
|
||||
cnt++;
|
||||
}
|
||||
niu_unlock_parent(np, flags);
|
||||
|
||||
if (n_entries != cnt) {
|
||||
/* print warning, this should not happen */
|
||||
netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n",
|
||||
np->parent->index, __func__, n_entries, cnt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
|
||||
|
|
|
@ -1865,15 +1865,15 @@ static int stmmac_resume(struct platform_device *pdev)
|
|||
if (!netif_running(dev))
|
||||
return 0;
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
if (priv->shutdown) {
|
||||
/* Re-open the interface and re-init the MAC/DMA
|
||||
and the rings. */
|
||||
and the rings (i.e. on hibernation stage) */
|
||||
stmmac_open(dev);
|
||||
goto out_resume;
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock(&priv->lock);
|
||||
|
||||
/* Power Down bit, into the PM register, is cleared
|
||||
* automatically as soon as a magic packet or a Wake-up frame
|
||||
* is received. Anyway, it's better to manually clear
|
||||
|
@ -1901,7 +1901,6 @@ static int stmmac_resume(struct platform_device *pdev)
|
|||
|
||||
netif_start_queue(dev);
|
||||
|
||||
out_resume:
|
||||
spin_unlock(&priv->lock);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -429,10 +429,6 @@ static const struct net_device_ops ipheth_netdev_ops = {
|
|||
.ndo_get_stats = &ipheth_stats,
|
||||
};
|
||||
|
||||
static struct device_type ipheth_type = {
|
||||
.name = "wwan",
|
||||
};
|
||||
|
||||
static int ipheth_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
|
@ -450,7 +446,7 @@ static int ipheth_probe(struct usb_interface *intf,
|
|||
|
||||
netdev->netdev_ops = &ipheth_netdev_ops;
|
||||
netdev->watchdog_timeo = IPHETH_TX_TIMEOUT;
|
||||
strcpy(netdev->name, "wwan%d");
|
||||
strcpy(netdev->name, "eth%d");
|
||||
|
||||
dev = netdev_priv(netdev);
|
||||
dev->udev = udev;
|
||||
|
@ -500,7 +496,6 @@ static int ipheth_probe(struct usb_interface *intf,
|
|||
|
||||
SET_NETDEV_DEV(netdev, &intf->dev);
|
||||
SET_ETHTOOL_OPS(netdev, &ops);
|
||||
SET_NETDEV_DEVTYPE(netdev, &ipheth_type);
|
||||
|
||||
retval = register_netdev(netdev);
|
||||
if (retval) {
|
||||
|
|
|
@ -2824,7 +2824,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
|
|||
netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
|
||||
|
||||
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
|
||||
NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM | NETIF_F_SG;
|
||||
NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM;
|
||||
|
||||
ret = register_netdev(dev);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -60,17 +60,8 @@ static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Init poll structure */
|
||||
void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
|
||||
unsigned long mask, struct vhost_dev *dev)
|
||||
static void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn)
|
||||
{
|
||||
struct vhost_work *work = &poll->work;
|
||||
|
||||
init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
|
||||
init_poll_funcptr(&poll->table, vhost_poll_func);
|
||||
poll->mask = mask;
|
||||
poll->dev = dev;
|
||||
|
||||
INIT_LIST_HEAD(&work->node);
|
||||
work->fn = fn;
|
||||
init_waitqueue_head(&work->done);
|
||||
|
@ -78,6 +69,18 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
|
|||
work->queue_seq = work->done_seq = 0;
|
||||
}
|
||||
|
||||
/* Init poll structure */
|
||||
void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
|
||||
unsigned long mask, struct vhost_dev *dev)
|
||||
{
|
||||
init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
|
||||
init_poll_funcptr(&poll->table, vhost_poll_func);
|
||||
poll->mask = mask;
|
||||
poll->dev = dev;
|
||||
|
||||
vhost_work_init(&poll->work, fn);
|
||||
}
|
||||
|
||||
/* Start polling a file. We add ourselves to file's wait queue. The caller must
|
||||
* keep a reference to a file until after vhost_poll_stop is called. */
|
||||
void vhost_poll_start(struct vhost_poll *poll, struct file *file)
|
||||
|
@ -95,35 +98,38 @@ void vhost_poll_stop(struct vhost_poll *poll)
|
|||
remove_wait_queue(poll->wqh, &poll->wait);
|
||||
}
|
||||
|
||||
/* Flush any work that has been scheduled. When calling this, don't hold any
|
||||
* locks that are also used by the callback. */
|
||||
void vhost_poll_flush(struct vhost_poll *poll)
|
||||
static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work)
|
||||
{
|
||||
struct vhost_work *work = &poll->work;
|
||||
unsigned seq;
|
||||
int left;
|
||||
int flushing;
|
||||
|
||||
spin_lock_irq(&poll->dev->work_lock);
|
||||
spin_lock_irq(&dev->work_lock);
|
||||
seq = work->queue_seq;
|
||||
work->flushing++;
|
||||
spin_unlock_irq(&poll->dev->work_lock);
|
||||
spin_unlock_irq(&dev->work_lock);
|
||||
wait_event(work->done, ({
|
||||
spin_lock_irq(&poll->dev->work_lock);
|
||||
spin_lock_irq(&dev->work_lock);
|
||||
left = seq - work->done_seq <= 0;
|
||||
spin_unlock_irq(&poll->dev->work_lock);
|
||||
spin_unlock_irq(&dev->work_lock);
|
||||
left;
|
||||
}));
|
||||
spin_lock_irq(&poll->dev->work_lock);
|
||||
spin_lock_irq(&dev->work_lock);
|
||||
flushing = --work->flushing;
|
||||
spin_unlock_irq(&poll->dev->work_lock);
|
||||
spin_unlock_irq(&dev->work_lock);
|
||||
BUG_ON(flushing < 0);
|
||||
}
|
||||
|
||||
void vhost_poll_queue(struct vhost_poll *poll)
|
||||
/* Flush any work that has been scheduled. When calling this, don't hold any
|
||||
* locks that are also used by the callback. */
|
||||
void vhost_poll_flush(struct vhost_poll *poll)
|
||||
{
|
||||
vhost_work_flush(poll->dev, &poll->work);
|
||||
}
|
||||
|
||||
static inline void vhost_work_queue(struct vhost_dev *dev,
|
||||
struct vhost_work *work)
|
||||
{
|
||||
struct vhost_dev *dev = poll->dev;
|
||||
struct vhost_work *work = &poll->work;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->work_lock, flags);
|
||||
|
@ -135,6 +141,11 @@ void vhost_poll_queue(struct vhost_poll *poll)
|
|||
spin_unlock_irqrestore(&dev->work_lock, flags);
|
||||
}
|
||||
|
||||
void vhost_poll_queue(struct vhost_poll *poll)
|
||||
{
|
||||
vhost_work_queue(poll->dev, &poll->work);
|
||||
}
|
||||
|
||||
static void vhost_vq_reset(struct vhost_dev *dev,
|
||||
struct vhost_virtqueue *vq)
|
||||
{
|
||||
|
@ -236,6 +247,29 @@ long vhost_dev_check_owner(struct vhost_dev *dev)
|
|||
return dev->mm == current->mm ? 0 : -EPERM;
|
||||
}
|
||||
|
||||
struct vhost_attach_cgroups_struct {
|
||||
struct vhost_work work;
|
||||
struct task_struct *owner;
|
||||
int ret;
|
||||
};
|
||||
|
||||
static void vhost_attach_cgroups_work(struct vhost_work *work)
|
||||
{
|
||||
struct vhost_attach_cgroups_struct *s;
|
||||
s = container_of(work, struct vhost_attach_cgroups_struct, work);
|
||||
s->ret = cgroup_attach_task_all(s->owner, current);
|
||||
}
|
||||
|
||||
static int vhost_attach_cgroups(struct vhost_dev *dev)
|
||||
{
|
||||
struct vhost_attach_cgroups_struct attach;
|
||||
attach.owner = current;
|
||||
vhost_work_init(&attach.work, vhost_attach_cgroups_work);
|
||||
vhost_work_queue(dev, &attach.work);
|
||||
vhost_work_flush(dev, &attach.work);
|
||||
return attach.ret;
|
||||
}
|
||||
|
||||
/* Caller should have device mutex */
|
||||
static long vhost_dev_set_owner(struct vhost_dev *dev)
|
||||
{
|
||||
|
@ -255,14 +289,16 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
|
|||
}
|
||||
|
||||
dev->worker = worker;
|
||||
err = cgroup_attach_task_current_cg(worker);
|
||||
wake_up_process(worker); /* avoid contributing to loadavg */
|
||||
|
||||
err = vhost_attach_cgroups(dev);
|
||||
if (err)
|
||||
goto err_cgroup;
|
||||
wake_up_process(worker); /* avoid contributing to loadavg */
|
||||
|
||||
return 0;
|
||||
err_cgroup:
|
||||
kthread_stop(worker);
|
||||
dev->worker = NULL;
|
||||
err_worker:
|
||||
if (dev->mm)
|
||||
mmput(dev->mm);
|
||||
|
|
|
@ -27,11 +27,17 @@ struct cgroup_cls_state
|
|||
#ifdef CONFIG_NET_CLS_CGROUP
|
||||
static inline u32 task_cls_classid(struct task_struct *p)
|
||||
{
|
||||
int classid;
|
||||
|
||||
if (in_interrupt())
|
||||
return 0;
|
||||
|
||||
return container_of(task_subsys_state(p, net_cls_subsys_id),
|
||||
struct cgroup_cls_state, css)->classid;
|
||||
rcu_read_lock();
|
||||
classid = container_of(task_subsys_state(p, net_cls_subsys_id),
|
||||
struct cgroup_cls_state, css)->classid;
|
||||
rcu_read_unlock();
|
||||
|
||||
return classid;
|
||||
}
|
||||
#else
|
||||
extern int net_cls_subsys_id;
|
||||
|
|
|
@ -955,6 +955,9 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
|
|||
return csum_partial(diff, sizeof(diff), oldsum);
|
||||
}
|
||||
|
||||
extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
|
||||
int outin);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _NET_IP_VS_H */
|
||||
|
|
|
@ -752,6 +752,7 @@ struct proto {
|
|||
/* Keeping track of sk's, looking them up, and port selection methods. */
|
||||
void (*hash)(struct sock *sk);
|
||||
void (*unhash)(struct sock *sk);
|
||||
void (*rehash)(struct sock *sk);
|
||||
int (*get_port)(struct sock *sk, unsigned short snum);
|
||||
|
||||
/* Keeping track of sockets in use */
|
||||
|
|
|
@ -151,6 +151,7 @@ static inline void udp_lib_hash(struct sock *sk)
|
|||
}
|
||||
|
||||
extern void udp_lib_unhash(struct sock *sk);
|
||||
extern void udp_lib_rehash(struct sock *sk, u16 new_hash);
|
||||
|
||||
static inline void udp_lib_close(struct sock *sk, long timeout)
|
||||
{
|
||||
|
|
|
@ -2058,16 +2058,16 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
|
|||
struct sk_buff *skb)
|
||||
{
|
||||
int queue_index;
|
||||
struct sock *sk = skb->sk;
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
|
||||
queue_index = sk_tx_queue_get(sk);
|
||||
if (queue_index < 0) {
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
if (ops->ndo_select_queue) {
|
||||
queue_index = ops->ndo_select_queue(dev, skb);
|
||||
queue_index = dev_cap_txqueue(dev, queue_index);
|
||||
} else {
|
||||
struct sock *sk = skb->sk;
|
||||
queue_index = sk_tx_queue_get(sk);
|
||||
if (queue_index < 0) {
|
||||
|
||||
if (ops->ndo_select_queue) {
|
||||
queue_index = ops->ndo_select_queue(dev, skb);
|
||||
queue_index = dev_cap_txqueue(dev, queue_index);
|
||||
} else {
|
||||
queue_index = 0;
|
||||
if (dev->real_num_tx_queues > 1)
|
||||
queue_index = skb_tx_hash(dev, skb);
|
||||
|
|
|
@ -2706,7 +2706,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
|
|||
} else if (skb_gro_len(p) != pinfo->gso_size)
|
||||
return -E2BIG;
|
||||
|
||||
headroom = NET_SKB_PAD + NET_IP_ALIGN;
|
||||
headroom = skb_headroom(p);
|
||||
nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
|
||||
if (unlikely(!nskb))
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -62,8 +62,11 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
}
|
||||
if (!inet->inet_saddr)
|
||||
inet->inet_saddr = rt->rt_src; /* Update source address */
|
||||
if (!inet->inet_rcv_saddr)
|
||||
if (!inet->inet_rcv_saddr) {
|
||||
inet->inet_rcv_saddr = rt->rt_src;
|
||||
if (sk->sk_prot->rehash)
|
||||
sk->sk_prot->rehash(sk);
|
||||
}
|
||||
inet->inet_daddr = rt->rt_dst;
|
||||
inet->inet_dport = usin->sin_port;
|
||||
sk->sk_state = TCP_ESTABLISHED;
|
||||
|
|
|
@ -246,6 +246,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
|
|||
|
||||
struct fib_result res;
|
||||
int no_addr, rpf, accept_local;
|
||||
bool dev_match;
|
||||
int ret;
|
||||
struct net *net;
|
||||
|
||||
|
@ -273,12 +274,22 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
|
|||
}
|
||||
*spec_dst = FIB_RES_PREFSRC(res);
|
||||
fib_combine_itag(itag, &res);
|
||||
dev_match = false;
|
||||
|
||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||
if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
|
||||
for (ret = 0; ret < res.fi->fib_nhs; ret++) {
|
||||
struct fib_nh *nh = &res.fi->fib_nh[ret];
|
||||
|
||||
if (nh->nh_dev == dev) {
|
||||
dev_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (FIB_RES_DEV(res) == dev)
|
||||
dev_match = true;
|
||||
#endif
|
||||
{
|
||||
if (dev_match) {
|
||||
ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
|
||||
fib_res_put(&res);
|
||||
return ret;
|
||||
|
|
|
@ -186,7 +186,9 @@ static inline struct tnode *node_parent_rcu(struct node *node)
|
|||
{
|
||||
struct tnode *ret = node_parent(node);
|
||||
|
||||
return rcu_dereference(ret);
|
||||
return rcu_dereference_check(ret,
|
||||
rcu_read_lock_held() ||
|
||||
lockdep_rtnl_is_held());
|
||||
}
|
||||
|
||||
/* Same as rcu_assign_pointer
|
||||
|
@ -1753,7 +1755,9 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
|
|||
|
||||
static struct leaf *trie_firstleaf(struct trie *t)
|
||||
{
|
||||
struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
|
||||
struct tnode *n = (struct tnode *) rcu_dereference_check(t->trie,
|
||||
rcu_read_lock_held() ||
|
||||
lockdep_rtnl_is_held());
|
||||
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
|
|
@ -2738,6 +2738,11 @@ int __ip_route_output_key(struct net *net, struct rtable **rp,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(__ip_route_output_key);
|
||||
|
||||
static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
|
||||
{
|
||||
}
|
||||
|
@ -2746,7 +2751,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
|
|||
.family = AF_INET,
|
||||
.protocol = cpu_to_be16(ETH_P_IP),
|
||||
.destroy = ipv4_dst_destroy,
|
||||
.check = ipv4_dst_check,
|
||||
.check = ipv4_blackhole_dst_check,
|
||||
.update_pmtu = ipv4_rt_blackhole_update_pmtu,
|
||||
.entries = ATOMIC_INIT(0),
|
||||
};
|
||||
|
|
|
@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk)
|
|||
}
|
||||
EXPORT_SYMBOL(udp_lib_unhash);
|
||||
|
||||
/*
|
||||
* inet_rcv_saddr was changed, we must rehash secondary hash
|
||||
*/
|
||||
void udp_lib_rehash(struct sock *sk, u16 newhash)
|
||||
{
|
||||
if (sk_hashed(sk)) {
|
||||
struct udp_table *udptable = sk->sk_prot->h.udp_table;
|
||||
struct udp_hslot *hslot, *hslot2, *nhslot2;
|
||||
|
||||
hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
|
||||
nhslot2 = udp_hashslot2(udptable, newhash);
|
||||
udp_sk(sk)->udp_portaddr_hash = newhash;
|
||||
if (hslot2 != nhslot2) {
|
||||
hslot = udp_hashslot(udptable, sock_net(sk),
|
||||
udp_sk(sk)->udp_port_hash);
|
||||
/* we must lock primary chain too */
|
||||
spin_lock_bh(&hslot->lock);
|
||||
|
||||
spin_lock(&hslot2->lock);
|
||||
hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node);
|
||||
hslot2->count--;
|
||||
spin_unlock(&hslot2->lock);
|
||||
|
||||
spin_lock(&nhslot2->lock);
|
||||
hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node,
|
||||
&nhslot2->head);
|
||||
nhslot2->count++;
|
||||
spin_unlock(&nhslot2->lock);
|
||||
|
||||
spin_unlock_bh(&hslot->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(udp_lib_rehash);
|
||||
|
||||
static void udp_v4_rehash(struct sock *sk)
|
||||
{
|
||||
u16 new_hash = udp4_portaddr_hash(sock_net(sk),
|
||||
inet_sk(sk)->inet_rcv_saddr,
|
||||
inet_sk(sk)->inet_num);
|
||||
udp_lib_rehash(sk, new_hash);
|
||||
}
|
||||
|
||||
static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
int rc;
|
||||
|
@ -1843,6 +1886,7 @@ struct proto udp_prot = {
|
|||
.backlog_rcv = __udp_queue_rcv_skb,
|
||||
.hash = udp_lib_hash,
|
||||
.unhash = udp_lib_unhash,
|
||||
.rehash = udp_v4_rehash,
|
||||
.get_port = udp_v4_get_port,
|
||||
.memory_allocated = &udp_memory_allocated,
|
||||
.sysctl_mem = sysctl_udp_mem,
|
||||
|
|
|
@ -105,9 +105,12 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
if (ipv6_addr_any(&np->saddr))
|
||||
ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
|
||||
|
||||
if (ipv6_addr_any(&np->rcv_saddr))
|
||||
if (ipv6_addr_any(&np->rcv_saddr)) {
|
||||
ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
|
||||
&np->rcv_saddr);
|
||||
if (sk->sk_prot->rehash)
|
||||
sk->sk_prot->rehash(sk);
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
@ -181,6 +184,8 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
|||
if (ipv6_addr_any(&np->rcv_saddr)) {
|
||||
ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
|
||||
inet->inet_rcv_saddr = LOOPBACK4_IPV6;
|
||||
if (sk->sk_prot->rehash)
|
||||
sk->sk_prot->rehash(sk);
|
||||
}
|
||||
|
||||
ip6_dst_store(sk, dst,
|
||||
|
|
|
@ -113,14 +113,6 @@ static void nf_skb_free(struct sk_buff *skb)
|
|||
kfree_skb(NFCT_FRAG6_CB(skb)->orig);
|
||||
}
|
||||
|
||||
/* Memory Tracking Functions. */
|
||||
static void frag_kfree_skb(struct sk_buff *skb)
|
||||
{
|
||||
atomic_sub(skb->truesize, &nf_init_frags.mem);
|
||||
nf_skb_free(skb);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* Destruction primitives. */
|
||||
|
||||
static __inline__ void fq_put(struct nf_ct_frag6_queue *fq)
|
||||
|
@ -282,66 +274,22 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
found:
|
||||
/* We found where to put this one. Check for overlap with
|
||||
* preceding fragment, and, if needed, align things so that
|
||||
* any overlaps are eliminated.
|
||||
/* RFC5722, Section 4:
|
||||
* When reassembling an IPv6 datagram, if
|
||||
* one or more its constituent fragments is determined to be an
|
||||
* overlapping fragment, the entire datagram (and any constituent
|
||||
* fragments, including those not yet received) MUST be silently
|
||||
* discarded.
|
||||
*/
|
||||
if (prev) {
|
||||
int i = (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset;
|
||||
|
||||
if (i > 0) {
|
||||
offset += i;
|
||||
if (end <= offset) {
|
||||
pr_debug("overlap\n");
|
||||
goto err;
|
||||
}
|
||||
if (!pskb_pull(skb, i)) {
|
||||
pr_debug("Can't pull\n");
|
||||
goto err;
|
||||
}
|
||||
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
}
|
||||
}
|
||||
/* Check for overlap with preceding fragment. */
|
||||
if (prev &&
|
||||
(NFCT_FRAG6_CB(prev)->offset + prev->len) - offset > 0)
|
||||
goto discard_fq;
|
||||
|
||||
/* Look for overlap with succeeding segments.
|
||||
* If we can merge fragments, do it.
|
||||
*/
|
||||
while (next && NFCT_FRAG6_CB(next)->offset < end) {
|
||||
/* overlap is 'i' bytes */
|
||||
int i = end - NFCT_FRAG6_CB(next)->offset;
|
||||
|
||||
if (i < next->len) {
|
||||
/* Eat head of the next overlapped fragment
|
||||
* and leave the loop. The next ones cannot overlap.
|
||||
*/
|
||||
pr_debug("Eat head of the overlapped parts.: %d", i);
|
||||
if (!pskb_pull(next, i))
|
||||
goto err;
|
||||
|
||||
/* next fragment */
|
||||
NFCT_FRAG6_CB(next)->offset += i;
|
||||
fq->q.meat -= i;
|
||||
if (next->ip_summed != CHECKSUM_UNNECESSARY)
|
||||
next->ip_summed = CHECKSUM_NONE;
|
||||
break;
|
||||
} else {
|
||||
struct sk_buff *free_it = next;
|
||||
|
||||
/* Old fragmnet is completely overridden with
|
||||
* new one drop it.
|
||||
*/
|
||||
next = next->next;
|
||||
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
fq->q.fragments = next;
|
||||
|
||||
fq->q.meat -= free_it->len;
|
||||
frag_kfree_skb(free_it);
|
||||
}
|
||||
}
|
||||
/* Look for overlap with succeeding segment. */
|
||||
if (next && NFCT_FRAG6_CB(next)->offset < end)
|
||||
goto discard_fq;
|
||||
|
||||
NFCT_FRAG6_CB(skb)->offset = offset;
|
||||
|
||||
|
@ -371,6 +319,8 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
|
|||
write_unlock(&nf_frags.lock);
|
||||
return 0;
|
||||
|
||||
discard_fq:
|
||||
fq_kill(fq);
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -149,13 +149,6 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a)
|
|||
}
|
||||
EXPORT_SYMBOL(ip6_frag_match);
|
||||
|
||||
/* Memory Tracking Functions. */
|
||||
static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb)
|
||||
{
|
||||
atomic_sub(skb->truesize, &nf->mem);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
void ip6_frag_init(struct inet_frag_queue *q, void *a)
|
||||
{
|
||||
struct frag_queue *fq = container_of(q, struct frag_queue, q);
|
||||
|
@ -346,58 +339,22 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
found:
|
||||
/* We found where to put this one. Check for overlap with
|
||||
* preceding fragment, and, if needed, align things so that
|
||||
* any overlaps are eliminated.
|
||||
/* RFC5722, Section 4:
|
||||
* When reassembling an IPv6 datagram, if
|
||||
* one or more its constituent fragments is determined to be an
|
||||
* overlapping fragment, the entire datagram (and any constituent
|
||||
* fragments, including those not yet received) MUST be silently
|
||||
* discarded.
|
||||
*/
|
||||
if (prev) {
|
||||
int i = (FRAG6_CB(prev)->offset + prev->len) - offset;
|
||||
|
||||
if (i > 0) {
|
||||
offset += i;
|
||||
if (end <= offset)
|
||||
goto err;
|
||||
if (!pskb_pull(skb, i))
|
||||
goto err;
|
||||
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
}
|
||||
}
|
||||
/* Check for overlap with preceding fragment. */
|
||||
if (prev &&
|
||||
(FRAG6_CB(prev)->offset + prev->len) - offset > 0)
|
||||
goto discard_fq;
|
||||
|
||||
/* Look for overlap with succeeding segments.
|
||||
* If we can merge fragments, do it.
|
||||
*/
|
||||
while (next && FRAG6_CB(next)->offset < end) {
|
||||
int i = end - FRAG6_CB(next)->offset; /* overlap is 'i' bytes */
|
||||
|
||||
if (i < next->len) {
|
||||
/* Eat head of the next overlapped fragment
|
||||
* and leave the loop. The next ones cannot overlap.
|
||||
*/
|
||||
if (!pskb_pull(next, i))
|
||||
goto err;
|
||||
FRAG6_CB(next)->offset += i; /* next fragment */
|
||||
fq->q.meat -= i;
|
||||
if (next->ip_summed != CHECKSUM_UNNECESSARY)
|
||||
next->ip_summed = CHECKSUM_NONE;
|
||||
break;
|
||||
} else {
|
||||
struct sk_buff *free_it = next;
|
||||
|
||||
/* Old fragment is completely overridden with
|
||||
* new one drop it.
|
||||
*/
|
||||
next = next->next;
|
||||
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
fq->q.fragments = next;
|
||||
|
||||
fq->q.meat -= free_it->len;
|
||||
frag_kfree_skb(fq->q.net, free_it);
|
||||
}
|
||||
}
|
||||
/* Look for overlap with succeeding segment. */
|
||||
if (next && FRAG6_CB(next)->offset < end)
|
||||
goto discard_fq;
|
||||
|
||||
FRAG6_CB(skb)->offset = offset;
|
||||
|
||||
|
@ -436,6 +393,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
|
|||
write_unlock(&ip6_frags.lock);
|
||||
return -1;
|
||||
|
||||
discard_fq:
|
||||
fq_kill(fq);
|
||||
err:
|
||||
IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
|
||||
IPSTATS_MIB_REASMFAILS);
|
||||
|
|
|
@ -111,6 +111,15 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
|
|||
return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr);
|
||||
}
|
||||
|
||||
static void udp_v6_rehash(struct sock *sk)
|
||||
{
|
||||
u16 new_hash = udp6_portaddr_hash(sock_net(sk),
|
||||
&inet6_sk(sk)->rcv_saddr,
|
||||
inet_sk(sk)->inet_num);
|
||||
|
||||
udp_lib_rehash(sk, new_hash);
|
||||
}
|
||||
|
||||
static inline int compute_score(struct sock *sk, struct net *net,
|
||||
unsigned short hnum,
|
||||
struct in6_addr *saddr, __be16 sport,
|
||||
|
@ -1447,6 +1456,7 @@ struct proto udpv6_prot = {
|
|||
.backlog_rcv = udpv6_queue_rcv_skb,
|
||||
.hash = udp_lib_hash,
|
||||
.unhash = udp_lib_unhash,
|
||||
.rehash = udp_v6_rehash,
|
||||
.get_port = udp_v6_get_port,
|
||||
.memory_allocated = &udp_memory_allocated,
|
||||
.sysctl_mem = sysctl_udp_mem,
|
||||
|
|
|
@ -1102,7 +1102,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
|
|||
memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
|
||||
le16_to_cpus(&val_len); n+=2;
|
||||
|
||||
if (val_len > 1016) {
|
||||
if (val_len >= 1016) {
|
||||
IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ );
|
||||
return -RSP_INVALID_COMMAND_FORMAT;
|
||||
}
|
||||
|
|
|
@ -924,6 +924,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
|
||||
ip_vs_out_stats(cp, skb);
|
||||
ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
|
||||
ip_vs_update_conntrack(skb, cp, 0);
|
||||
ip_vs_conn_put(cp);
|
||||
|
||||
skb->ipvs_property = 1;
|
||||
|
|
|
@ -410,7 +410,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
|||
union nf_inet_addr to;
|
||||
__be16 port;
|
||||
struct ip_vs_conn *n_cp;
|
||||
struct nf_conn *ct;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
/* This application helper doesn't work with IPv6 yet,
|
||||
|
@ -497,11 +496,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
|||
ip_vs_control_add(n_cp, cp);
|
||||
}
|
||||
|
||||
ct = (struct nf_conn *)skb->nfct;
|
||||
if (ct && ct != &nf_conntrack_untracked)
|
||||
ip_vs_expect_related(skb, ct, n_cp,
|
||||
IPPROTO_TCP, &n_cp->dport, 1);
|
||||
|
||||
/*
|
||||
* Move tunnel to listen state
|
||||
*/
|
||||
|
|
|
@ -349,8 +349,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)
|
||||
void
|
||||
ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
|
||||
{
|
||||
struct nf_conn *ct = (struct nf_conn *)skb->nfct;
|
||||
struct nf_conntrack_tuple new_tuple;
|
||||
|
@ -365,11 +365,17 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)
|
|||
* real-server we will see RIP->DIP.
|
||||
*/
|
||||
new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
|
||||
new_tuple.src.u3 = cp->daddr;
|
||||
if (outin)
|
||||
new_tuple.src.u3 = cp->daddr;
|
||||
else
|
||||
new_tuple.dst.u3 = cp->vaddr;
|
||||
/*
|
||||
* This will also take care of UDP and other protocols.
|
||||
*/
|
||||
new_tuple.src.u.tcp.port = cp->dport;
|
||||
if (outin)
|
||||
new_tuple.src.u.tcp.port = cp->dport;
|
||||
else
|
||||
new_tuple.dst.u.tcp.port = cp->vport;
|
||||
nf_conntrack_alter_reply(ct, &new_tuple);
|
||||
}
|
||||
|
||||
|
@ -428,7 +434,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
|
||||
IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
|
||||
|
||||
ip_vs_update_conntrack(skb, cp);
|
||||
ip_vs_update_conntrack(skb, cp, 1);
|
||||
|
||||
/* FIXME: when application helper enlarges the packet and the length
|
||||
is larger than the MTU of outgoing device, there will be still
|
||||
|
@ -506,7 +512,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
|||
|
||||
IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
|
||||
|
||||
ip_vs_update_conntrack(skb, cp);
|
||||
ip_vs_update_conntrack(skb, cp, 1);
|
||||
|
||||
/* FIXME: when application helper enlarges the packet and the length
|
||||
is larger than the MTU of outgoing device, there will be still
|
||||
|
|
|
@ -1232,6 +1232,18 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool list_has_sctp_addr(const struct list_head *list,
|
||||
union sctp_addr *ipaddr)
|
||||
{
|
||||
struct sctp_transport *addr;
|
||||
|
||||
list_for_each_entry(addr, list, transports) {
|
||||
if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/* A restart is occurring, check to make sure no new addresses
|
||||
* are being added as we may be under a takeover attack.
|
||||
*/
|
||||
|
@ -1240,10 +1252,10 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
|
|||
struct sctp_chunk *init,
|
||||
sctp_cmd_seq_t *commands)
|
||||
{
|
||||
struct sctp_transport *new_addr, *addr;
|
||||
int found;
|
||||
struct sctp_transport *new_addr;
|
||||
int ret = 1;
|
||||
|
||||
/* Implementor's Guide - Sectin 5.2.2
|
||||
/* Implementor's Guide - Section 5.2.2
|
||||
* ...
|
||||
* Before responding the endpoint MUST check to see if the
|
||||
* unexpected INIT adds new addresses to the association. If new
|
||||
|
@ -1254,31 +1266,19 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
|
|||
/* Search through all current addresses and make sure
|
||||
* we aren't adding any new ones.
|
||||
*/
|
||||
new_addr = NULL;
|
||||
found = 0;
|
||||
|
||||
list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list,
|
||||
transports) {
|
||||
found = 0;
|
||||
list_for_each_entry(addr, &asoc->peer.transport_addr_list,
|
||||
transports) {
|
||||
if (sctp_cmp_addr_exact(&new_addr->ipaddr,
|
||||
&addr->ipaddr)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
transports) {
|
||||
if (!list_has_sctp_addr(&asoc->peer.transport_addr_list,
|
||||
&new_addr->ipaddr)) {
|
||||
sctp_sf_send_restart_abort(&new_addr->ipaddr, init,
|
||||
commands);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If a new address was added, ABORT the sender. */
|
||||
if (!found && new_addr) {
|
||||
sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return success if all addresses were found. */
|
||||
return found;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Populate the verification/tie tags based on overlapping INIT
|
||||
|
|
|
@ -692,6 +692,7 @@ static int unix_autobind(struct socket *sock)
|
|||
static u32 ordernum = 1;
|
||||
struct unix_address *addr;
|
||||
int err;
|
||||
unsigned int retries = 0;
|
||||
|
||||
mutex_lock(&u->readlock);
|
||||
|
||||
|
@ -717,9 +718,17 @@ static int unix_autobind(struct socket *sock)
|
|||
if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
|
||||
addr->hash)) {
|
||||
spin_unlock(&unix_table_lock);
|
||||
/* Sanity yield. It is unusual case, but yet... */
|
||||
if (!(ordernum&0xFF))
|
||||
yield();
|
||||
/*
|
||||
* __unix_find_socket_byname() may take long time if many names
|
||||
* are already in use.
|
||||
*/
|
||||
cond_resched();
|
||||
/* Give up if all names seems to be in use. */
|
||||
if (retries++ == 0xFFFFF) {
|
||||
err = -ENOSPC;
|
||||
kfree(addr);
|
||||
goto out;
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
addr->hash ^= sk->sk_type;
|
||||
|
|
Loading…
Reference in a new issue