* Re: IPv6: autoconfiguration and suspend/resume or link down/up
From: Dan Williams @ 2011-07-21 5:30 UTC (permalink / raw)
To: Jiri Bohac; +Cc: netdev, Herbert Xu, David S. Miller, stephen hemminger
In-Reply-To: <20110720163656.GD11692@midget.suse.cz>
On Wed, 2011-07-20 at 18:36 +0200, Jiri Bohac wrote:
> On Wed, Jul 20, 2011 at 11:21:43AM -0500, Dan Williams wrote:
> > ... and in the resume handler use that value to age anything
> > that needs to know about time spent in suspend, and then do what needs
> > to be done with that. So something like that may work for IPv6
> > addrconf; on suspend save current time, and on resume check the current
> > time, subtract the time you saved on suspend, and magically add that to
> > the lifetime counts and then run any expiry stuff.
>
> IPv6 (by specification) does not send any RS when an IP address
> or route expires. So only subtracting the supend time from the
> lifetimes and possibly expiring the routes/IP addresses won't fix
> the problem.
Well, the prefix option of the RA includes the Valid Lifetime (in
seconds, no less) so I'd assume the kernel starts a timer when it
receives the RA and updates any addresses configured as a result of
receiving that RA+prefix, such that when the timer expires, the
autoconfigured address is deleted. That timer can be used as a base for
the expiry mechanism that I've noted above, no? This fixes problem #1
from your first mail.
For problem #2, shouldn't a new RS be sent whenever the interface
changes it's IFF_LOWER_UP bit? IFF_LOWER_UP indicates a carrier on/off
event and thus indicates possible disconnect/reconnect to a new network.
I don't specifically know how it works now, but if RS isn't triggered
from IFF_LOWER_UP, I'd imagine that either (a) something didn't get
updated when IFF_LOWER_UP became how carrier was indicated in 2.6.17
(commit b00055aacdb172c05067612278ba27265fcd05ce) or (b) there's a
reason IFF_LOWER_UP isn't used as the trigger for sending an RS and I'm
qualified to say why.
Dan
> When I move to a new network, I need to restart the
> autoconfiguration. This does not currently happen - neither for
> an alive system where the ethernet link goes down/up, nor for a
> system that gets suspended, moved and then resumed.
>
^ permalink raw reply
* Re: ipvs oops in 3.0-rc7
From: Simon Horman @ 2011-07-21 5:40 UTC (permalink / raw)
To: Randy Dunlap; +Cc: netdev, lvs-devel, Wensong Zhang, Julian Anastasov
In-Reply-To: <20110720205019.9dfa30c3.rdunlap@xenotime.net>
On Wed, Jul 20, 2011 at 08:50:19PM -0700, Randy Dunlap wrote:
> I'm seeing the following Oops in 3.0-rc7 on x86_64, just loading and unloading
> modules. Any chance this is already fixed? I can test current git, but I
> wanted to ask first.
>
> Looks like it is on the second module load of ip_vs (i.e.,
> modprobe ip_vs; rmmod ip_vs; modprobe ip_vs).
Hi Randy,
I don't believe that this problem has been resolved (or observed before).
^ permalink raw reply
* [PATCH] net: Kobj and queues_kset should be used when CONFIG_XPS is enabled
From: jhbird.choi @ 2011-07-21 6:33 UTC (permalink / raw)
To: netdev, linux-kernel; +Cc: David S. Miller, Choi, Jong-Hwan
From: Choi, Jong-Hwan <jhbird.choi@samsung.com>
Kobj and queues_kset are used with CONFIG_XPS=y.
Signed-off-by: Choi, Jong-Hwan <jhbird.choi@samsung.com>
---
include/linux/netdevice.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9e19477..8eb2f11 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -556,7 +556,7 @@ struct netdev_queue {
struct Qdisc *qdisc;
unsigned long state;
struct Qdisc *qdisc_sleeping;
-#ifdef CONFIG_RPS
+#if defined(CONFIG_RPS) || defined(CONFIG_XPS)
struct kobject kobj;
#endif
#if defined(CONFIG_XPS) && defined(CONFIG_NUMA)
@@ -1214,7 +1214,7 @@ struct net_device {
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
-#ifdef CONFIG_RPS
+#if defined(CONFIG_RPS) || defined(CONFIG_XPS)
struct kset *queues_kset;
struct netdev_rx_queue *_rx;
--
1.7.1
^ permalink raw reply related
* Re: [PATCH 1/2] igb: Allow extra 4 bytes on RX for vlan tags.
From: Alexander Duyck @ 2011-07-21 6:35 UTC (permalink / raw)
To: jeffrey.t.kirsher
Cc: Ben Greear, Jesse Gross, netdev@vger.kernel.org,
Duyck, Alexander H
In-Reply-To: <1311211304.2401.9.camel@jtkirshe-mobl>
On Wed, Jul 20, 2011 at 6:21 PM, Jeff Kirsher
<jeffrey.t.kirsher@intel.com> wrote:
> On Wed, 2011-07-20 at 17:27 -0700, Ben Greear wrote:
>> On 07/20/2011 05:18 PM, Jesse Gross wrote:
>> > On Thu, Feb 17, 2011 at 9:28 AM, Ben Greear<greearb@candelatech.com> wrote:
>> >> On 02/17/2011 03:04 AM, Jeff Kirsher wrote:
>> >>>
>> >>> On Thu, Feb 10, 2011 at 13:59,<greearb@candelatech.com> wrote:
>> >>>>
>> >>>> From: Ben Greear<greearb@candelatech.com>
>> >>>>
>> >>>> This allows the NIC to receive 1518 byte (not counting
>> >>>> FCS) packets when MTU is 1500, thus allowing 1500 MTU
>> >>>> VLAN frames to be received. Please note that no VLANs
>> >>>> were actually configured on the NIC...it was just acting
>> >>>> as pass-through device.
>> >>>>
>> >>>> Signed-off-by: Ben Greear<greearb@candelatech.com>
>> >>>> ---
>> >>>> :100644 100644 58c665b... 30c9cc6... M drivers/net/igb/igb_main.c
>> >>>> drivers/net/igb/igb_main.c | 5 +++--
>> >>>> 1 files changed, 3 insertions(+), 2 deletions(-)
>> >>>>
>> >>>> diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
>> >>>> index 58c665b..30c9cc6 100644
>> >>>> --- a/drivers/net/igb/igb_main.c
>> >>>> +++ b/drivers/net/igb/igb_main.c
>> >>>> @@ -2281,7 +2281,8 @@ static int __devinit igb_sw_init(struct igb_adapter
>> >>>> *adapter)
>> >>>> adapter->rx_itr_setting = IGB_DEFAULT_ITR;
>> >>>> adapter->tx_itr_setting = IGB_DEFAULT_ITR;
>> >>>>
>> >>>> - adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
>> >>>> + adapter->max_frame_size = (netdev->mtu + ETH_HLEN + ETH_FCS_LEN
>> >>>> + + VLAN_HLEN);
>> >>>> adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
>> >>>>
>> >>>> spin_lock_init(&adapter->stats64_lock);
>> >>>> @@ -4303,7 +4304,7 @@ static int igb_change_mtu(struct net_device
>> >>>> *netdev, int new_mtu)
>> >>>> {
>> >>>> struct igb_adapter *adapter = netdev_priv(netdev);
>> >>>> struct pci_dev *pdev = adapter->pdev;
>> >>>> - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
>> >>>> + int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
>> >>>> u32 rx_buffer_len, i;
>> >>>>
>> >>>> if ((new_mtu< 68) || (max_frame> MAX_JUMBO_FRAME_SIZE)) {
>> >>>
>> >>> While testing this patch, validation found that the patch reduces the
>> >>> maximum mtu size
>> >>> by 4 bytes (reduces it from 9216 to 9212). This is not a desired side
>> >>> effect of this patch.
>> >>
>> >> You could add handling for that case and have it act as it used to when
>> >> new_mtu is greater than 9212?
>> >>
>> >> I tested e1000e and it worked w/out hacking at 1500 MTU, so maybe
>> >> check how it does it?
>> >
>> > I just wanted to bring this up again to see if any progress had been
>> > made. We were looking at this driver and trying to figure out the
>> > best way to convert it to use the new vlan model but I'm not familiar
>>
>> I've been watching :)
>>
>> > enough with the hardware to know. It seems that all of the other
>> > Intel drivers unconditionally add space for the vlan tag to the
>> > receive buffer (and would therefore have similar effects as this
>> > patch), is there something different about this card?
>> >
>> > I believe that Alex was working on something in this area (in the
>> > context of one of my patches from a long time ago) but I'm not sure
>> > what came of that.
>>
>> Truth is, I don't really see why it's a problem to decrease the
>> maximum MTU slightly in order to make it work with VLANs.
>>
>> I'm not sure if there is some way to make it work with VLANs
>> and not decrease the maximum MTU.
>
> This was the reason this did not get accepted. I was looking into what
> could be done so that we did not decease the maximum MTU, but I got
> side-tracked and have not done anything on it in several months.
>
I can take a look at fixing this most likely tomorrow. I have some
work planned for igb anyway over the next few days.
Odds are it is just a matter of where the VLAN_HLEN is added. As I
recall for our drivers the correct spot is in the setting of
rx_buffer_len since that is the area more concerned with maximum
receive frame size versus the mtu section which is more concerned with
the transmit side of things.
Thanks,
Alex
^ permalink raw reply
* Re: [patch net-next-2.6 37/47] igb: do vlan cleanup
From: Jiri Pirko @ 2011-07-21 6:57 UTC (permalink / raw)
To: Jesse Gross
Cc: netdev, davem, shemminger, eric.dumazet, greearb, mirqus,
jeffrey.t.kirsher, jesse.brandeburg, peter.p.waskiewicz.jr,
bruce.w.allan, carolyn.wyborny, donald.c.skidmore, gregory.v.rose,
alexander.h.duyck, john.ronciak, e1000-devel
In-Reply-To: <CAEP_g=9j3=s74_VQ6RQxVRGOOs-mVR94s31ETXJ1S5P7aQV4iQ@mail.gmail.com>
Thu, Jul 21, 2011 at 01:58:10AM CEST, jesse@nicira.com wrote:
>On Wed, Jul 20, 2011 at 12:10 PM, Jiri Pirko <jpirko@redhat.com> wrote:
>> Wed, Jul 20, 2011 at 07:35:33PM CEST, jesse@nicira.com wrote:
>>>On Wed, Jul 20, 2011 at 7:54 AM, Jiri Pirko <jpirko@redhat.com> wrote:
>>>> @@ -2943,7 +2944,7 @@ static void igb_rlpml_set(struct igb_adapter *adapter)
>>>> struct e1000_hw *hw = &adapter->hw;
>>>> u16 pf_id = adapter->vfs_allocated_count;
>>>>
>>>> - if (adapter->vlgrp)
>>>> + if (igb_vlan_used(adapter))
>>>> max_frame_size += VLAN_TAG_SIZE;
>>>
>>>There are similar issues here as with the VF driver. I think you're
>>>also confusing vlan acceleration with vlan filtering. If no vlan
>>>filters are in use but the card is in promiscuous mode, the buffer
>>>will be undersized and we lose tagged packets.
>>
>> I'm certainly not confusing vlan accel and filtering. Here is the
>> intension is the behaviour remains intact as well. I believe it's true.
>
>I believe the underlying issue for all three of these threads is the
>same, so I'll just respond to them all here.
>
>I agree that this doesn't change the behavior of the driver but I
>don't think that should be the goal. When I originally designed this
>new vlan model my intention was to eliminate a whole class of driver
>bugs that I was repeatedly hitting in various forms. In the example
>above, if you run tcpdump on this device without configuring a vlan
>group on it then you will see that MTU sized packets are missing
>because the receive buffer was undersized.
>
>The common theme for these problems is that they all occur in
>situations where vlans are not configured on the device and the driver
>does something different as a result of this. The solution was to
>prevent drivers from changing their behavior in such situations by
>completely removing the concept of a vlan group from them and letting
>the networking core tell them when to make the changes instead of
>doing it implicitly. That's why I don't see the fact that this change
>essentially emulates the knowledge of configuring a group to be a
>plus. By the way, plenty of your other patches change the behavior of
>the drivers - on any of the NICs that always enable stripping, try
>running tcpdump on the interface without configuring a vlan group.
>Before the change you will see that tags have disappeared and
>afterwards the tags are intact. So I think that changing the behavior
>of drivers in this regard is a positive thing.
>
>As an aside, thank you for taking the time to work on all of these
>drivers. The only reason why I'm complaining about these few drivers
>is because I'd like to close the door on this class of problems, which
>is finally in reach thanks to your work.
Okay now it's clear to me. I tried to stay with the code as much similar
as unpatched. But I see your arguments. I will review and repost
patches which are enabling/disabling vlan accel on add_vid/kill_vid and
convert it to set_features.
Thanks. Jesse.
Jirka
^ permalink raw reply
* Re: [PATCH net-next-2.6] ipv6: make fragment identifications less predictable
From: Fernando Gont @ 2011-07-21 1:32 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, security, Eugene Teo, netdev, Matt Mackall
In-Reply-To: <1311157648.2338.22.camel@edumazet-HP-Compaq-6005-Pro-SFF-PC>
On 07/20/2011 07:27 AM, Eric Dumazet wrote:
> Le mercredi 20 juillet 2011 à 10:25 +0200, Eric Dumazet a écrit :
>
>> Please hold on, I'll make a different patch series to ease stable teams
>> job. It appears inetpeer & ipv6 are really not an option for old
>> kernels.
>>
>> Common patch for all kernels :
>> 1) Fix the problem without inetpeer help
>> ---
>> Patches for next kernels
>> 2) random split as suggested by Matt Mackal
>> 3) Use inetpeer cache to scale identification generation
>
> Here is the first patch, applicable on net-2.6 / linux-2.6 and stable
> kernels.
Does it make sense to go in this direction rather than simply randomize
the IPv6 Fragment Identification?
Keep in mind that IPv6 routers don't perform fragmentation, that that
the IPv6 identification is 32-bits long.
Thanks,
--
Fernando Gont
e-mail: fernando@gont.com.ar || fgont@acm.org
PGP Fingerprint: 7809 84F5 322E 45C7 F1C9 3945 96EE A9EF D076 FFF1
^ permalink raw reply
* Re: [PATCH V2] vhost: fix check for # of outstanding buffers
From: Michael S. Tsirkin @ 2011-07-21 8:06 UTC (permalink / raw)
To: Shirley Ma; +Cc: David Miller, netdev, jasowang
In-Reply-To: <1311182592.8573.45.camel@localhost.localdomain>
On Wed, Jul 20, 2011 at 10:23:12AM -0700, Shirley Ma wrote:
> Fix the check for number of outstanding buffers returns incorrect
> results due to vq->pend_idx wrap around;
>
> Signed-off-by: Shirley Ma <xma@us.ibm.com>
OK, the logic's right now, and it's not worse
than what we had, so I applied this after
fixing up the comment (it's upend_idx and English
sentences don't need to end with a semicolumn ;)
However, I would like to see the effect of the bug
noted in the log in the future.
And the reason I mention this here, is that
I think that the whole VHOST_MAX_PEND thing
does not work as advertised: this logic only
triggers when the ring is empty, so we will happily push
more than VHOST_MAX_PEND packets if the guest manages
to give them to us.
I'm not sure why we have the limit, either: the wmem
limit in the socket still applies and seems more
effective to prevent denial of service by a malicious guest.
> ---
>
> drivers/vhost/net.c | 12 +++++++++---
> 1 files changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 70ac604..946a71e 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -182,15 +182,21 @@ static void handle_tx(struct vhost_net *net)
> break;
> /* Nothing new? Wait for eventfd to tell us they refilled. */
> if (head == vq->num) {
> + int num_pends;
> +
> wmem = atomic_read(&sock->sk->sk_wmem_alloc);
> if (wmem >= sock->sk->sk_sndbuf * 3 / 4) {
> tx_poll_start(net, sock);
> set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
> break;
> }
> - /* If more outstanding DMAs, queue the work */
> - if (unlikely(vq->upend_idx - vq->done_idx >
> - VHOST_MAX_PEND)) {
> + /* If more outstanding DMAs, queue the work
> + * handle upend_idx wrap around
> + */
> + num_pends = (vq->upend_idx >= vq->done_idx) ?
> + (vq->upend_idx - vq->done_idx) :
> + (vq->upend_idx + UIO_MAXIOV - vq->done_idx);
> + if (unlikely(num_pends > VHOST_MAX_PEND)) {
> tx_poll_start(net, sock);
> set_bit(SOCK_ASYNC_NOSPACE, &sock->flags);
> break;
>
^ permalink raw reply
* (unknown),
From: Victor Chernika @ 2011-07-21 8:21 UTC (permalink / raw)
To: netdev
unsubscribe netdev
^ permalink raw reply
* Re: ipvs oops in 3.0-rc7
From: Huajun Li @ 2011-07-21 8:42 UTC (permalink / raw)
To: Simon Horman
Cc: Randy Dunlap, netdev, lvs-devel, Wensong Zhang, Julian Anastasov,
huajun li
In-Reply-To: <20110721054033.GA8299@verge.net.au>
Hi Randy and Simon,
I happened to meet the issue too, loading and unloading module of
ip_vs, then loading it again will cause Oops, the root cause may be
ip_vs_dst_notifier is not unregistered. Please try following patch, it
works for me.
Signed-off-by: Huajun Li <huajun.li.lee@gmail.com>
---
net/netfilter/ipvs/ip_vs_ctl.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 699c79a..a178cb3 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -3771,6 +3771,7 @@ err_sock:
void ip_vs_control_cleanup(void)
{
EnterFunction(2);
+ unregister_netdevice_notifier(&ip_vs_dst_notifier);
ip_vs_genl_unregister();
nf_unregister_sockopt(&ip_vs_sockopts);
LeaveFunction(2);
--
1.7.4.1
2011/7/21 Simon Horman <horms@verge.net.au>:
> On Wed, Jul 20, 2011 at 08:50:19PM -0700, Randy Dunlap wrote:
>> I'm seeing the following Oops in 3.0-rc7 on x86_64, just loading and unloading
>> modules. Any chance this is already fixed? I can test current git, but I
>> wanted to ask first.
>>
>> Looks like it is on the second module load of ip_vs (i.e.,
>> modprobe ip_vs; rmmod ip_vs; modprobe ip_vs).
>
> Hi Randy,
>
> I don't believe that this problem has been resolved (or observed before).
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply related
* Re: ipvs oops in 3.0-rc7
From: Julian Anastasov @ 2011-07-21 9:04 UTC (permalink / raw)
To: Randy Dunlap; +Cc: netdev, lvs-devel, Simon Horman, Wensong Zhang
In-Reply-To: <20110720205019.9dfa30c3.rdunlap@xenotime.net>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 7076 bytes --]
Hello,
On Wed, 20 Jul 2011, Randy Dunlap wrote:
> I'm seeing the following Oops in 3.0-rc7 on x86_64, just loading and unloading
> modules. Any chance this is already fixed? I can test current git, but I
> wanted to ask first.
>
> Looks like it is on the second module load of ip_vs (i.e.,
> modprobe ip_vs; rmmod ip_vs; modprobe ip_vs).
I think, this problem was fixed by this patch:
http://www.spinics.net/lists/lvs-devel/msg02051.html
But it seems it was lost somewhere ...
> Jul 20 17:15:05 chimera kernel: [ 3323.505527] IPVS: ipvs unloaded.
> Jul 20 17:15:06 chimera kernel: [ 3324.554297] BUG: unable to handle kernel paging request at ffffffffa1543820
> Jul 20 17:15:06 chimera kernel: [ 3324.554382] IP: [<ffffffff810a8d4f>] raw_notifier_chain_register+0x1f/0x4a
> Jul 20 17:15:06 chimera kernel: [ 3324.554445] PGD 1872067 PUD 1876063 PMD b653f067 PTE 0
> Jul 20 17:15:06 chimera kernel: [ 3324.554505] Oops: 0000 [#1] SMP
> Jul 20 17:15:06 chimera kernel: [ 3324.554551] CPU 1
> Jul 20 17:15:06 chimera kernel: [ 3324.554574] Modules linked in: ip_vs(+) nf_conntrack_sip nf_tproxy_core xt_RATEEST nf_conntrack_proto_gre nfnetlink_log nfnetlink nf_conntrack_broadcast l2tp_core can rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr atm kernelcapi fcrypt pcbc af_rxrpc xp gru macvtap tun isdnhdlc mISDNipac mISDN_core chipreg map_funcs macvlan ptp pps_core mdio_bitbang hdlcdrv ax25 mdio pppox gre inet_lro cycx_drv wanrouter hdlc lapb uio ppp_generic xenbus_probe_frontend configfs ecb rtl8192c_common ath9k_common ath9k_hw ath libertas atmel rt2x00pci rt2x00usb rt2x00lib rng_core orinoco wl12xx crc7 p54common arc4 hostap rndis_host eeprom_93cx6 libipw lib80211 mac80211 cfg80211 fddi crc32c libcrc32c dca com20020 arcnet psnap cdc_ether phonet usbnet sja1000 can_dev sir_dev i
rda crc_ccitt mtd zlib_deflate slhc virtio_ring virtio tr i2400m wimax mii usbserial leds_net5501 fuse af_packet ipt_MASQUERADE iptable_nat nf_nat nfsd lockd nfs_acl auth_rpcgss stp llc bne!
p bluetooth rfkill crc16 sunrpc ipt_REJEC
> Jul 20 17:15:06 chimera kernel: T nf_conntrack_ipv4 nf_defrag_ipv4 iptable_filter ip_tables ip6t_REJECT xt_tcpudp nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables x_tables ipv6 cpufreq_ondemand acpi_cpufreq freq_table mperf binfmt_misc dm_mirror dm_region_hash dm_log dm_multipath scsi_dh dm_mod kvm_intel kvm uinput mousedev sr_mod cdrom ppdev snd_hda_codec_idt snd_hda_intel snd_hda_codec snd_hwdep snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device ide_pci_generic snd_pcm_oss usbmouse ide_core snd_mixer_oss firewire_ohci usbhid snd_pcm firewire_core usb_storage hid usblp ata_generic i2c_i801 sg pcspkr snd_timer pata_acpi usb_libusual iTCO_wdt iTCO_vendor_support uas snd crc_itu_t soundcore pata_marvell snd_page_alloc parport_pc evdev proce
ssor parport mac_hid rtc_cmos unix sd_mod crc_t10dif ext3 jbd mbcache uhci_hcd ohci_hcd ssb mmc_core pcmcia pcmcia_core firmware_class ehci_hcd usbcore i915 drm_kms_helper intel_agp button !
intel_gtt video thermal_sys hwmon [last unlo
> Jul 20 17:15:06 chimera kernel: aded: ip_vs]
> Jul 20 17:15:06 chimera kernel: [ 3324.556037]
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] Pid: 20884, comm: modprobe Not tainted 3.0.0-rc7 #6 Gateway GT5636E/DG965OT
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] RIP: 0010:[<ffffffff810a8d4f>] [<ffffffff810a8d4f>] raw_notifier_chain_register+0x1f/0x4a
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] RSP: 0018:ffff8800b5169e88 EFLAGS: 00010202
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] RAX: ffffffffa1543810 RBX: ffffffffa18f3810 RCX: 0000000000000000
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] RDX: 0000000000000000 RSI: ffffffffa18f3810 RDI: ffffffffa125f9b8
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] RBP: ffff8800b5169e88 R08: ffffffff810aa3ee R09: 0000000000000000
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] R10: 0000000000000088 R11: ffffffff81b24258 R12: ffffffffa1908155
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] R13: 0000000000000000 R14: 000003060ede68d6 R15: 0000000000000000
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] FS: 00007f6e2d1856f0(0000) GS:ffff88011b400000(0000) knlGS:0000000000000000
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] CR2: ffffffffa1543820 CR3: 00000000b5241000 CR4: 00000000000006e0
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] Process modprobe (pid: 20884, threadinfo ffff8800b5168000, task ffff8800b818b000)
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] Stack:
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] ffff8800b5169ed8 ffffffff814932e7 ffff8800b5169ed8 ffffffff814c5248
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] ffff8800b5169eb8 0000000000000000 ffffffffa1908155 0000000000000000
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] 000003060ede68d6 0000000000000000 ffff8800b5169ef8 ffffffffa190843f
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] Call Trace:
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffff814932e7>] register_netdevice_notifier+0x3b/0x24b
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffff814c5248>] ? genl_register_family_with_ops+0x50/0x9e
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffffa1908155>] ? ip_vs_conn_init+0x155/0x155 [ip_vs]
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffffa190843f>] ip_vs_control_init+0xeb/0x132 [ip_vs]
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffffa1908155>] ? ip_vs_conn_init+0x155/0x155 [ip_vs]
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffffa1908176>] ip_vs_init+0x21/0x1ff [ip_vs]
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffffa1908155>] ? ip_vs_conn_init+0x155/0x155 [ip_vs]
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffff81002094>] do_one_initcall+0x6c/0x1c5
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffff810cd572>] sys_init_module+0xe1/0x2b0
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] [<ffffffff8157da02>] system_call_fastpath+0x16/0x1b
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] Code: 89 e5 e8 85 e3 04 00 c9 c3 90 90 90 55 48 89 e5 66 66 66 66 90 48 ff 05 f8 5b 00 01 48 8b 07 eb 1e 48 ff 05 fc 5b 00 01 8b 56 10 <3b> 50 10 7f 14 48 ff 05 e5 5b 00 01 48 8d 78 08 48 8b 40 08 48
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] RIP [<ffffffff810a8d4f>] raw_notifier_chain_register+0x1f/0x4a
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] RSP <ffff8800b5169e88>
> Jul 20 17:15:06 chimera kernel: [ 3324.556037] CR2: ffffffffa1543820
> Jul 20 17:15:06 chimera kernel: [ 3324.583800] ---[ end trace 1df4eeece34268d5 ]---
>
>
>
> ---
> ~Randy
> *** Remember to use Documentation/SubmitChecklist when testing your code ***
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply
* [PATCH 0/8] netfilter: netfilter update for net-next
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
Hi Dave,
following is a netfilter update for net-next, containing:
- changes to the AUDIT target to log the security context, from Mr Dash Four
- RCUification of nfnetlink and nfnetlink_queue from Eric, raising performance
fourfold in his tests
- a fix for nfnetlink_queue to make sure packet IDs are monotonic increasing,
from Eric
- nfnetlink_queue batch verdict support from Florian, increasing performance
even further
- ipset updates from Jozsef
Please apply or pull from:
git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6.git master
Thanks!
^ permalink raw reply
* [PATCH 4/8] netfilter: nfnetlink_queue: assert monotonic packet ids
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
In-Reply-To: <1311243476-18236-1-git-send-email-kaber@trash.net>
From: Eric Dumazet <eric.dumazet@gmail.com>
Packet identifier is currently setup in nfqnl_build_packet_message(),
using one atomic_inc_return().
Problem is that since several cpus might concurrently call
nfqnl_enqueue_packet() for the same queue, we can deliver packets to
consumer in non monotonic way (packet N+1 being delivered after packet
N)
This patch moves the packet id setup from nfqnl_build_packet_message()
to nfqnl_enqueue_packet() to guarantee correct delivery order.
This also removes one atomic operation.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Florian Westphal <fw@strlen.de>
CC: Pablo Neira Ayuso <pablo@netfilter.org>
CC: Eric Leblond <eric@regit.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/netfilter/nfnetlink_queue.c | 26 +++++++++++++++-----------
1 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index c645b87..3b2af8c 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -58,7 +58,7 @@ struct nfqnl_instance {
*/
spinlock_t lock;
unsigned int queue_total;
- atomic_t id_sequence; /* 'sequence' of pkt ids */
+ unsigned int id_sequence; /* 'sequence' of pkt ids */
struct list_head queue_list; /* packets in queue */
};
@@ -213,13 +213,15 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data)
static struct sk_buff *
nfqnl_build_packet_message(struct nfqnl_instance *queue,
- struct nf_queue_entry *entry)
+ struct nf_queue_entry *entry,
+ __be32 **packet_id_ptr)
{
sk_buff_data_t old_tail;
size_t size;
size_t data_len = 0;
struct sk_buff *skb;
- struct nfqnl_msg_packet_hdr pmsg;
+ struct nlattr *nla;
+ struct nfqnl_msg_packet_hdr *pmsg;
struct nlmsghdr *nlh;
struct nfgenmsg *nfmsg;
struct sk_buff *entskb = entry->skb;
@@ -272,12 +274,11 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
nfmsg->version = NFNETLINK_V0;
nfmsg->res_id = htons(queue->queue_num);
- entry->id = atomic_inc_return(&queue->id_sequence);
- pmsg.packet_id = htonl(entry->id);
- pmsg.hw_protocol = entskb->protocol;
- pmsg.hook = entry->hook;
-
- NLA_PUT(skb, NFQA_PACKET_HDR, sizeof(pmsg), &pmsg);
+ nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg));
+ pmsg = nla_data(nla);
+ pmsg->hw_protocol = entskb->protocol;
+ pmsg->hook = entry->hook;
+ *packet_id_ptr = &pmsg->packet_id;
indev = entry->indev;
if (indev) {
@@ -388,6 +389,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
struct sk_buff *nskb;
struct nfqnl_instance *queue;
int err = -ENOBUFS;
+ __be32 *packet_id_ptr;
/* rcu_read_lock()ed by nf_hook_slow() */
queue = instance_lookup(queuenum);
@@ -401,7 +403,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
goto err_out;
}
- nskb = nfqnl_build_packet_message(queue, entry);
+ nskb = nfqnl_build_packet_message(queue, entry, &packet_id_ptr);
if (nskb == NULL) {
err = -ENOMEM;
goto err_out;
@@ -420,6 +422,8 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
queue->queue_total);
goto err_out_free_nskb;
}
+ entry->id = ++queue->id_sequence;
+ *packet_id_ptr = htonl(entry->id);
/* nfnetlink_unicast will either free the nskb or add it to a socket */
err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT);
@@ -852,7 +856,7 @@ static int seq_show(struct seq_file *s, void *v)
inst->peer_pid, inst->queue_total,
inst->copy_mode, inst->copy_range,
inst->queue_dropped, inst->queue_user_dropped,
- atomic_read(&inst->id_sequence), 1);
+ inst->id_sequence, 1);
}
static const struct seq_operations nfqnl_seq_ops = {
--
1.7.2.3
^ permalink raw reply related
* [PATCH 8/8] netfilter: ipset: fix compiler warnings "'hash_ip4_data_next' declared inline after being called"
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
In-Reply-To: <1311243476-18236-1-git-send-email-kaber@trash.net>
From: Chris Friesen <chris.friesen@genband.com>
Some gcc versions warn about prototypes without "inline" when the declaration
includes the "inline" keyword. The fix generates a false error message
"marked inline, but without a definition" with sparse below 0.4.2.
Signed-off-by: Chris Friesen <chris.friesen@genband.com>
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/linux/netfilter/ipset/ip_set_ahash.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index 1e7f759..b89fb79 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -392,7 +392,7 @@ retry:
return 0;
}
-static void
+static inline void
type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d);
/* Add an element to a hash and update the internal counters when succeeded,
--
1.7.2.3
^ permalink raw reply related
* [PATCH 2/8] netfilter: nfnetlink: add RCU in nfnetlink_rcv_msg()
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
In-Reply-To: <1311243476-18236-1-git-send-email-kaber@trash.net>
From: Eric Dumazet <eric.dumazet@gmail.com>
Goal of this patch is to permit nfnetlink providers not mandate
nfnl_mutex being held while nfnetlink_rcv_msg() calls them.
If struct nfnl_callback contains a non NULL call_rcu(), then
nfnetlink_rcv_msg() will use it instead of call() field, holding
rcu_read_lock instead of nfnl_mutex
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Florian Westphal <fw@strlen.de>
CC: Eric Leblond <eric@regit.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/linux/netfilter/nfnetlink.h | 3 ++
net/netfilter/nfnetlink.c | 40 ++++++++++++++++++++++++++--------
2 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 2b11fc1..74d3386 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -60,6 +60,9 @@ struct nfnl_callback {
int (*call)(struct sock *nl, struct sk_buff *skb,
const struct nlmsghdr *nlh,
const struct nlattr * const cda[]);
+ int (*call_rcu)(struct sock *nl, struct sk_buff *skb,
+ const struct nlmsghdr *nlh,
+ const struct nlattr * const cda[]);
const struct nla_policy *policy; /* netlink attribute policy */
const u_int16_t attr_count; /* number of nlattr's */
};
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index b4a4532..1905976 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -37,7 +37,7 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
static char __initdata nfversion[] = "0.30";
-static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
+static const struct nfnetlink_subsystem __rcu *subsys_table[NFNL_SUBSYS_COUNT];
static DEFINE_MUTEX(nfnl_mutex);
void nfnl_lock(void)
@@ -59,7 +59,7 @@ int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
nfnl_unlock();
return -EBUSY;
}
- subsys_table[n->subsys_id] = n;
+ rcu_assign_pointer(subsys_table[n->subsys_id], n);
nfnl_unlock();
return 0;
@@ -71,7 +71,7 @@ int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n)
nfnl_lock();
subsys_table[n->subsys_id] = NULL;
nfnl_unlock();
-
+ synchronize_rcu();
return 0;
}
EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
@@ -83,7 +83,7 @@ static inline const struct nfnetlink_subsystem *nfnetlink_get_subsys(u_int16_t t
if (subsys_id >= NFNL_SUBSYS_COUNT)
return NULL;
- return subsys_table[subsys_id];
+ return rcu_dereference(subsys_table[subsys_id]);
}
static inline const struct nfnl_callback *
@@ -139,21 +139,27 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
type = nlh->nlmsg_type;
replay:
+ rcu_read_lock();
ss = nfnetlink_get_subsys(type);
if (!ss) {
#ifdef CONFIG_MODULES
- nfnl_unlock();
+ rcu_read_unlock();
request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
- nfnl_lock();
+ rcu_read_lock();
ss = nfnetlink_get_subsys(type);
if (!ss)
#endif
+ {
+ rcu_read_unlock();
return -EINVAL;
+ }
}
nc = nfnetlink_find_client(type, ss);
- if (!nc)
+ if (!nc) {
+ rcu_read_unlock();
return -EINVAL;
+ }
{
int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
@@ -167,7 +173,23 @@ replay:
if (err < 0)
return err;
- err = nc->call(net->nfnl, skb, nlh, (const struct nlattr **)cda);
+ if (nc->call_rcu) {
+ err = nc->call_rcu(net->nfnl, skb, nlh,
+ (const struct nlattr **)cda);
+ rcu_read_unlock();
+ } else {
+ rcu_read_unlock();
+ nfnl_lock();
+ if (rcu_dereference_protected(
+ subsys_table[NFNL_SUBSYS_ID(type)],
+ lockdep_is_held(&nfnl_mutex)) != ss ||
+ nfnetlink_find_client(type, ss) != nc)
+ err = -EAGAIN;
+ else
+ err = nc->call(net->nfnl, skb, nlh,
+ (const struct nlattr **)cda);
+ nfnl_unlock();
+ }
if (err == -EAGAIN)
goto replay;
return err;
@@ -176,9 +198,7 @@ replay:
static void nfnetlink_rcv(struct sk_buff *skb)
{
- nfnl_lock();
netlink_rcv_skb(skb, &nfnetlink_rcv_msg);
- nfnl_unlock();
}
static int __net_init nfnetlink_net_init(struct net *net)
--
1.7.2.3
^ permalink raw reply related
* [PATCH 1/8] netfilter: add SELinux context support to AUDIT target
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
In-Reply-To: <1311243476-18236-1-git-send-email-kaber@trash.net>
From: Mr Dash Four <mr.dash.four@googlemail.com>
In this revision the conversion of secid to SELinux context and adding it
to the audit log is moved from xt_AUDIT.c to audit.c with the aid of a
separate helper function - audit_log_secctx - which does both the conversion
and logging of SELinux context, thus also preventing internal secid number
being leaked to userspace. If conversion is not successful an error is raised.
With the introduction of this helper function the work done in xt_AUDIT.c is
much more simplified. It also opens the possibility of this helper function
being used by other modules (including auditd itself), if desired. With this
addition, typical (raw auditd) output after applying the patch would be:
type=NETFILTER_PKT msg=audit(1305852240.082:31012): action=0 hook=1 len=52 inif=? outif=eth0 saddr=10.1.1.7 daddr=10.1.2.1 ipid=16312 proto=6 sport=56150 dport=22 obj=system_u:object_r:ssh_client_packet_t:s0
type=NETFILTER_PKT msg=audit(1306772064.079:56): action=0 hook=3 len=48 inif=eth0 outif=? smac=00:05:5d:7c:27:0b dmac=00:02:b3:0a:7f:81 macproto=0x0800 saddr=10.1.2.1 daddr=10.1.1.7 ipid=462 proto=6 sport=22 dport=3561 obj=system_u:object_r:ssh_server_packet_t:s0
Acked-by: Eric Paris <eparis@redhat.com>
Signed-off-by: Mr Dash Four <mr.dash.four@googlemail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/linux/audit.h | 7 +++++++
kernel/audit.c | 29 +++++++++++++++++++++++++++++
net/netfilter/xt_AUDIT.c | 5 +++++
3 files changed, 41 insertions(+), 0 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9d339eb..0c80061 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -613,6 +613,12 @@ extern void audit_log_d_path(struct audit_buffer *ab,
extern void audit_log_key(struct audit_buffer *ab,
char *key);
extern void audit_log_lost(const char *message);
+#ifdef CONFIG_SECURITY
+extern void audit_log_secctx(struct audit_buffer *ab, u32 secid);
+#else
+#define audit_log_secctx(b,s) do { ; } while (0)
+#endif
+
extern int audit_update_lsm_rules(void);
/* Private API (for audit.c only) */
@@ -635,6 +641,7 @@ extern int audit_enabled;
#define audit_log_untrustedstring(a,s) do { ; } while (0)
#define audit_log_d_path(b, p, d) do { ; } while (0)
#define audit_log_key(b, k) do { ; } while (0)
+#define audit_log_secctx(b,s) do { ; } while (0)
#define audit_enabled 0
#endif
#endif
diff --git a/kernel/audit.c b/kernel/audit.c
index 9395003..52501b5 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -55,6 +55,9 @@
#include <net/sock.h>
#include <net/netlink.h>
#include <linux/skbuff.h>
+#ifdef CONFIG_SECURITY
+#include <linux/security.h>
+#endif
#include <linux/netlink.h>
#include <linux/freezer.h>
#include <linux/tty.h>
@@ -1502,6 +1505,32 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
}
}
+#ifdef CONFIG_SECURITY
+/**
+ * audit_log_secctx - Converts and logs SELinux context
+ * @ab: audit_buffer
+ * @secid: security number
+ *
+ * This is a helper function that calls security_secid_to_secctx to convert
+ * secid to secctx and then adds the (converted) SELinux context to the audit
+ * log by calling audit_log_format, thus also preventing leak of internal secid
+ * to userspace. If secid cannot be converted audit_panic is called.
+ */
+void audit_log_secctx(struct audit_buffer *ab, u32 secid)
+{
+ u32 len;
+ char *secctx;
+
+ if (security_secid_to_secctx(secid, &secctx, &len)) {
+ audit_panic("Cannot convert secid to context");
+ } else {
+ audit_log_format(ab, " obj=%s", secctx);
+ security_release_secctx(secctx, len);
+ }
+}
+EXPORT_SYMBOL(audit_log_secctx);
+#endif
+
EXPORT_SYMBOL(audit_log_start);
EXPORT_SYMBOL(audit_log_end);
EXPORT_SYMBOL(audit_log_format);
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c
index 363a99e..4bca15a 100644
--- a/net/netfilter/xt_AUDIT.c
+++ b/net/netfilter/xt_AUDIT.c
@@ -163,6 +163,11 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
break;
}
+#ifdef CONFIG_NETWORK_SECMARK
+ if (skb->secmark)
+ audit_log_secctx(ab, skb->secmark);
+#endif
+
audit_log_end(ab);
errout:
--
1.7.2.3
^ permalink raw reply related
* [PATCH 3/8] netfilter: nfnetlink_queue: provide rcu enabled callbacks
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
In-Reply-To: <1311243476-18236-1-git-send-email-kaber@trash.net>
From: Eric Dumazet <eric.dumazet@gmail.com>
nenetlink_queue operations on SMP are not efficent if several queues are
used, because of nfnl_mutex contention when applications give packet
verdict.
Use new call_rcu field in struct nfnl_callback to advertize a callback
that is called under rcu_read_lock instead of nfnl_mutex.
On my 2x4x2 machine, I was able to reach 2.000.000 pps going through
user land returning NF_ACCEPT verdicts without losses, instead of less
than 500.000 pps before patch.
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
CC: Florian Westphal <fw@strlen.de>
CC: Eric Leblond <eric@regit.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
net/netfilter/nfnetlink_queue.c | 41 +++++++++++---------------------------
1 files changed, 12 insertions(+), 29 deletions(-)
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index b83123f..c645b87 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -619,39 +619,26 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
struct nfqnl_instance *queue;
unsigned int verdict;
struct nf_queue_entry *entry;
- int err;
- rcu_read_lock();
queue = instance_lookup(queue_num);
- if (!queue) {
- err = -ENODEV;
- goto err_out_unlock;
- }
+ if (!queue)
+ return -ENODEV;
- if (queue->peer_pid != NETLINK_CB(skb).pid) {
- err = -EPERM;
- goto err_out_unlock;
- }
+ if (queue->peer_pid != NETLINK_CB(skb).pid)
+ return -EPERM;
- if (!nfqa[NFQA_VERDICT_HDR]) {
- err = -EINVAL;
- goto err_out_unlock;
- }
+ if (!nfqa[NFQA_VERDICT_HDR])
+ return -EINVAL;
vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
verdict = ntohl(vhdr->verdict);
- if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT) {
- err = -EINVAL;
- goto err_out_unlock;
- }
+ if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT)
+ return -EINVAL;
entry = find_dequeue_entry(queue, ntohl(vhdr->id));
- if (entry == NULL) {
- err = -ENOENT;
- goto err_out_unlock;
- }
- rcu_read_unlock();
+ if (entry == NULL)
+ return -ENOENT;
if (nfqa[NFQA_PAYLOAD]) {
if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
@@ -664,10 +651,6 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
nf_reinject(entry, verdict);
return 0;
-
-err_out_unlock:
- rcu_read_unlock();
- return err;
}
static int
@@ -780,9 +763,9 @@ err_out_unlock:
}
static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
- [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp,
+ [NFQNL_MSG_PACKET] = { .call_rcu = nfqnl_recv_unsupp,
.attr_count = NFQA_MAX, },
- [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict,
+ [NFQNL_MSG_VERDICT] = { .call_rcu = nfqnl_recv_verdict,
.attr_count = NFQA_MAX,
.policy = nfqa_verdict_policy },
[NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config,
--
1.7.2.3
^ permalink raw reply related
* [PATCH 7/8] netfilter: ipset: hash:net,iface fixed to handle overlapping nets behind different interfaces
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
In-Reply-To: <1311243476-18236-1-git-send-email-kaber@trash.net>
From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
If overlapping networks with different interfaces was added to
the set, the type did not handle it properly. Example
ipset create test hash:net,iface
ipset add test 192.168.0.0/16,eth0
ipset add test 192.168.0.0/24,eth1
Now, if a packet was sent from 192.168.0.0/24,eth0, the type returned
a match.
In the patch the algorithm is fixed in order to correctly handle
overlapping networks.
Limitation: the same network cannot be stored with more than 64 different
interfaces in a single set.
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/linux/netfilter/ipset/ip_set_ahash.h | 92 +++++++++++++++++---------
net/netfilter/ipset/ip_set_hash_ip.c | 6 +-
net/netfilter/ipset/ip_set_hash_ipport.c | 6 +-
net/netfilter/ipset/ip_set_hash_ipportip.c | 6 +-
net/netfilter/ipset/ip_set_hash_ipportnet.c | 6 +-
net/netfilter/ipset/ip_set_hash_net.c | 6 +-
net/netfilter/ipset/ip_set_hash_netiface.c | 40 +++++++++--
net/netfilter/ipset/ip_set_hash_netport.c | 6 +-
8 files changed, 117 insertions(+), 51 deletions(-)
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index 42b7d25..1e7f759 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -28,7 +28,32 @@
/* Number of elements to store in an initial array block */
#define AHASH_INIT_SIZE 4
/* Max number of elements to store in an array block */
-#define AHASH_MAX_SIZE (3*4)
+#define AHASH_MAX_SIZE (3*AHASH_INIT_SIZE)
+
+/* Max number of elements can be tuned */
+#ifdef IP_SET_HASH_WITH_MULTI
+#define AHASH_MAX(h) ((h)->ahash_max)
+
+static inline u8
+tune_ahash_max(u8 curr, u32 multi)
+{
+ u32 n;
+
+ if (multi < curr)
+ return curr;
+
+ n = curr + AHASH_INIT_SIZE;
+ /* Currently, at listing one hash bucket must fit into a message.
+ * Therefore we have a hard limit here.
+ */
+ return n > curr && n <= 64 ? n : curr;
+}
+#define TUNE_AHASH_MAX(h, multi) \
+ ((h)->ahash_max = tune_ahash_max((h)->ahash_max, multi))
+#else
+#define AHASH_MAX(h) AHASH_MAX_SIZE
+#define TUNE_AHASH_MAX(h, multi)
+#endif
/* A hash bucket */
struct hbucket {
@@ -60,6 +85,9 @@ struct ip_set_hash {
u32 timeout; /* timeout value, if enabled */
struct timer_list gc; /* garbage collection when timeout enabled */
struct type_pf_next next; /* temporary storage for uadd */
+#ifdef IP_SET_HASH_WITH_MULTI
+ u8 ahash_max; /* max elements in an array block */
+#endif
#ifdef IP_SET_HASH_WITH_NETMASK
u8 netmask; /* netmask value for subnets to store */
#endif
@@ -279,12 +307,13 @@ ip_set_hash_destroy(struct ip_set *set)
/* Add an element to the hash table when resizing the set:
* we spare the maintenance of the internal counters. */
static int
-type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value)
+type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value,
+ u8 ahash_max)
{
if (n->pos >= n->size) {
void *tmp;
- if (n->size >= AHASH_MAX_SIZE)
+ if (n->size >= ahash_max)
/* Trigger rehashing */
return -EAGAIN;
@@ -339,7 +368,7 @@ retry:
for (j = 0; j < n->pos; j++) {
data = ahash_data(n, j);
m = hbucket(t, HKEY(data, h->initval, htable_bits));
- ret = type_pf_elem_add(m, data);
+ ret = type_pf_elem_add(m, data, AHASH_MAX(h));
if (ret < 0) {
read_unlock_bh(&set->lock);
ahash_destroy(t);
@@ -376,7 +405,7 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
const struct type_pf_elem *d = value;
struct hbucket *n;
int i, ret = 0;
- u32 key;
+ u32 key, multi = 0;
if (h->elements >= h->maxelem)
return -IPSET_ERR_HASH_FULL;
@@ -386,12 +415,12 @@ type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
key = HKEY(value, h->initval, t->htable_bits);
n = hbucket(t, key);
for (i = 0; i < n->pos; i++)
- if (type_pf_data_equal(ahash_data(n, i), d)) {
+ if (type_pf_data_equal(ahash_data(n, i), d, &multi)) {
ret = -IPSET_ERR_EXIST;
goto out;
}
-
- ret = type_pf_elem_add(n, value);
+ TUNE_AHASH_MAX(h, multi);
+ ret = type_pf_elem_add(n, value, AHASH_MAX(h));
if (ret != 0) {
if (ret == -EAGAIN)
type_pf_data_next(h, d);
@@ -419,13 +448,13 @@ type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
struct hbucket *n;
int i;
struct type_pf_elem *data;
- u32 key;
+ u32 key, multi = 0;
key = HKEY(value, h->initval, t->htable_bits);
n = hbucket(t, key);
for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i);
- if (!type_pf_data_equal(data, d))
+ if (!type_pf_data_equal(data, d, &multi))
continue;
if (i != n->pos - 1)
/* Not last one */
@@ -466,17 +495,17 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
struct hbucket *n;
const struct type_pf_elem *data;
int i, j = 0;
- u32 key;
+ u32 key, multi = 0;
u8 host_mask = SET_HOST_MASK(set->family);
pr_debug("test by nets\n");
- for (; j < host_mask && h->nets[j].cidr; j++) {
+ for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
type_pf_data_netmask(d, h->nets[j].cidr);
key = HKEY(d, h->initval, t->htable_bits);
n = hbucket(t, key);
for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i);
- if (type_pf_data_equal(data, d))
+ if (type_pf_data_equal(data, d, &multi))
return 1;
}
}
@@ -494,7 +523,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
struct hbucket *n;
const struct type_pf_elem *data;
int i;
- u32 key;
+ u32 key, multi = 0;
#ifdef IP_SET_HASH_WITH_NETS
/* If we test an IP address and not a network address,
@@ -507,7 +536,7 @@ type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
n = hbucket(t, key);
for (i = 0; i < n->pos; i++) {
data = ahash_data(n, i);
- if (type_pf_data_equal(data, d))
+ if (type_pf_data_equal(data, d, &multi))
return 1;
}
return 0;
@@ -664,14 +693,14 @@ type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
static int
type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,
- u32 timeout)
+ u8 ahash_max, u32 timeout)
{
struct type_pf_elem *data;
if (n->pos >= n->size) {
void *tmp;
- if (n->size >= AHASH_MAX_SIZE)
+ if (n->size >= ahash_max)
/* Trigger rehashing */
return -EAGAIN;
@@ -776,7 +805,7 @@ retry:
for (j = 0; j < n->pos; j++) {
data = ahash_tdata(n, j);
m = hbucket(t, HKEY(data, h->initval, htable_bits));
- ret = type_pf_elem_tadd(m, data,
+ ret = type_pf_elem_tadd(m, data, AHASH_MAX(h),
type_pf_data_timeout(data));
if (ret < 0) {
read_unlock_bh(&set->lock);
@@ -807,9 +836,9 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
const struct type_pf_elem *d = value;
struct hbucket *n;
struct type_pf_elem *data;
- int ret = 0, i, j = AHASH_MAX_SIZE + 1;
+ int ret = 0, i, j = AHASH_MAX(h) + 1;
bool flag_exist = flags & IPSET_FLAG_EXIST;
- u32 key;
+ u32 key, multi = 0;
if (h->elements >= h->maxelem)
/* FIXME: when set is full, we slow down here */
@@ -823,18 +852,18 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
n = hbucket(t, key);
for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i);
- if (type_pf_data_equal(data, d)) {
+ if (type_pf_data_equal(data, d, &multi)) {
if (type_pf_data_expired(data) || flag_exist)
j = i;
else {
ret = -IPSET_ERR_EXIST;
goto out;
}
- } else if (j == AHASH_MAX_SIZE + 1 &&
+ } else if (j == AHASH_MAX(h) + 1 &&
type_pf_data_expired(data))
j = i;
}
- if (j != AHASH_MAX_SIZE + 1) {
+ if (j != AHASH_MAX(h) + 1) {
data = ahash_tdata(n, j);
#ifdef IP_SET_HASH_WITH_NETS
del_cidr(h, data->cidr, HOST_MASK);
@@ -844,7 +873,8 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags)
type_pf_data_timeout_set(data, timeout);
goto out;
}
- ret = type_pf_elem_tadd(n, d, timeout);
+ TUNE_AHASH_MAX(h, multi);
+ ret = type_pf_elem_tadd(n, d, AHASH_MAX(h), timeout);
if (ret != 0) {
if (ret == -EAGAIN)
type_pf_data_next(h, d);
@@ -869,13 +899,13 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags)
struct hbucket *n;
int i;
struct type_pf_elem *data;
- u32 key;
+ u32 key, multi = 0;
key = HKEY(value, h->initval, t->htable_bits);
n = hbucket(t, key);
for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i);
- if (!type_pf_data_equal(data, d))
+ if (!type_pf_data_equal(data, d, &multi))
continue;
if (type_pf_data_expired(data))
return -IPSET_ERR_EXIST;
@@ -915,16 +945,16 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
struct type_pf_elem *data;
struct hbucket *n;
int i, j = 0;
- u32 key;
+ u32 key, multi = 0;
u8 host_mask = SET_HOST_MASK(set->family);
- for (; j < host_mask && h->nets[j].cidr; j++) {
+ for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
type_pf_data_netmask(d, h->nets[j].cidr);
key = HKEY(d, h->initval, t->htable_bits);
n = hbucket(t, key);
for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i);
- if (type_pf_data_equal(data, d))
+ if (type_pf_data_equal(data, d, &multi))
return !type_pf_data_expired(data);
}
}
@@ -940,7 +970,7 @@ type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
struct type_pf_elem *data, *d = value;
struct hbucket *n;
int i;
- u32 key;
+ u32 key, multi = 0;
#ifdef IP_SET_HASH_WITH_NETS
if (d->cidr == SET_HOST_MASK(set->family))
@@ -950,7 +980,7 @@ type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
n = hbucket(t, key);
for (i = 0; i < n->pos; i++) {
data = ahash_tdata(n, i);
- if (type_pf_data_equal(data, d))
+ if (type_pf_data_equal(data, d, &multi))
return !type_pf_data_expired(data);
}
return 0;
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index fa80bb9..f2d576e 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -53,7 +53,8 @@ struct hash_ip4_telem {
static inline bool
hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
- const struct hash_ip4_elem *ip2)
+ const struct hash_ip4_elem *ip2,
+ u32 *multi)
{
return ip1->ip == ip2->ip;
}
@@ -225,7 +226,8 @@ struct hash_ip6_telem {
static inline bool
hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
- const struct hash_ip6_elem *ip2)
+ const struct hash_ip6_elem *ip2,
+ u32 *multi)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
}
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index bbf51b6..6ee10f5 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -60,7 +60,8 @@ struct hash_ipport4_telem {
static inline bool
hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
- const struct hash_ipport4_elem *ip2)
+ const struct hash_ipport4_elem *ip2,
+ u32 *multi)
{
return ip1->ip == ip2->ip &&
ip1->port == ip2->port &&
@@ -276,7 +277,8 @@ struct hash_ipport6_telem {
static inline bool
hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
- const struct hash_ipport6_elem *ip2)
+ const struct hash_ipport6_elem *ip2,
+ u32 *multi)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->port == ip2->port &&
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 96525f5..fb90e34 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -62,7 +62,8 @@ struct hash_ipportip4_telem {
static inline bool
hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
- const struct hash_ipportip4_elem *ip2)
+ const struct hash_ipportip4_elem *ip2,
+ u32 *multi)
{
return ip1->ip == ip2->ip &&
ip1->ip2 == ip2->ip2 &&
@@ -286,7 +287,8 @@ struct hash_ipportip6_telem {
static inline bool
hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
- const struct hash_ipportip6_elem *ip2)
+ const struct hash_ipportip6_elem *ip2,
+ u32 *multi)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index d2d6ab8..deb3e3d 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -62,7 +62,8 @@ struct hash_ipportnet4_telem {
static inline bool
hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
- const struct hash_ipportnet4_elem *ip2)
+ const struct hash_ipportnet4_elem *ip2,
+ u32 *multi)
{
return ip1->ip == ip2->ip &&
ip1->ip2 == ip2->ip2 &&
@@ -335,7 +336,8 @@ struct hash_ipportnet6_telem {
static inline bool
hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
- const struct hash_ipportnet6_elem *ip2)
+ const struct hash_ipportnet6_elem *ip2,
+ u32 *multi)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 2d4b1f4..60d0165 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -58,7 +58,8 @@ struct hash_net4_telem {
static inline bool
hash_net4_data_equal(const struct hash_net4_elem *ip1,
- const struct hash_net4_elem *ip2)
+ const struct hash_net4_elem *ip2,
+ u32 *multi)
{
return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
}
@@ -249,7 +250,8 @@ struct hash_net6_telem {
static inline bool
hash_net6_data_equal(const struct hash_net6_elem *ip1,
- const struct hash_net6_elem *ip2)
+ const struct hash_net6_elem *ip2,
+ u32 *multi)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->cidr == ip2->cidr;
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index 3d6c53b..e13095d 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -99,7 +99,7 @@ iface_test(struct rb_root *root, const char **iface)
while (n) {
const char *d = iface_data(n);
- int res = ifname_compare(*iface, d);
+ long res = ifname_compare(*iface, d);
if (res < 0)
n = n->rb_left;
@@ -121,7 +121,7 @@ iface_add(struct rb_root *root, const char **iface)
while (*n) {
char *ifname = iface_data(*n);
- int res = ifname_compare(*iface, ifname);
+ long res = ifname_compare(*iface, ifname);
p = *n;
if (res < 0)
@@ -159,31 +159,42 @@ hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
/* The type variant functions: IPv4 */
+struct hash_netiface4_elem_hashed {
+ __be32 ip;
+ u8 physdev;
+ u8 cidr;
+ u16 padding;
+};
+
+#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
+
/* Member elements without timeout */
struct hash_netiface4_elem {
__be32 ip;
- const char *iface;
u8 physdev;
u8 cidr;
u16 padding;
+ const char *iface;
};
/* Member elements with timeout support */
struct hash_netiface4_telem {
__be32 ip;
- const char *iface;
u8 physdev;
u8 cidr;
u16 padding;
+ const char *iface;
unsigned long timeout;
};
static inline bool
hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
- const struct hash_netiface4_elem *ip2)
+ const struct hash_netiface4_elem *ip2,
+ u32 *multi)
{
return ip1->ip == ip2->ip &&
ip1->cidr == ip2->cidr &&
+ (++*multi) &&
ip1->physdev == ip2->physdev &&
ip1->iface == ip2->iface;
}
@@ -257,6 +268,7 @@ nla_put_failure:
#define IP_SET_HASH_WITH_NETS
#define IP_SET_HASH_WITH_RBTREE
+#define IP_SET_HASH_WITH_MULTI
#define PF 4
#define HOST_MASK 32
@@ -424,29 +436,40 @@ hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
/* The type variant functions: IPv6 */
+struct hash_netiface6_elem_hashed {
+ union nf_inet_addr ip;
+ u8 physdev;
+ u8 cidr;
+ u16 padding;
+};
+
+#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
+
struct hash_netiface6_elem {
union nf_inet_addr ip;
- const char *iface;
u8 physdev;
u8 cidr;
u16 padding;
+ const char *iface;
};
struct hash_netiface6_telem {
union nf_inet_addr ip;
- const char *iface;
u8 physdev;
u8 cidr;
u16 padding;
+ const char *iface;
unsigned long timeout;
};
static inline bool
hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
- const struct hash_netiface6_elem *ip2)
+ const struct hash_netiface6_elem *ip2,
+ u32 *multi)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->cidr == ip2->cidr &&
+ (++*multi) &&
ip1->physdev == ip2->physdev &&
ip1->iface == ip2->iface;
}
@@ -681,6 +704,7 @@ hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
h->maxelem = maxelem;
get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT;
+ h->ahash_max = AHASH_MAX_SIZE;
hbits = htable_bits(hashsize);
h->table = ip_set_alloc(
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index fe203d1..8f9de72 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -59,7 +59,8 @@ struct hash_netport4_telem {
static inline bool
hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
- const struct hash_netport4_elem *ip2)
+ const struct hash_netport4_elem *ip2,
+ u32 *multi)
{
return ip1->ip == ip2->ip &&
ip1->port == ip2->port &&
@@ -300,7 +301,8 @@ struct hash_netport6_telem {
static inline bool
hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
- const struct hash_netport6_elem *ip2)
+ const struct hash_netport6_elem *ip2,
+ u32 *multi)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->port == ip2->port &&
--
1.7.2.3
^ permalink raw reply related
* [PATCH 6/8] netfilter: ipset: make possible to hash some part of the data element only
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
In-Reply-To: <1311243476-18236-1-git-send-email-kaber@trash.net>
From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/linux/netfilter/ipset/ip_set_ahash.h | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
index c5b06aa..42b7d25 100644
--- a/include/linux/netfilter/ipset/ip_set_ahash.h
+++ b/include/linux/netfilter/ipset/ip_set_ahash.h
@@ -211,12 +211,16 @@ ip_set_hash_destroy(struct ip_set *set)
set->data = NULL;
}
-#define HKEY(data, initval, htable_bits) \
-(jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \
- & jhash_mask(htable_bits))
-
#endif /* _IP_SET_AHASH_H */
+#ifndef HKEY_DATALEN
+#define HKEY_DATALEN sizeof(struct type_pf_elem)
+#endif
+
+#define HKEY(data, initval, htable_bits) \
+(jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \
+ & jhash_mask(htable_bits))
+
#define CONCAT(a, b, c) a##b##c
#define TOKEN(a, b, c) CONCAT(a, b, c)
@@ -1054,6 +1058,8 @@ type_pf_gc_init(struct ip_set *set)
IPSET_GC_PERIOD(h->timeout));
}
+#undef HKEY_DATALEN
+#undef HKEY
#undef type_pf_data_equal
#undef type_pf_data_isnull
#undef type_pf_data_copy
--
1.7.2.3
^ permalink raw reply related
* [PATCH 5/8] netfilter: nfnetlink_queue: batch verdict support
From: kaber @ 2011-07-21 10:17 UTC (permalink / raw)
To: davem; +Cc: netfilter-devel, netdev
In-Reply-To: <1311243476-18236-1-git-send-email-kaber@trash.net>
From: Florian Westphal <fw@strlen.de>
Introduces a new nfnetlink type that applies a given
verdict to all queued packets with an id <= the id in the verdict
message.
If a mark is provided it is applied to all matched packets.
This reduces the number of verdicts that have to be sent.
Applications that make use of this feature need to maintain
a timeout to send a batchverdict periodically to avoid starvation.
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
---
include/linux/netfilter/nfnetlink_queue.h | 1 +
net/netfilter/nfnetlink_queue.c | 115 ++++++++++++++++++++++++++---
2 files changed, 104 insertions(+), 12 deletions(-)
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index af94e00..24b32e6 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -8,6 +8,7 @@ enum nfqnl_msg_types {
NFQNL_MSG_PACKET, /* packet from kernel to userspace */
NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */
NFQNL_MSG_CONFIG, /* connect to a particular queue */
+ NFQNL_MSG_VERDICT_BATCH, /* batchv from userspace to kernel */
NFQNL_MSG_MAX
};
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 3b2af8c..fbfcd83 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -171,6 +171,13 @@ __enqueue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
queue->queue_total++;
}
+static void
+__dequeue_entry(struct nfqnl_instance *queue, struct nf_queue_entry *entry)
+{
+ list_del(&entry->list);
+ queue->queue_total--;
+}
+
static struct nf_queue_entry *
find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
{
@@ -185,10 +192,8 @@ find_dequeue_entry(struct nfqnl_instance *queue, unsigned int id)
}
}
- if (entry) {
- list_del(&entry->list);
- queue->queue_total--;
- }
+ if (entry)
+ __dequeue_entry(queue, entry);
spin_unlock_bh(&queue->lock);
@@ -611,6 +616,92 @@ static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
[NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
};
+static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
+ [NFQA_VERDICT_HDR] = { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
+ [NFQA_MARK] = { .type = NLA_U32 },
+};
+
+static struct nfqnl_instance *verdict_instance_lookup(u16 queue_num, int nlpid)
+{
+ struct nfqnl_instance *queue;
+
+ queue = instance_lookup(queue_num);
+ if (!queue)
+ return ERR_PTR(-ENODEV);
+
+ if (queue->peer_pid != nlpid)
+ return ERR_PTR(-EPERM);
+
+ return queue;
+}
+
+static struct nfqnl_msg_verdict_hdr*
+verdicthdr_get(const struct nlattr * const nfqa[])
+{
+ struct nfqnl_msg_verdict_hdr *vhdr;
+ unsigned int verdict;
+
+ if (!nfqa[NFQA_VERDICT_HDR])
+ return NULL;
+
+ vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
+ verdict = ntohl(vhdr->verdict);
+ if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT)
+ return NULL;
+ return vhdr;
+}
+
+static int nfq_id_after(unsigned int id, unsigned int max)
+{
+ return (int)(id - max) > 0;
+}
+
+static int
+nfqnl_recv_verdict_batch(struct sock *ctnl, struct sk_buff *skb,
+ const struct nlmsghdr *nlh,
+ const struct nlattr * const nfqa[])
+{
+ struct nfgenmsg *nfmsg = NLMSG_DATA(nlh);
+ struct nf_queue_entry *entry, *tmp;
+ unsigned int verdict, maxid;
+ struct nfqnl_msg_verdict_hdr *vhdr;
+ struct nfqnl_instance *queue;
+ LIST_HEAD(batch_list);
+ u16 queue_num = ntohs(nfmsg->res_id);
+
+ queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
+ if (IS_ERR(queue))
+ return PTR_ERR(queue);
+
+ vhdr = verdicthdr_get(nfqa);
+ if (!vhdr)
+ return -EINVAL;
+
+ verdict = ntohl(vhdr->verdict);
+ maxid = ntohl(vhdr->id);
+
+ spin_lock_bh(&queue->lock);
+
+ list_for_each_entry_safe(entry, tmp, &queue->queue_list, list) {
+ if (nfq_id_after(entry->id, maxid))
+ break;
+ __dequeue_entry(queue, entry);
+ list_add_tail(&entry->list, &batch_list);
+ }
+
+ spin_unlock_bh(&queue->lock);
+
+ if (list_empty(&batch_list))
+ return -ENOENT;
+
+ list_for_each_entry_safe(entry, tmp, &batch_list, list) {
+ if (nfqa[NFQA_MARK])
+ entry->skb->mark = ntohl(nla_get_be32(nfqa[NFQA_MARK]));
+ nf_reinject(entry, verdict);
+ }
+ return 0;
+}
+
static int
nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
const struct nlmsghdr *nlh,
@@ -626,20 +717,17 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
queue = instance_lookup(queue_num);
if (!queue)
- return -ENODEV;
- if (queue->peer_pid != NETLINK_CB(skb).pid)
- return -EPERM;
+ queue = verdict_instance_lookup(queue_num, NETLINK_CB(skb).pid);
+ if (IS_ERR(queue))
+ return PTR_ERR(queue);
- if (!nfqa[NFQA_VERDICT_HDR])
+ vhdr = verdicthdr_get(nfqa);
+ if (!vhdr)
return -EINVAL;
- vhdr = nla_data(nfqa[NFQA_VERDICT_HDR]);
verdict = ntohl(vhdr->verdict);
- if ((verdict & NF_VERDICT_MASK) > NF_MAX_VERDICT)
- return -EINVAL;
-
entry = find_dequeue_entry(queue, ntohl(vhdr->id));
if (entry == NULL)
return -ENOENT;
@@ -775,6 +863,9 @@ static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
[NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config,
.attr_count = NFQA_CFG_MAX,
.policy = nfqa_cfg_policy },
+ [NFQNL_MSG_VERDICT_BATCH]={ .call_rcu = nfqnl_recv_verdict_batch,
+ .attr_count = NFQA_MAX,
+ .policy = nfqa_verdict_batch_policy },
};
static const struct nfnetlink_subsystem nfqnl_subsys = {
--
1.7.2.3
^ permalink raw reply related
* Re: NIC driver r8168 with r8169 for RTL8111/8168B and DGE-528T together
From: Francois Romieu @ 2011-07-21 10:22 UTC (permalink / raw)
To: Danie Wessels; +Cc: Stephen Hemminger, netdev
In-Reply-To: <4E2752A2.3030208@telkomsa.net>
Danie Wessels <dawessels@telkomsa.net> :
[...]
> .> Remove the 8168 PCI IDs from the r8169 driver and you should be set.
> gr8. I can give that a try...8^0 (some more hints....?)
Search for rtl8169_pci_tbl and remove the 0x8168 line : the kernel r8169
driver will stop being used on the 8168s.
>
> .>It ought to be supported by the kernel r8169 driver.
>
> See bugs listed on Ubuntu:
> https://bugs.launchpad.net/ubuntu/+source/linux-source-2.6.22/+bug/141343
Executive summary :
a. started in 2007
b. includes "kernel r8169 driver does not work, tried Realtek's r8168,
happy now"
c. includes b. + "...wait a few days, Oops"
d. covers different devices (8168b, 8168c, plain 8169).
e. people still using old kernel (see post 2.6.26
77332894c21165404496c56763d7df6c15c4bb09 in #38 then mention of 2.6.22,
2.6.24)
f. usual "this is the same bug" (#141343 is the same bug as #141343
e. one (1) dmesg attached to the whole thread (74 messages). Tons of lspci,
not a single XID.
> https://bugs.launchpad.net/ubuntu/+source/linux/+bug/221499
Trend (?) : recent kernels help. XID and up-to-date reports would be
welcome if they can be streamlined to a standard (for me :o) ) kernel.
See below.
> https://bugs.launchpad.net/linux/+bug/347711
I wish I could filter out comments by author. Flat PR get really, really
messy with time.
> And 0n Bug #347711
> linux-kernel-bugs #12411
> Duplicates of this bug
> Bug #76489
> Bug #347670
Parts of reports look the same but it is more a bag of mixed bugs than
a duplicated one. On the bright side I only have to pick one to fix
something. :o/
> .> Which problem(s) do you have with it ?
> No communication to outside devices. I can not ping my router
> through it but can ping its IP.
So it is receiving packets either in promiscuous mode or (and)
as long as its peer knows its MAC address ?
No Tx at all (it may help if you can capture traffic on the remote
end) or just a few packets before it stops (and spits a NETDEV
WATCHDOG message) ?
> What can I do now or where should I report it or how can I help?
> RTFM 4 rules.d = where?
- Where (general)
Here and/or kernel.org bugzilla. Cc: good. Private email: bad. You may
Cc: Hayes as well.
If you go for bugzilla, fill Product/Component as "Drivers/Network"
- What (general)
If it is not a regression - i.e. it does not fall in the "stopped
working" bucket - always try last Linus's -rc or David Miller's "next"
branch. I may have a bit more pending sauce but the "next" branch usually
is a good starting point (especially as fixing regressions in it asap is
a rather high priority task). "next" is waiting for you at :
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6.git
Comparing Realtek's driver and kernel r8169 one is welcome. BIOS lan
options and reboot from a different OS sometimes make a difference (its
always nice to be sure than the damn thing _can_ work).
Include:
- dmesg output (unabbreviated, explicit). The XID line is a mess but it
allows me to triage the bugs.
- ethtool -d ethX. Be it a single line or a (nowadays partial) registers
dump.
- lspci -v/-tv
- brand/motherboard identification
(wrt your report, I already have most of the needed material)
Ping me when you want a status update or feel things are sidetracked.
- What (specific)
One of Ubuntu's report suggests that you are experiencing a regression.
If so it would be nice to bissect it.
In the short run I can not do more as I must push something out for a mac
address change problem with the 8168evl.
--
Ueimor
^ permalink raw reply
* Re: [PATCH][TRIVIAL] net, netfilter: Remove redundant goto in ebt_ulog_packet
From: Jiri Kosina @ 2011-07-21 12:02 UTC (permalink / raw)
To: Jesper Juhl
Cc: linux-kernel, netdev, bridge, coreteam, netfilter,
netfilter-devel, David S. Miller, Stephen Hemminger,
Patrick McHardy, Bart De Schuymer
In-Reply-To: <alpine.LNX.2.00.1107171953500.32359@swampdragon.chaosbits.net>
On Sun, 17 Jul 2011, Jesper Juhl wrote:
> In net/bridge/netfilter/ebt_ulog.c:ebt_ulog_packet() the 'goto unlock'
> before the 'alloc_failure' label is completely redundant. This patch
> removes it.
>
> Signed-off-by: Jesper Juhl <jj@chaosbits.net>
> ---
> net/bridge/netfilter/ebt_ulog.c | 1 -
> 1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
> index 26377e9..bf2a333 100644
> --- a/net/bridge/netfilter/ebt_ulog.c
> +++ b/net/bridge/netfilter/ebt_ulog.c
> @@ -216,7 +216,6 @@ unlock:
> nlmsg_failure:
> pr_debug("error during NLMSG_PUT. This should "
> "not happen, please report to author.\n");
> - goto unlock;
> alloc_failure:
> goto unlock;
> }
> --
> 1.7.6
>
>
> PS. Please CC me on replies since I'm not subscribed to all the lists
> copied on this mail.
Doesn't seem to be present in linux-next as of today. I have picked it up.
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* Re: [PATCH 09/10] nfs: use sk fragment destructors to delay I/O completion until page is released by network stack.
From: Ian Campbell @ 2011-07-21 13:18 UTC (permalink / raw)
To: Trond Myklebust
Cc: netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-nfs-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1310738489.4381.20.camel-SyLVLa/KEI9HwK5hSS5vWB2eb7JE58TQ@public.gmane.org>
On Fri, 2011-07-15 at 15:01 +0100, Trond Myklebust wrote:
> On Fri, 2011-07-15 at 12:07 +0100, Ian Campbell wrote:
> > Thos prevents an issue where an ACK is delayed, a retransmit is queued (either
> > at the RPC or TCP level) and the ACK arrives before the retransmission hits the
> > wire. If this happens then the write() system call and the userspace process
> > can continue potentially modifying the data before the retransmission occurs.
> >
> > NB: this only covers the O_DIRECT write() case. I expect other cases to need
> > handling as well.
>
> That is why this belongs entirely in the RPC layer, and really should
> not touch the NFS layer.
> If you move your callback to the RPC layer and have it notify the
> rpc_task when the pages have been sent, then it should be possible to
> achieve the same thing.
>
> IOW: Add an extra state machine step after call_decode() which checks if
> all the page data has been transmitted and if not, puts the rpc_task on
> a wait queue, and has it wait for the fragment destructor callback
> before calling rpc_exit_task().
>
> Cheers
Is this the sort of thing? I wasn't sure where best to put the
destructor data structure to get the right lifecycle and ended up
putting it in the struct rpc_rqst and initialising it at
xprt_request_init time.
I changed everywhere which currently transitions to rpc_exit_task to
transition to a new "call_complete" task, blocking on the pending wait
queue. The SKB destructor wakes that queue and call_complete then
transitions to rpc_exit_task.
Several of the locations already block on that wait queue so I simply
remove the wake up in those cases (since it will happen in the SKB frag
destructor). Since we call unref at these points (to drop the initial
refcount) in the common case we will be woken from the pending wait
queue before we even sleep on it.
Thanks,
Ian.
>From 49d7d53d065bf0963fd4bb70405f4f1972f618c4 Mon Sep 17 00:00:00 2001
From: Ian Campbell <ian.campbell-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
Date: Mon, 11 Jul 2011 14:43:24 +0100
Subject: [PATCH] sunrpc: use SKB fragment destructors to delay completion until page is released by network stack.
This prevents an issue where an ACK is delayed, a retransmit is queued (either
at the RPC or TCP level) and the ACK arrives before the retransmission hits the
wire. If this happens to an NFS WRITE RPC then the write() system call
completes and the userspace process can continue, potentially modifying data
referenced by the retransmission before the retransmission occurs.
Signed-off-by: Ian Campbell <ian.campbell-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
---
include/linux/sunrpc/xdr.h | 2 ++
include/linux/sunrpc/xprt.h | 5 ++++-
net/sunrpc/clnt.c | 28 +++++++++++++++++++++++-----
net/sunrpc/svcsock.c | 2 +-
net/sunrpc/xprt.c | 13 +++++++++++++
net/sunrpc/xprtsock.c | 2 +-
6 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index a20970e..172f81e 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -16,6 +16,7 @@
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
/*
* Buffer adjustment
@@ -57,6 +58,7 @@ struct xdr_buf {
tail[1]; /* Appended after page data */
struct page ** pages; /* Array of contiguous pages */
+ struct skb_frag_destructor *destructor;
unsigned int page_base, /* Start of page data */
page_len, /* Length of page data */
flags; /* Flags for data disposition */
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 81cce3b..0de6bc3 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -91,7 +91,10 @@ struct rpc_rqst {
/* A cookie used to track the
state of the transport
connection */
-
+ struct skb_frag_destructor destructor; /* SKB paged fragment
+ * destructor for
+ * transmitted pages*/
+
/*
* Partial send handling
*/
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 8c91415..0c85acb 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -61,6 +61,7 @@ static void call_reserve(struct rpc_task *task);
static void call_reserveresult(struct rpc_task *task);
static void call_allocate(struct rpc_task *task);
static void call_decode(struct rpc_task *task);
+static void call_complete(struct rpc_task *task);
static void call_bind(struct rpc_task *task);
static void call_bind_status(struct rpc_task *task);
static void call_transmit(struct rpc_task *task);
@@ -1114,6 +1115,8 @@ rpc_xdr_encode(struct rpc_task *task)
(char *)req->rq_buffer + req->rq_callsize,
req->rq_rcvsize);
+ req->rq_snd_buf.destructor = &req->destructor;
+
p = rpc_encode_header(task);
if (p == NULL) {
printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n");
@@ -1277,6 +1280,7 @@ call_connect_status(struct rpc_task *task)
static void
call_transmit(struct rpc_task *task)
{
+ struct rpc_rqst *req = task->tk_rqstp;
dprint_status(task);
task->tk_action = call_status;
@@ -1310,8 +1314,8 @@ call_transmit(struct rpc_task *task)
call_transmit_status(task);
if (rpc_reply_expected(task))
return;
- task->tk_action = rpc_exit_task;
- rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
+ task->tk_action = call_complete;
+ skb_frag_destructor_unref(&req->destructor);
}
/*
@@ -1384,7 +1388,8 @@ call_bc_transmit(struct rpc_task *task)
return;
}
- task->tk_action = rpc_exit_task;
+ task->tk_action = call_complete;
+ skb_frag_destructor_unref(&req->destructor);
if (task->tk_status < 0) {
printk(KERN_NOTICE "RPC: Could not send backchannel reply "
"error: %d\n", task->tk_status);
@@ -1424,7 +1429,6 @@ call_bc_transmit(struct rpc_task *task)
"error: %d\n", task->tk_status);
break;
}
- rpc_wake_up_queued_task(&req->rq_xprt->pending, task);
}
#endif /* CONFIG_NFS_V4_1 */
@@ -1591,12 +1595,14 @@ call_decode(struct rpc_task *task)
return;
}
- task->tk_action = rpc_exit_task;
+ task->tk_action = call_complete;
if (decode) {
task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
task->tk_msg.rpc_resp);
}
+ rpc_sleep_on(&req->rq_xprt->pending, task, NULL);
+ skb_frag_destructor_unref(&req->destructor);
dprintk("RPC: %5u call_decode result %d\n", task->tk_pid,
task->tk_status);
return;
@@ -1611,6 +1617,18 @@ out_retry:
}
}
+/*
+ * 8. Wait for pages to be released by the network stack.
+ */
+static void
+call_complete(struct rpc_task *task)
+{
+ struct rpc_rqst *req = task->tk_rqstp;
+ dprintk("RPC: %5u call_complete result %d\n", task->tk_pid, task->tk_status);
+ task->tk_action = rpc_exit_task;
+ rpc_wake_up_queued_task(&req->rq_xprt->pending, task);
+}
+
static __be32 *
rpc_encode_header(struct rpc_task *task)
{
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index a80b1d3..40c2420 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -194,7 +194,7 @@ int svc_send_common(struct socket *sock, struct xdr_buf *xdr,
while (pglen > 0) {
if (slen == size)
flags = 0;
- result = kernel_sendpage(sock, *ppage, NULL, base, size, flags);
+ result = kernel_sendpage(sock, *ppage, xdr->destructor, base, size, flags);
if (result > 0)
len += result;
if (result != size)
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index ce5eb68..62f52a3 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1017,6 +1017,16 @@ static inline void xprt_init_xid(struct rpc_xprt *xprt)
xprt->xid = net_random();
}
+static int xprt_complete_skb_pages(void *calldata)
+{
+ struct rpc_task *task = calldata;
+ struct rpc_rqst *req = task->tk_rqstp;
+
+ dprintk("RPC: %5u completing skb pages\n", task->tk_pid);
+ rpc_wake_up_queued_task(&req->rq_xprt->pending, task);
+ return 0;
+}
+
static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
{
struct rpc_rqst *req = task->tk_rqstp;
@@ -1028,6 +1038,9 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
req->rq_xid = xprt_alloc_xid(xprt);
req->rq_release_snd_buf = NULL;
xprt_reset_majortimeo(req);
+ atomic_set(&req->destructor.ref, 1);
+ req->destructor.destroy = &xprt_complete_skb_pages;
+ req->destructor.data = task;
dprintk("RPC: %5u reserved req %p xid %08x\n", task->tk_pid,
req, ntohl(req->rq_xid));
}
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index d027621..ca1643b 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -397,7 +397,7 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i
remainder -= len;
if (remainder != 0 || more)
flags |= MSG_MORE;
- err = sock->ops->sendpage(sock, *ppage, NULL, base, len, flags);
+ err = sock->ops->sendpage(sock, *ppage, xdr->destructor, base, len, flags);
if (remainder == 0 || err != len)
break;
sent += err;
--
1.7.2.5
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [patch net-next-2.6 18/47 V2] igbvf: do vlan cleanup
From: Jiri Pirko @ 2011-07-21 13:22 UTC (permalink / raw)
To: netdev
Cc: jesse, e1000-devel, bruce.w.allan, jesse.brandeburg, mirqus,
john.ronciak, shemminger, davem
In-Reply-To: <1311173689-17419-19-git-send-email-jpirko@redhat.com>
- unify vlan and nonvlan rx path
- kill adapter->vlgrp and igbvf_vlan_rx_register
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
drivers/net/igbvf/igbvf.h | 4 +-
drivers/net/igbvf/netdev.c | 55 +++++++++++++++++++------------------------
2 files changed, 26 insertions(+), 33 deletions(-)
diff --git a/drivers/net/igbvf/igbvf.h b/drivers/net/igbvf/igbvf.h
index d5dad5d..fd4a7b7 100644
--- a/drivers/net/igbvf/igbvf.h
+++ b/drivers/net/igbvf/igbvf.h
@@ -34,7 +34,7 @@
#include <linux/timer.h>
#include <linux/io.h>
#include <linux/netdevice.h>
-
+#include <linux/if_vlan.h>
#include "vf.h"
@@ -173,7 +173,7 @@ struct igbvf_adapter {
const struct igbvf_info *ei;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u32 bd_number;
u32 rx_buffer_len;
u32 polling_interval;
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 64b47bf..d924b09 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -100,12 +100,12 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
struct sk_buff *skb,
u32 status, u16 vlan)
{
- if (adapter->vlgrp && (status & E1000_RXD_STAT_VP))
- vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(vlan) &
- E1000_RXD_SPC_VLAN_MASK);
- else
- netif_receive_skb(skb);
+ if (status & E1000_RXD_STAT_VP) {
+ u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+
+ __vlan_hwaccel_put_tag(skb, vid);
+ }
+ netif_receive_skb(skb);
}
static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
@@ -1167,22 +1167,29 @@ static int igbvf_poll(struct napi_struct *napi, int budget)
*/
static void igbvf_set_rlpml(struct igbvf_adapter *adapter)
{
- int max_frame_size = adapter->max_frame_size;
+ int max_frame_size;
struct e1000_hw *hw = &adapter->hw;
- if (adapter->vlgrp)
- max_frame_size += VLAN_TAG_SIZE;
-
+ max_frame_size = adapter->max_frame_size + VLAN_TAG_SIZE;
e1000_rlpml_set_vf(hw, max_frame_size);
}
-static void igbvf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+static bool __igbvf_vlan_rx_add_vid(struct igbvf_adapter *adapter, u16 vid)
{
- struct igbvf_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
if (hw->mac.ops.set_vfta(hw, vid, true))
dev_err(&adapter->pdev->dev, "Failed to add vlan id %d\n", vid);
+ return false;
+ return true;
+}
+
+static void igbvf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+ struct igbvf_adapter *adapter = netdev_priv(netdev);
+
+ if (__igbvf_vlan_rx_add_vid(adapter, vid))
+ set_bit(vid, adapter->active_vlans);
}
static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -1191,7 +1198,6 @@ static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
struct e1000_hw *hw = &adapter->hw;
igbvf_irq_disable(adapter);
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
if (!test_bit(__IGBVF_DOWN, &adapter->state))
igbvf_irq_enable(adapter);
@@ -1199,28 +1205,16 @@ static void igbvf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
if (hw->mac.ops.set_vfta(hw, vid, false))
dev_err(&adapter->pdev->dev,
"Failed to remove vlan id %d\n", vid);
-}
-
-static void igbvf_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
-{
- struct igbvf_adapter *adapter = netdev_priv(netdev);
-
- adapter->vlgrp = grp;
+ else
+ clear_bit(vid, adapter->active_vlans);
}
static void igbvf_restore_vlan(struct igbvf_adapter *adapter)
{
u16 vid;
- if (!adapter->vlgrp)
- return;
-
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(adapter->vlgrp, vid))
- continue;
- igbvf_vlan_rx_add_vid(adapter->netdev, vid);
- }
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ __igbvf_vlan_rx_add_vid(adapter, vid);
igbvf_set_rlpml(adapter);
}
@@ -2203,7 +2197,7 @@ static netdev_tx_t igbvf_xmit_frame_ring_adv(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
- if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+ if (vlan_tx_tag_present(skb)) {
tx_flags |= IGBVF_TX_FLAGS_VLAN;
tx_flags |= (vlan_tx_tag_get(skb) << IGBVF_TX_FLAGS_VLAN_SHIFT);
}
@@ -2556,7 +2550,6 @@ static const struct net_device_ops igbvf_netdev_ops = {
.ndo_change_mtu = igbvf_change_mtu,
.ndo_do_ioctl = igbvf_ioctl,
.ndo_tx_timeout = igbvf_tx_timeout,
- .ndo_vlan_rx_register = igbvf_vlan_rx_register,
.ndo_vlan_rx_add_vid = igbvf_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = igbvf_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
--
1.7.6
------------------------------------------------------------------------------
5 Ways to Improve & Secure Unified Communications
Unified Communications promises greater efficiencies for business. UC can
improve internal communications as well as offer faster, more efficient ways
to interact with customers and streamline customer service. Learn more!
http://www.accelacomm.com/jaw/sfnl/114/51426253/
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply related
* [patch net-next-2.6 21/47 V2] qlge: do vlan cleanup
From: Jiri Pirko @ 2011-07-21 13:24 UTC (permalink / raw)
To: netdev
Cc: davem, shemminger, eric.dumazet, greearb, mirqus,
jitendra.kalsaria, ron.mercer, linux-driver, jesse
In-Reply-To: <1311173689-17419-22-git-send-email-jpirko@redhat.com>
- unify vlan and nonvlan path
- kill qdev->vlgrp and qlge_vlan_rx_register
- allow to turn on/off rx/tx vlan accel via ethtool (set_features)
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
drivers/net/qlge/qlge.h | 3 +-
drivers/net/qlge/qlge_main.c | 163 ++++++++++++++++++++++++------------------
2 files changed, 94 insertions(+), 72 deletions(-)
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index 794252c..8731f79 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
/*
* General definitions...
@@ -2052,7 +2053,7 @@ struct ql_adapter {
struct nic_stats nic_stats;
- struct vlan_group *vlgrp;
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
/* PCI Configuration information for this device */
struct pci_dev *pdev;
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 68fbfac..743e3ec 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -7,6 +7,7 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/list.h>
@@ -33,6 +34,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <linux/delay.h>
@@ -415,7 +417,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
(qdev->
func << CAM_OUT_FUNC_SHIFT) |
(0 << CAM_OUT_CQ_ID_SHIFT));
- if (qdev->vlgrp)
+ if (qdev->ndev->features & NETIF_F_HW_VLAN_RX)
cam_output |= CAM_OUT_RV;
/* route to NIC core */
ql_write32(qdev, MAC_ADDR_DATA, cam_output);
@@ -1507,10 +1509,9 @@ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev,
rx_ring->rx_bytes += length;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb_record_rx_queue(skb, rx_ring->cq_id);
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_gro_frags(&rx_ring->napi, qdev->vlgrp, vlan_id);
- else
- napi_gro_frags(napi);
+ if (vlan_id != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vlan_id);
+ napi_gro_frags(napi);
}
/* Process an inbound completion from an rx ring. */
@@ -1594,17 +1595,12 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev,
}
skb_record_rx_queue(skb, rx_ring->cq_id);
- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_gro_receive(napi, qdev->vlgrp, vlan_id, skb);
- else
- napi_gro_receive(napi, skb);
- } else {
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
- else
- netif_receive_skb(skb);
- }
+ if (vlan_id != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vlan_id);
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ napi_gro_receive(napi, skb);
+ else
+ netif_receive_skb(skb);
return;
err_out:
dev_kfree_skb_any(skb);
@@ -1707,18 +1703,12 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev,
}
skb_record_rx_queue(skb, rx_ring->cq_id);
- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_gro_receive(&rx_ring->napi, qdev->vlgrp,
- vlan_id, skb);
- else
- napi_gro_receive(&rx_ring->napi, skb);
- } else {
- if (qdev->vlgrp && (vlan_id != 0xffff))
- vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
- else
- netif_receive_skb(skb);
- }
+ if (vlan_id != 0xffff)
+ __vlan_hwaccel_put_tag(skb, vlan_id);
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ napi_gro_receive(&rx_ring->napi, skb);
+ else
+ netif_receive_skb(skb);
}
static void ql_realign_skb(struct sk_buff *skb, int len)
@@ -2028,22 +2018,12 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev,
rx_ring->rx_packets++;
rx_ring->rx_bytes += skb->len;
skb_record_rx_queue(skb, rx_ring->cq_id);
- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
- if (qdev->vlgrp &&
- (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) &&
- (vlan_id != 0))
- vlan_gro_receive(&rx_ring->napi, qdev->vlgrp,
- vlan_id, skb);
- else
- napi_gro_receive(&rx_ring->napi, skb);
- } else {
- if (qdev->vlgrp &&
- (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) &&
- (vlan_id != 0))
- vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id);
- else
- netif_receive_skb(skb);
- }
+ if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && (vlan_id != 0))
+ __vlan_hwaccel_put_tag(skb, vlan_id);
+ if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+ napi_gro_receive(&rx_ring->napi, skb);
+ else
+ netif_receive_skb(skb);
}
/* Process an inbound completion from an rx ring. */
@@ -2334,71 +2314,111 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget)
return work_done;
}
-static void qlge_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
+static void qlge_vlan_mode(struct net_device *ndev, u32 features)
{
struct ql_adapter *qdev = netdev_priv(ndev);
- qdev->vlgrp = grp;
- if (grp) {
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
+ if (features & NETIF_F_HW_VLAN_RX) {
+ netif_printk(qdev, ifup, KERN_DEBUG, ndev,
"Turning on VLAN in NIC_RCV_CFG.\n");
ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK |
- NIC_RCV_CFG_VLAN_MATCH_AND_NON);
+ NIC_RCV_CFG_VLAN_MATCH_AND_NON);
} else {
- netif_printk(qdev, ifup, KERN_DEBUG, qdev->ndev,
+ netif_printk(qdev, ifup, KERN_DEBUG, ndev,
"Turning off VLAN in NIC_RCV_CFG.\n");
ql_write32(qdev, NIC_RCV_CFG, NIC_RCV_CFG_VLAN_MASK);
}
}
-static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
+static u32 qlge_fix_features(struct net_device *ndev, u32 features)
+{
+ /*
+ * Since there is no support for separate rx/tx vlan accel
+ * enable/disable make sure tx flag is always in same state as rx.
+ */
+ if (features & NETIF_F_HW_VLAN_RX)
+ features |= NETIF_F_HW_VLAN_TX;
+ else
+ features &= ~NETIF_F_HW_VLAN_TX;
+
+ return features;
+}
+
+static int qlge_set_features(struct net_device *ndev, u32 features)
+{
+ u32 changed = ndev->features ^ features;
+
+ if (changed & NETIF_F_HW_VLAN_RX)
+ qlge_vlan_mode(ndev, features);
+
+ return 0;
+}
+
+static void __qlge_vlan_rx_add_vid(struct ql_adapter *qdev, u16 vid)
{
- struct ql_adapter *qdev = netdev_priv(ndev);
u32 enable_bit = MAC_ADDR_E;
- int status;
- status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
- if (status)
- return;
if (ql_set_mac_addr_reg
(qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
netif_err(qdev, ifup, qdev->ndev,
"Failed to init vlan address.\n");
}
- ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
}
-static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+static void qlge_vlan_rx_add_vid(struct net_device *ndev, u16 vid)
{
struct ql_adapter *qdev = netdev_priv(ndev);
- u32 enable_bit = 0;
int status;
status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
if (status)
return;
+ __qlge_vlan_rx_add_vid(qdev, vid);
+ set_bit(vid, qdev->active_vlans);
+
+ ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+}
+
+static void __qlge_vlan_rx_kill_vid(struct ql_adapter *qdev, u16 vid)
+{
+ u32 enable_bit = 0;
+
if (ql_set_mac_addr_reg
(qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) {
netif_err(qdev, ifup, qdev->ndev,
"Failed to clear vlan address.\n");
}
- ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
+}
+
+static void qlge_vlan_rx_kill_vid(struct net_device *ndev, u16 vid)
+{
+ struct ql_adapter *qdev = netdev_priv(ndev);
+ int status;
+
+ status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+ if (status)
+ return;
+
+ __qlge_vlan_rx_kill_vid(qdev, vid);
+ clear_bit(vid, qdev->active_vlans);
+ ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
}
static void qlge_restore_vlan(struct ql_adapter *qdev)
{
- qlge_vlan_rx_register(qdev->ndev, qdev->vlgrp);
+ int status;
+ u16 vid;
- if (qdev->vlgrp) {
- u16 vid;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(qdev->vlgrp, vid))
- continue;
- qlge_vlan_rx_add_vid(qdev->ndev, vid);
- }
- }
+ status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK);
+ if (status)
+ return;
+
+ for_each_set_bit(vid, qdev->active_vlans, VLAN_N_VID)
+ __qlge_vlan_rx_add_vid(qdev, vid);
+
+ ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK);
}
/* MSI-X Multiple Vector Interrupt Handler for inbound completions. */
@@ -4661,7 +4681,8 @@ static const struct net_device_ops qlge_netdev_ops = {
.ndo_set_mac_address = qlge_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = qlge_tx_timeout,
- .ndo_vlan_rx_register = qlge_vlan_rx_register,
+ .ndo_fix_features = qlge_fix_features,
+ .ndo_set_features = qlge_set_features,
.ndo_vlan_rx_add_vid = qlge_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid,
};
--
1.7.6
^ permalink raw reply related
* [patch net-next-2.6 26/47 V2] ixgbevf: do vlan cleanup
From: Jiri Pirko @ 2011-07-21 13:25 UTC (permalink / raw)
To: netdev
Cc: davem, shemminger, eric.dumazet, greearb, mirqus,
jeffrey.t.kirsher, jesse.brandeburg, peter.p.waskiewicz.jr,
bruce.w.allan, carolyn.wyborny, donald.c.skidmore, gregory.v.rose,
alexander.h.duyck, john.ronciak, e1000-devel, jesse
In-Reply-To: <1311173689-17419-27-git-send-email-jpirko@redhat.com>
- unify vlan and nonvlan rx path
- kill adapter->vlgrp and ixgbevf_vlan_rx_register
Signed-off-by: Jiri Pirko <jpirko@redhat.com>
---
drivers/net/ixgbevf/ixgbevf.h | 6 ++--
drivers/net/ixgbevf/ixgbevf_main.c | 64 ++++++++---------------------------
2 files changed, 18 insertions(+), 52 deletions(-)
diff --git a/drivers/net/ixgbevf/ixgbevf.h b/drivers/net/ixgbevf/ixgbevf.h
index a2bbbb3..8857df4 100644
--- a/drivers/net/ixgbevf/ixgbevf.h
+++ b/drivers/net/ixgbevf/ixgbevf.h
@@ -29,9 +29,11 @@
#define _IXGBEVF_H_
#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/timer.h>
#include <linux/io.h>
#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
#include "vf.h"
@@ -185,9 +187,7 @@ struct ixgbevf_q_vector {
/* board specific private data structure */
struct ixgbevf_adapter {
struct timer_list watchdog_timer;
-#ifdef NETIF_F_HW_VLAN_TX
- struct vlan_group *vlgrp;
-#endif
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
u16 bd_number;
struct work_struct reset_task;
struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index fec36bd..3b880a2 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -30,6 +30,7 @@
Copyright (c)2006 - 2007 Myricom, Inc. for some LRO specific code
******************************************************************************/
#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
@@ -288,21 +289,17 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
{
struct ixgbevf_adapter *adapter = q_vector->adapter;
bool is_vlan = (status & IXGBE_RXD_STAT_VP);
- u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
- if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
- if (adapter->vlgrp && is_vlan)
- vlan_gro_receive(&q_vector->napi,
- adapter->vlgrp,
- tag, skb);
- else
+ if (is_vlan) {
+ u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
+
+ __vlan_hwaccel_put_tag(skb, tag);
+ }
+
+ if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
napi_gro_receive(&q_vector->napi, skb);
- } else {
- if (adapter->vlgrp && is_vlan)
- vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
- else
+ else
netif_rx(skb);
- }
}
/**
@@ -1401,24 +1398,6 @@ static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter)
}
}
-static void ixgbevf_vlan_rx_register(struct net_device *netdev,
- struct vlan_group *grp)
-{
- struct ixgbevf_adapter *adapter = netdev_priv(netdev);
- struct ixgbe_hw *hw = &adapter->hw;
- int i, j;
- u32 ctrl;
-
- adapter->vlgrp = grp;
-
- for (i = 0; i < adapter->num_rx_queues; i++) {
- j = adapter->rx_ring[i].reg_idx;
- ctrl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
- ctrl |= IXGBE_RXDCTL_VME;
- IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), ctrl);
- }
-}
-
static void ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
{
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@ -1427,6 +1406,7 @@ static void ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
/* add VID to filter table */
if (hw->mac.ops.set_vfta)
hw->mac.ops.set_vfta(hw, vid, 0, true);
+ set_bit(vid, adapter->active_vlans);
}
static void ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
@@ -1434,31 +1414,18 @@ static void ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
struct ixgbevf_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
- if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
- ixgbevf_irq_disable(adapter);
-
- vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
- if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
- ixgbevf_irq_enable(adapter, true, true);
-
/* remove VID from filter table */
if (hw->mac.ops.set_vfta)
hw->mac.ops.set_vfta(hw, vid, 0, false);
+ clear_bit(vid, adapter->active_vlans);
}
static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter)
{
- ixgbevf_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+ u16 vid;
- if (adapter->vlgrp) {
- u16 vid;
- for (vid = 0; vid < VLAN_N_VID; vid++) {
- if (!vlan_group_get_device(adapter->vlgrp, vid))
- continue;
- ixgbevf_vlan_rx_add_vid(adapter->netdev, vid);
- }
- }
+ for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+ ixgbevf_vlan_rx_add_vid(adapter->netdev, vid);
}
static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
@@ -1648,7 +1615,7 @@ static int ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
for (i = 0; i < num_rx_rings; i++) {
j = adapter->rx_ring[i].reg_idx;
rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
- rxdctl |= IXGBE_RXDCTL_ENABLE;
+ rxdctl |= IXGBE_RXDCTL_ENABLE | IXGBE_RXDCTL_VME;
if (hw->mac.type == ixgbe_mac_X540_vf) {
rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
rxdctl |= ((netdev->mtu + ETH_HLEN + ETH_FCS_LEN) |
@@ -3258,7 +3225,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_mac_address = ixgbevf_set_mac,
.ndo_change_mtu = ixgbevf_change_mtu,
.ndo_tx_timeout = ixgbevf_tx_timeout,
- .ndo_vlan_rx_register = ixgbevf_vlan_rx_register,
.ndo_vlan_rx_add_vid = ixgbevf_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ixgbevf_vlan_rx_kill_vid,
};
--
1.7.6
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox