From 1c4d5c33ddf44fdb403ca67d072fd84731504d9d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 9 Feb 2009 23:30:44 -0800 Subject: [PATCH] --- yaml --- r: 134417 b: refs/heads/master c: 4b53b361e0fbb2390f1d98ed9eede8e0c9a887b6 h: refs/heads/master i: 134415: 7b724efdeae5ead73ce5116cde2fd5f26731b1a8 v: v3 --- [refs] | 2 +- trunk/drivers/atm/solos-pci.c | 1 + trunk/drivers/isdn/hardware/mISDN/hfcmulti.c | 2 + trunk/drivers/net/enic/enic.h | 3 +- trunk/drivers/net/enic/enic_main.c | 68 ++++++++++--------- trunk/drivers/net/enic/vnic_dev.c | 33 +++++++-- trunk/drivers/net/enic/vnic_dev.h | 2 + trunk/drivers/net/enic/vnic_devcmd.h | 8 ++- trunk/drivers/net/enic/vnic_intr.h | 14 ++++ trunk/drivers/net/gianfar.c | 6 ++ trunk/drivers/net/netxen/netxen_nic.h | 2 +- trunk/drivers/net/netxen/netxen_nic_main.c | 13 +++- trunk/drivers/net/ppp_generic.c | 2 +- trunk/drivers/net/pppoe.c | 2 +- trunk/drivers/net/pppol2tp.c | 2 +- trunk/drivers/net/tulip/de2104x.c | 3 +- trunk/drivers/net/tun.c | 10 ++- trunk/net/bridge/br_forward.c | 7 +- trunk/net/ipv6/ip6_tunnel.c | 2 +- .../netfilter/nf_conntrack_proto_icmpv6.c | 25 ++++++- trunk/net/netfilter/nf_conntrack_netlink.c | 15 +++- trunk/net/netfilter/xt_sctp.c | 2 +- 22 files changed, 171 insertions(+), 53 deletions(-) diff --git a/[refs] b/[refs] index 7f05c651d242..298e9a8450ff 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 99e0fca6740b98aed1f604fc2e0acbdbc9e7578a +refs/heads/master: 4b53b361e0fbb2390f1d98ed9eede8e0c9a887b6 diff --git a/trunk/drivers/atm/solos-pci.c b/trunk/drivers/atm/solos-pci.c index 72fc0f799a64..89d7a6e94c9c 100644 --- a/trunk/drivers/atm/solos-pci.c +++ b/trunk/drivers/atm/solos-pci.c @@ -685,6 +685,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) out_release_regions: pci_release_regions(dev); out: + kfree(card); return err; } diff --git a/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c b/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c index 595ba8eb4a07..0b28141e43bf 100644 --- a/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c +++ b/trunk/drivers/isdn/hardware/mISDN/hfcmulti.c @@ -4599,6 +4599,7 @@ init_e1_port(struct hfc_multi *hc, struct hm_map *m) printk(KERN_ERR "%s: no memory for coeffs\n", __func__); ret = -ENOMEM; + kfree(bch); goto free_chan; } bch->nr = ch; @@ -4767,6 +4768,7 @@ init_multi_port(struct hfc_multi *hc, int pt) printk(KERN_ERR "%s: no memory for coeffs\n", __func__); ret = -ENOMEM; + kfree(bch); goto free_chan; } bch->nr = ch + 1; diff --git a/trunk/drivers/net/enic/enic.h b/trunk/drivers/net/enic/enic.h index a832cc5d6a1e..c26cea0b300e 100644 --- a/trunk/drivers/net/enic/enic.h +++ b/trunk/drivers/net/enic/enic.h @@ -33,7 +33,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco 10G Ethernet Driver" -#define DRV_VERSION "1.0.0.648" +#define DRV_VERSION "1.0.0.933" #define DRV_COPYRIGHT "Copyright 2008 Cisco Systems, Inc" #define PFX DRV_NAME ": " @@ -97,6 +97,7 @@ struct enic { ____cacheline_aligned struct vnic_rq rq[1]; unsigned int rq_count; int (*rq_alloc_buf)(struct vnic_rq *rq); + u64 rq_bad_fcs; struct napi_struct napi; struct net_lro_mgr lro_mgr; struct net_lro_desc lro_desc[ENIC_LRO_MAX_DESC]; diff --git a/trunk/drivers/net/enic/enic_main.c b/trunk/drivers/net/enic/enic_main.c index 5dd11563553e..03403a51f7ea 100644 --- a/trunk/drivers/net/enic/enic_main.c +++ b/trunk/drivers/net/enic/enic_main.c @@ -400,10 +400,13 @@ static irqreturn_t enic_isr_legacy(int irq, void *data) return IRQ_NONE; /* not our interrupt */ } - if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) + if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) { + vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_NOTIFY]); enic_notify_check(enic); + } if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) { + vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_ERR]); enic_log_q_error(enic); /* schedule recovery from WQ/RQ error */ schedule_work(&enic->reset); @@ -476,6 +479,8 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data) { struct enic *enic = data; + vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_ERR]); + enic_log_q_error(enic); /* schedule recovery from WQ/RQ error */ @@ -488,8 +493,8 @@ static irqreturn_t enic_isr_msix_notify(int irq, void *data) { struct enic *enic = data; + vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_NOTIFY]); enic_notify_check(enic); - vnic_intr_unmask(&enic->intr[ENIC_MSIX_NOTIFY]); return IRQ_HANDLED; } @@ -616,7 +621,7 @@ static inline void enic_queue_wq_skb(struct enic *enic, vlan_tag_insert, vlan_tag); } -/* netif_tx_lock held, process context with BHs disabled */ +/* netif_tx_lock held, process context with BHs disabled, or BH */ static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct enic *enic = netdev_priv(netdev); @@ -683,7 +688,7 @@ static struct net_device_stats *enic_get_stats(struct net_device *netdev) net_stats->rx_bytes = stats->rx.rx_bytes_ok; net_stats->rx_errors = stats->rx.rx_errors; net_stats->multicast = stats->rx.rx_multicast_frames_ok; - net_stats->rx_crc_errors = stats->rx.rx_crc_errors; + net_stats->rx_crc_errors = enic->rq_bad_fcs; net_stats->rx_dropped = stats->rx.rx_no_bufs; return net_stats; @@ -928,12 +933,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq, if (packet_error) { - if (bytes_written > 0 && !fcs_ok) { - if (net_ratelimit()) - printk(KERN_ERR PFX - "%s: packet error: bad FCS\n", - netdev->name); - } + if (bytes_written > 0 && !fcs_ok) + enic->rq_bad_fcs++; dev_kfree_skb_any(skb); @@ -1069,7 +1070,7 @@ static int enic_poll(struct napi_struct *napi, int budget) lro_flush_all(&enic->lro_mgr); napi_complete(napi); - vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]); + vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]); } return rq_work_done; @@ -1095,9 +1096,9 @@ static int enic_poll_msix(struct napi_struct *napi, int budget) vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); - /* Accumulate intr event credits for this polling + /* Return intr event credits for this polling * cycle. An intr event is the completion of a - * a WQ or RQ packet. + * RQ packet. */ vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ], @@ -1461,6 +1462,26 @@ static int enic_dev_soft_reset(struct enic *enic) return err; } +static int enic_set_niccfg(struct enic *enic) +{ + const u8 rss_default_cpu = 0; + const u8 rss_hash_type = 0; + const u8 rss_hash_bits = 0; + const u8 rss_base_cpu = 0; + const u8 rss_enable = 0; + const u8 tso_ipid_split_en = 0; + const u8 ig_vlan_strip_en = 1; + + /* Enable VLAN tag stripping. RSS not enabled (yet). + */ + + return enic_set_nic_cfg(enic, + rss_default_cpu, rss_hash_type, + rss_hash_bits, rss_base_cpu, + rss_enable, tso_ipid_split_en, + ig_vlan_strip_en); +} + static void enic_reset(struct work_struct *work) { struct enic *enic = container_of(work, struct enic, reset); @@ -1476,8 +1497,10 @@ static void enic_reset(struct work_struct *work) enic_stop(enic->netdev); enic_dev_soft_reset(enic); + vnic_dev_init(enic->vdev, 0); enic_reset_mcaddrs(enic); enic_init_vnic_resources(enic); + enic_set_niccfg(enic); enic_open(enic->netdev); rtnl_unlock(); @@ -1620,14 +1643,6 @@ static int __devinit enic_probe(struct pci_dev *pdev, unsigned int i; int err; - const u8 rss_default_cpu = 0; - const u8 rss_hash_type = 0; - const u8 rss_hash_bits = 0; - const u8 rss_base_cpu = 0; - const u8 rss_enable = 0; - const u8 tso_ipid_split_en = 0; - const u8 ig_vlan_strip_en = 1; - /* Allocate net device structure and initialize. Private * instance data is initialized to zero. */ @@ -1793,14 +1808,7 @@ static int __devinit enic_probe(struct pci_dev *pdev, enic_init_vnic_resources(enic); - /* Enable VLAN tag stripping. RSS not enabled (yet). - */ - - err = enic_set_nic_cfg(enic, - rss_default_cpu, rss_hash_type, - rss_hash_bits, rss_base_cpu, - rss_enable, tso_ipid_split_en, - ig_vlan_strip_en); + err = enic_set_niccfg(enic); if (err) { printk(KERN_ERR PFX "Failed to config nic, aborting.\n"); @@ -1858,7 +1866,6 @@ static int __devinit enic_probe(struct pci_dev *pdev, if (using_dac) netdev->features |= NETIF_F_HIGHDMA; - enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM); enic->lro_mgr.max_aggr = ENIC_LRO_MAX_AGGR; @@ -1870,7 +1877,6 @@ static int __devinit enic_probe(struct pci_dev *pdev, enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE; enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY; - err = register_netdev(netdev); if (err) { printk(KERN_ERR PFX diff --git a/trunk/drivers/net/enic/vnic_dev.c b/trunk/drivers/net/enic/vnic_dev.c index 11708579b6ce..e21b9d636aec 100644 --- a/trunk/drivers/net/enic/vnic_dev.c +++ b/trunk/drivers/net/enic/vnic_dev.c @@ -34,6 +34,9 @@ struct vnic_res { unsigned int count; }; +#define VNIC_DEV_CAP_INIT 0x0001 +#define VNIC_DEV_CAP_PERBI 0x0002 + struct vnic_dev { void *priv; struct pci_dev *pdev; @@ -50,6 +53,7 @@ struct vnic_dev { dma_addr_t stats_pa; struct vnic_devcmd_fw_info *fw_info; dma_addr_t fw_info_pa; + u32 cap_flags; }; #define VNIC_MAX_RES_HDR_SIZE \ @@ -575,9 +579,9 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) { u64 a0 = (u32)arg, a1 = 0; int wait = 1000; - int r = 0; + int r = 0; - if (vnic_dev_capable(vdev, CMD_INIT)) + if (vdev->cap_flags & VNIC_DEV_CAP_INIT) r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); else { vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait); @@ -587,8 +591,8 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg) vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait); vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait); } - } - return r; + } + return r; } int vnic_dev_link_status(struct vnic_dev *vdev) @@ -626,6 +630,22 @@ u32 vnic_dev_mtu(struct vnic_dev *vdev) return vdev->notify_copy.mtu; } +u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.link_down_cnt; +} + +u32 vnic_dev_notify_status(struct vnic_dev *vdev) +{ + if (!vnic_dev_notify_ready(vdev)) + return 0; + + return vdev->notify_copy.status; +} + void vnic_dev_set_intr_mode(struct vnic_dev *vdev, enum vnic_dev_intr_mode intr_mode) { @@ -682,6 +702,11 @@ struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev, if (!vdev->devcmd) goto err_out; + vdev->cap_flags = 0; + + if (vnic_dev_capable(vdev, CMD_INIT)) + vdev->cap_flags |= VNIC_DEV_CAP_INIT; + return vdev; err_out: diff --git a/trunk/drivers/net/enic/vnic_dev.h b/trunk/drivers/net/enic/vnic_dev.h index b9dc1821c805..8aa8db2fd03f 100644 --- a/trunk/drivers/net/enic/vnic_dev.h +++ b/trunk/drivers/net/enic/vnic_dev.h @@ -102,6 +102,8 @@ int vnic_dev_link_status(struct vnic_dev *vdev); u32 vnic_dev_port_speed(struct vnic_dev *vdev); u32 vnic_dev_msg_lvl(struct vnic_dev *vdev); u32 vnic_dev_mtu(struct vnic_dev *vdev); +u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev); +u32 vnic_dev_notify_status(struct vnic_dev *vdev); int vnic_dev_close(struct vnic_dev *vdev); int vnic_dev_enable(struct vnic_dev *vdev); int vnic_dev_disable(struct vnic_dev *vdev); diff --git a/trunk/drivers/net/enic/vnic_devcmd.h b/trunk/drivers/net/enic/vnic_devcmd.h index 8062c75154e6..2587f34fbfbd 100644 --- a/trunk/drivers/net/enic/vnic_devcmd.h +++ b/trunk/drivers/net/enic/vnic_devcmd.h @@ -191,7 +191,7 @@ enum vnic_devcmd_cmd { CMD_INIT_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 31), /* INT13 API: (u64)a0=paddr to vnic_int13_params struct - * (u8)a1=INT13_CMD_xxx */ + * (u32)a1=INT13_CMD_xxx */ CMD_INT13 = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_FC, 32), /* logical uplink enable/disable: (u64)a0: 0/1=disable/enable */ @@ -207,6 +207,11 @@ enum vnic_devcmd_cmd { * in: (u32)a0=cmd * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */ CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36), + + /* persistent binding info + * in: (u64)a0=paddr of arg + * (u32)a1=CMD_PERBI_XXX */ + CMD_PERBI = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37), }; /* flags for CMD_OPEN */ @@ -259,6 +264,7 @@ struct vnic_devcmd_notify { u32 status; /* status bits (see VNIC_STF_*) */ u32 error; /* error code (see ERR_*) for first ERR */ u32 link_down_cnt; /* running count of link down transitions */ + u32 perbi_rebuild_cnt; /* running count of perbi rebuilds */ }; #define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */ #define VNIC_STF_STD_PAUSE 0x0002 /* standard link-level pause on */ diff --git a/trunk/drivers/net/enic/vnic_intr.h b/trunk/drivers/net/enic/vnic_intr.h index ce633a5a7e3c..9a53604edce6 100644 --- a/trunk/drivers/net/enic/vnic_intr.h +++ b/trunk/drivers/net/enic/vnic_intr.h @@ -76,6 +76,20 @@ static inline void vnic_intr_return_credits(struct vnic_intr *intr, iowrite32(int_credit_return, &intr->ctrl->int_credit_return); } +static inline unsigned int vnic_intr_credits(struct vnic_intr *intr) +{ + return ioread32(&intr->ctrl->int_credits); +} + +static inline void vnic_intr_return_all_credits(struct vnic_intr *intr) +{ + unsigned int credits = vnic_intr_credits(intr); + int unmask = 1; + int reset_timer = 1; + + vnic_intr_return_credits(intr, credits, unmask, reset_timer); +} + static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba) { /* read PBA without clearing */ diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index 802a9516ce41..a64a4385f5a5 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -1668,6 +1668,12 @@ static void gfar_schedule_cleanup(struct net_device *dev) if (napi_schedule_prep(&priv->napi)) { gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED); __napi_schedule(&priv->napi); + } else { + /* + * Clear IEVENT, so interrupts aren't called again + * because of the packets that have already arrived. + */ + gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK); } spin_unlock(&priv->rxlock); diff --git a/trunk/drivers/net/netxen/netxen_nic.h b/trunk/drivers/net/netxen/netxen_nic.h index 9c78c963b721..f4dd9acb6877 100644 --- a/trunk/drivers/net/netxen/netxen_nic.h +++ b/trunk/drivers/net/netxen/netxen_nic.h @@ -1203,7 +1203,7 @@ typedef struct { #define NETXEN_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) -#define MSIX_ENTRIES_PER_ADAPTER 8 +#define MSIX_ENTRIES_PER_ADAPTER 1 #define NETXEN_MSIX_TBL_SPACE 8192 #define NETXEN_PCI_REG_MSIX_TBL 0x44 diff --git a/trunk/drivers/net/netxen/netxen_nic_main.c b/trunk/drivers/net/netxen/netxen_nic_main.c index ada462e94c96..5597c754f127 100644 --- a/trunk/drivers/net/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/netxen/netxen_nic_main.c @@ -76,6 +76,7 @@ static void netxen_nic_poll_controller(struct net_device *netdev); #endif static irqreturn_t netxen_intr(int irq, void *data); static irqreturn_t netxen_msi_intr(int irq, void *data); +static irqreturn_t netxen_msix_intr(int irq, void *data); /* PCI Device ID Table */ #define ENTRY(device) \ @@ -1084,7 +1085,9 @@ static int netxen_nic_open(struct net_device *netdev) for (ring = 0; ring < adapter->max_rds_rings; ring++) netxen_post_rx_buffers(adapter, ctx, ring); } - if (NETXEN_IS_MSI_FAMILY(adapter)) + if (adapter->flags & NETXEN_NIC_MSIX_ENABLED) + handler = netxen_msix_intr; + else if (adapter->flags & NETXEN_NIC_MSI_ENABLED) handler = netxen_msi_intr; else { flags |= IRQF_SHARED; @@ -1612,6 +1615,14 @@ static irqreturn_t netxen_msi_intr(int irq, void *data) return IRQ_HANDLED; } +static irqreturn_t netxen_msix_intr(int irq, void *data) +{ + struct netxen_adapter *adapter = data; + + napi_schedule(&adapter->napi); + return IRQ_HANDLED; +} + static int netxen_nic_poll(struct napi_struct *napi, int budget) { struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi); diff --git a/trunk/drivers/net/ppp_generic.c b/trunk/drivers/net/ppp_generic.c index 4405a76ed3da..fddc8493f35c 100644 --- a/trunk/drivers/net/ppp_generic.c +++ b/trunk/drivers/net/ppp_generic.c @@ -901,7 +901,7 @@ static __net_exit void ppp_exit_net(struct net *net) kfree(pn); } -static __net_initdata struct pernet_operations ppp_net_ops = { +static struct pernet_operations ppp_net_ops = { .init = ppp_init_net, .exit = ppp_exit_net, }; diff --git a/trunk/drivers/net/pppoe.c b/trunk/drivers/net/pppoe.c index 1011fd64108b..af6321d97574 100644 --- a/trunk/drivers/net/pppoe.c +++ b/trunk/drivers/net/pppoe.c @@ -1175,7 +1175,7 @@ static __net_exit void pppoe_exit_net(struct net *net) kfree(pn); } -static __net_initdata struct pernet_operations pppoe_net_ops = { +static struct pernet_operations pppoe_net_ops = { .init = pppoe_init_net, .exit = pppoe_exit_net, }; diff --git a/trunk/drivers/net/pppol2tp.c b/trunk/drivers/net/pppol2tp.c index 15f4a43a6890..1ba0f6864ac4 100644 --- a/trunk/drivers/net/pppol2tp.c +++ b/trunk/drivers/net/pppol2tp.c @@ -2647,7 +2647,7 @@ static __net_exit void pppol2tp_exit_net(struct net *net) kfree(pn); } -static __net_initdata struct pernet_operations pppol2tp_net_ops = { +static struct pernet_operations pppol2tp_net_ops = { .init = pppol2tp_init_net, .exit = pppol2tp_exit_net, }; diff --git a/trunk/drivers/net/tulip/de2104x.c b/trunk/drivers/net/tulip/de2104x.c index 0bf2114738be..d4c5ecc51f77 100644 --- a/trunk/drivers/net/tulip/de2104x.c +++ b/trunk/drivers/net/tulip/de2104x.c @@ -464,13 +464,14 @@ static void de_rx (struct de_private *de) drop = 1; rx_next: - de->rx_ring[rx_tail].opts1 = cpu_to_le32(DescOwn); if (rx_tail == (DE_RX_RING_SIZE - 1)) de->rx_ring[rx_tail].opts2 = cpu_to_le32(RingEnd | de->rx_buf_sz); else de->rx_ring[rx_tail].opts2 = cpu_to_le32(de->rx_buf_sz); de->rx_ring[rx_tail].addr1 = cpu_to_le32(mapping); + wmb(); + de->rx_ring[rx_tail].opts1 = cpu_to_le32(DescOwn); rx_tail = NEXT_RX(rx_tail); } diff --git a/trunk/drivers/net/tun.c b/trunk/drivers/net/tun.c index 0476549841ac..4825c52924bf 100644 --- a/trunk/drivers/net/tun.c +++ b/trunk/drivers/net/tun.c @@ -260,10 +260,16 @@ static int update_filter(struct tap_filter *filter, void __user *arg) nexact = n; - /* The rest is hashed */ + /* Remaining multicast addresses are hashed, + * unicast will leave the filter disabled. */ memset(filter->mask, 0, sizeof(filter->mask)); - for (; n < uf.count; n++) + for (; n < uf.count; n++) { + if (!is_multicast_ether_addr(addr[n].u)) { + err = 0; /* no filter */ + goto done; + } addr_hash_set(filter->mask, addr[n].u); + } /* For ALLMULTI just set the mask to all ones. * This overrides the mask populated above. */ diff --git a/trunk/net/bridge/br_forward.c b/trunk/net/bridge/br_forward.c index bdd9ccea17ce..d2c27c808d3b 100644 --- a/trunk/net/bridge/br_forward.c +++ b/trunk/net/bridge/br_forward.c @@ -67,6 +67,11 @@ static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb) { struct net_device *indev; + if (skb_warn_if_lro(skb)) { + kfree_skb(skb); + return; + } + indev = skb->dev; skb->dev = to->dev; skb_forward_csum(skb); @@ -89,7 +94,7 @@ void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) /* called with rcu_read_lock */ void br_forward(const struct net_bridge_port *to, struct sk_buff *skb) { - if (!skb_warn_if_lro(skb) && should_deliver(to, skb)) { + if (should_deliver(to, skb)) { __br_forward(to, skb); return; } diff --git a/trunk/net/ipv6/ip6_tunnel.c b/trunk/net/ipv6/ip6_tunnel.c index 58e2b0d93758..d994c55a5b16 100644 --- a/trunk/net/ipv6/ip6_tunnel.c +++ b/trunk/net/ipv6/ip6_tunnel.c @@ -249,8 +249,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) } t = netdev_priv(dev); - ip6_tnl_dev_init(dev); t->parms = *p; + ip6_tnl_dev_init(dev); if ((err = register_netdevice(dev)) < 0) goto failed_free; diff --git a/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c index c455cf4ee756..c323643ffcf9 100644 --- a/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +++ b/trunk/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c @@ -49,8 +49,19 @@ static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb, static const u_int8_t invmap[] = { [ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1, [ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1, - [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1, - [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY +1 + [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_REPLY + 1, + [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_QUERY +1 +}; + +static const u_int8_t noct_valid_new[] = { + [ICMPV6_MGM_QUERY - 130] = 1, + [ICMPV6_MGM_REPORT -130] = 1, + [ICMPV6_MGM_REDUCTION - 130] = 1, + [NDISC_ROUTER_SOLICITATION - 130] = 1, + [NDISC_ROUTER_ADVERTISEMENT - 130] = 1, + [NDISC_NEIGHBOUR_SOLICITATION - 130] = 1, + [NDISC_NEIGHBOUR_ADVERTISEMENT - 130] = 1, + [ICMPV6_MLD2_REPORT - 130] = 1 }; static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple, @@ -178,6 +189,7 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, { const struct icmp6hdr *icmp6h; struct icmp6hdr _ih; + int type; icmp6h = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); if (icmp6h == NULL) { @@ -194,6 +206,15 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, return -NF_ACCEPT; } + type = icmp6h->icmp6_type - 130; + if (type >= 0 && type < sizeof(noct_valid_new) && + noct_valid_new[type]) { + skb->nfct = &nf_conntrack_untracked.ct_general; + skb->nfctinfo = IP_CT_NEW; + nf_conntrack_get(skb->nfct); + return NF_ACCEPT; + } + /* is not error message ? */ if (icmp6h->icmp6_type >= 128) return NF_ACCEPT; diff --git a/trunk/net/netfilter/nf_conntrack_netlink.c b/trunk/net/netfilter/nf_conntrack_netlink.c index c32a7e8e3a1b..cb78aa00399e 100644 --- a/trunk/net/netfilter/nf_conntrack_netlink.c +++ b/trunk/net/netfilter/nf_conntrack_netlink.c @@ -434,7 +434,7 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, } else return NOTIFY_DONE; - if (!nfnetlink_has_listeners(group)) + if (!item->report && !nfnetlink_has_listeners(group)) return NOTIFY_DONE; skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); @@ -1215,6 +1215,16 @@ ctnetlink_create_conntrack(struct nlattr *cda[], } } +#ifdef CONFIG_NF_NAT_NEEDED + if (cda[CTA_NAT_SEQ_ADJ_ORIG] || cda[CTA_NAT_SEQ_ADJ_REPLY]) { + err = ctnetlink_change_nat_seq_adj(ct, cda); + if (err < 0) { + rcu_read_unlock(); + goto err; + } + } +#endif + if (cda[CTA_PROTOINFO]) { err = ctnetlink_change_protoinfo(ct, cda); if (err < 0) { @@ -1492,7 +1502,8 @@ static int ctnetlink_expect_event(struct notifier_block *this, } else return NOTIFY_DONE; - if (!nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) + if (!item->report && + !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) return NOTIFY_DONE; skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC); diff --git a/trunk/net/netfilter/xt_sctp.c b/trunk/net/netfilter/xt_sctp.c index e223cb43ae8e..a189ada9128f 100644 --- a/trunk/net/netfilter/xt_sctp.c +++ b/trunk/net/netfilter/xt_sctp.c @@ -105,7 +105,7 @@ match_packet(const struct sk_buff *skb, switch (chunk_match_type) { case SCTP_CHUNK_MATCH_ALL: - return SCTP_CHUNKMAP_IS_CLEAR(info->chunkmap); + return SCTP_CHUNKMAP_IS_CLEAR(chunkmapcopy); case SCTP_CHUNK_MATCH_ANY: return false; case SCTP_CHUNK_MATCH_ONLY: