* [PATCH net-next 2/6] qlcnic: Add support for 0x8830 device ID
From: Shahed Shaikh @ 2014-08-27 16:43 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept-GELinuxNICDev, Shahed Shaikh
In-Reply-To: <1409157802-7895-1-git-send-email-shahed.shaikh@qlogic.com>
From: Shahed Shaikh <shahed.shaikh@qlogic.com>
Signed-off-by: Shahed Shaikh <shahed.shaikh@qlogic.com>
---
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 2 ++
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 1 +
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 8 ++++++++
3 files changed, 11 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
index b84f5ea..80a5509 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
@@ -2283,6 +2283,7 @@ extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
#define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020
#define PCI_DEVICE_ID_QLOGIC_QLE834X 0x8030
+#define PCI_DEVICE_ID_QLOGIC_QLE8830 0x8830
#define PCI_DEVICE_ID_QLOGIC_VF_QLE834X 0x8430
#define PCI_DEVICE_ID_QLOGIC_QLE844X 0x8040
#define PCI_DEVICE_ID_QLOGIC_VF_QLE844X 0x8440
@@ -2307,6 +2308,7 @@ static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter)
bool status;
status = ((device == PCI_DEVICE_ID_QLOGIC_QLE834X) ||
+ (device == PCI_DEVICE_ID_QLOGIC_QLE8830) ||
(device == PCI_DEVICE_ID_QLOGIC_QLE844X) ||
(device == PCI_DEVICE_ID_QLOGIC_VF_QLE844X) ||
(device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X)) ? true : false;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index 86783e1..d1bded7 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -2284,6 +2284,7 @@ static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter)
fw_info = ahw->fw_info;
switch (pdev->device) {
case PCI_DEVICE_ID_QLOGIC_QLE834X:
+ case PCI_DEVICE_ID_QLOGIC_QLE8830:
strncpy(fw_info->fw_file_name, QLC_83XX_FW_FILE_NAME,
QLC_FW_FILE_NAME_LEN);
break;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index cf08b2d..8db11e2 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -111,6 +111,7 @@ static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter)
static const struct pci_device_id qlcnic_pci_tbl[] = {
ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X),
ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X),
+ ENTRY(PCI_DEVICE_ID_QLOGIC_QLE8830),
ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X),
ENTRY(PCI_DEVICE_ID_QLOGIC_QLE844X),
ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE844X),
@@ -228,6 +229,11 @@ static const struct qlcnic_board_info qlcnic_boards[] = {
PCI_DEVICE_ID_QLOGIC_QLE834X,
0x0, 0x0, "8300 Series 1/10GbE Controller" },
{ PCI_VENDOR_ID_QLOGIC,
+ PCI_DEVICE_ID_QLOGIC_QLE8830,
+ 0x0,
+ 0x0,
+ "8830 Series 1/10GbE Controller" },
+ { PCI_VENDOR_ID_QLOGIC,
PCI_DEVICE_ID_QLOGIC_QLE824X,
PCI_VENDOR_ID_QLOGIC,
0x203,
@@ -1131,6 +1137,7 @@ static void qlcnic_get_bar_length(u32 dev_id, ulong *bar)
*bar = QLCNIC_82XX_BAR0_LENGTH;
break;
case PCI_DEVICE_ID_QLOGIC_QLE834X:
+ case PCI_DEVICE_ID_QLOGIC_QLE8830:
case PCI_DEVICE_ID_QLOGIC_QLE844X:
case PCI_DEVICE_ID_QLOGIC_VF_QLE834X:
case PCI_DEVICE_ID_QLOGIC_VF_QLE844X:
@@ -2474,6 +2481,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ahw->reg_tbl = (u32 *) qlcnic_reg_tbl;
break;
case PCI_DEVICE_ID_QLOGIC_QLE834X:
+ case PCI_DEVICE_ID_QLOGIC_QLE8830:
case PCI_DEVICE_ID_QLOGIC_QLE844X:
qlcnic_83xx_register_map(ahw);
break;
--
1.8.1.4
^ permalink raw reply related
* [PATCH net-next 0/6] qlcnic: Feature addition and enhancements
From: Shahed Shaikh @ 2014-08-27 16:43 UTC (permalink / raw)
To: davem; +Cc: netdev, Dept-GELinuxNICDev, Shahed Shaikh
From: Shahed Shaikh <shahed.shaikh@qlogic.com>
Hi Dave,
This series contains following feature addition and enhancements,
- Update Link speed and Port type information for 83xx series adapters
- Support 0x8830 device ID
- Support for Power on Self Test (POST) feature for 83xx
- Use usleep_range() instead of msleep() for values less than 20ms
Please apply this series to net-next.
Thanks,
Shahed
Jitendra Kalsaria (2):
qlcnic: Update Link speed and port type info for 83xx adapter
qlcnic: Use usleep_range() instead of msleep() for sleep less than
20ms
Shahed Shaikh (4):
qlcnic: Add support for 0x8830 device ID
qlcnic: Add support to run firmware POST
MAINTAINERS: Update group email alias for qlcnic driver
qlcnic: Update version to 5.3.62
MAINTAINERS | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 8 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 221 ++++++++++++++------
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 2 +-
.../net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 156 ++++++++++++++-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 2 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 6 +-
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 10 +-
8 files changed, 337 insertions(+), 70 deletions(-)
^ permalink raw reply
* Re: skb_warn_bad_offload warnings with FreeBSD guests
From: Brian Rak @ 2014-08-27 17:11 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Vlad Yasevich, netdev
In-Reply-To: <1409157890.3173.71.camel@edumazet-glaptop2.roam.corp.google.com>
On 8/27/2014 12:44 PM, Eric Dumazet wrote:
> On Wed, 2014-08-27 at 12:09 -0400, Brian Rak wrote:
>
>> I managed to intercept the raw packet + headers being delivered to the
>> tun device, though I'm having some trouble making sense of it. I've got
>> this call:
>>
>> writev(33, [{"\x00\x01\x42\x00\xa0\x05\x00\x00\x00\x00\x00\x00", 12},
>> .... ], 4) = 4258
>>
>> If I ignore the first 12 bytes that were written, I end up with a 4246
>> byte packet, which matches the warning message:
>>
>> kernel: igb: caps=(0x0000000390114bb3, 0x0000000000000000) len=4246
>> data_len=4180 gso_size=1440 gso_type=5 ip_summed=0
>>
>> Looking at the code (
>> https://github.com/torvalds/linux/blob/68e370289c29e3beac99d59c6d840d470af9dfcf/drivers/net/tun.c#L1037
>> ) it seems that the tun device is expecting a virtio_net_hdr, but that
>> structure is only 10 bytes long (
>> http://lxr.free-electrons.com/source/include/uapi/linux/virtio_net.h#L73
>> ). I'm assuming the last two bytes are padding, because then the rest
>> of the structure decodes okay:
>>
>> flags = 0
>> gso_type = VIRTIO_NET_HDR_GSO_TCPV4
>> hdr_len = 66
>> gso_size = 1440
>> csum_start = 0
>> csum_offset = 0
>>
>> This matches what the warning message says, so I'm fairly confident in
>> it. If I decode the remainder of the write call (ignoring the 2 bytes
>> after the header), I'm left with a perfectly normal looking TCP packet
>> (with a 4180 byte payload).
>>
>> Looking at the packet itself, I see a valid IP checksum, and a valid TCP
>> checksum. So, it seems like FreeBSD is calculating the packet checksums
>> correctly, but I'm unsure of why Linux isn't noticing that. I thought
>> it might be related to VIRTIO_NET_HDR_F_DATA_VALID, but I can't seem to
>> find any uses of this that seem relevant (not that FreeBSD sets it anyway).
>>
>> Shouldn't the tun code be setting ip_summed after receiving a packet
>> with a valid checksum? It's not clear to me where ip_summed should be
>> getting set.
> You need VIRTIO_NET_HDR_F_NEEDS_CSUM, and to provide proper csum_start &
> csum_offset
>
Why? The packet doesn't need a checksum (it already has a valid one).
Does 'VIRTIO_NET_HDR_F_NEEDS_CSUM' not mean 'this packet needs a
checksum calculated'?
^ permalink raw reply
* Sending undersized ARP packets with VXLAN L3 interface
From: Martin Rusko @ 2014-08-27 17:06 UTC (permalink / raw)
To: netdev
I tried to use VXLAN interface as an L3 interface. Something like this:
ip link add name vxln7 \
type vxlan id 7007 group 232.1.42.7 \
local 10.7.12.250 dev vlan482 \
dstport 0 ageing 300
ip ad ad 192.168.3.200/24 brd + dev vxln7
ip li set vxln7 up
Now this doesn't work very well for small packets like those carrying
ARP protocol. Because resulting ethernet frames which are encapsulated
in VXLAN are not padded to minimum 64bytes required for Ethernet. Once
the inner frame traverse through any switch, it will get dropped as
undersized (runt) packet.
I'm wondering, where is the proper place to fix this. Should
arp_create() function allocate skb big enough to produce ethernet
frame with at least minimum size? Or is it somewhere in NIC drivers
where small packets are padded with zeros?
Regards,
Martin
^ permalink raw reply
* Re: skb_warn_bad_offload warnings with FreeBSD guests
From: Eric Dumazet @ 2014-08-27 16:44 UTC (permalink / raw)
To: Brian Rak; +Cc: Vlad Yasevich, netdev
In-Reply-To: <53FE02CC.50501@gameservers.com>
On Wed, 2014-08-27 at 12:09 -0400, Brian Rak wrote:
>
> I managed to intercept the raw packet + headers being delivered to the
> tun device, though I'm having some trouble making sense of it. I've got
> this call:
>
> writev(33, [{"\x00\x01\x42\x00\xa0\x05\x00\x00\x00\x00\x00\x00", 12},
> .... ], 4) = 4258
>
> If I ignore the first 12 bytes that were written, I end up with a 4246
> byte packet, which matches the warning message:
>
> kernel: igb: caps=(0x0000000390114bb3, 0x0000000000000000) len=4246
> data_len=4180 gso_size=1440 gso_type=5 ip_summed=0
>
> Looking at the code (
> https://github.com/torvalds/linux/blob/68e370289c29e3beac99d59c6d840d470af9dfcf/drivers/net/tun.c#L1037
> ) it seems that the tun device is expecting a virtio_net_hdr, but that
> structure is only 10 bytes long (
> http://lxr.free-electrons.com/source/include/uapi/linux/virtio_net.h#L73
> ). I'm assuming the last two bytes are padding, because then the rest
> of the structure decodes okay:
>
> flags = 0
> gso_type = VIRTIO_NET_HDR_GSO_TCPV4
> hdr_len = 66
> gso_size = 1440
> csum_start = 0
> csum_offset = 0
>
> This matches what the warning message says, so I'm fairly confident in
> it. If I decode the remainder of the write call (ignoring the 2 bytes
> after the header), I'm left with a perfectly normal looking TCP packet
> (with a 4180 byte payload).
>
> Looking at the packet itself, I see a valid IP checksum, and a valid TCP
> checksum. So, it seems like FreeBSD is calculating the packet checksums
> correctly, but I'm unsure of why Linux isn't noticing that. I thought
> it might be related to VIRTIO_NET_HDR_F_DATA_VALID, but I can't seem to
> find any uses of this that seem relevant (not that FreeBSD sets it anyway).
>
> Shouldn't the tun code be setting ip_summed after receiving a packet
> with a valid checksum? It's not clear to me where ip_summed should be
> getting set.
You need VIRTIO_NET_HDR_F_NEEDS_CSUM, and to provide proper csum_start &
csum_offset
^ permalink raw reply
* Re: skb_warn_bad_offload warnings with FreeBSD guests
From: Brian Rak @ 2014-08-27 16:09 UTC (permalink / raw)
To: Vlad Yasevich, netdev
In-Reply-To: <53FB4775.8020507@gmail.com>
On 8/25/2014 10:25 AM, Vlad Yasevich wrote:
> On 08/22/2014 12:19 PM, Brian Rak wrote:
>> We have a number of machines running qemu with bridged networking. We have noticed that
>> *sometimes* FreeBSD guests cause this warning to flood the host "WARNING: CPU: 5 PID: 3705
>> at net/core/dev.c:2238 skb_warn_bad_offload+0xc3/0xd0()". I haven't been able to come up
>> with any sort of reproduction steps, it just seems to happen to some FreeBSD guests, but
>> not others.
>>
>> A full stack trace looks like this:
>>
>> ------------[ cut here ]------------
>> WARNING: CPU: 1 PID: 7147 at net/core/dev.c:2233 skb_warn_bad_offload+0xc3/0xd0()
>> igb: caps=(0x0000000190114bb3, 0x0000000000000000) len=2962 data_len=0 gso_size=1448
>> gso_type=5 ip_summed=0
>> Modules linked in: dm_snapshot dm_bufio ipmi_devintf xt_physdev ebt_arp ebt_ip ebtable_nat
>> ebtables cls_fw sch_sfq sch_htb tun kvm_intel kvm 8021q garp nfnetlink_queue nfnetlink_log
>> nfnetlink bluetooth rfkill bridge stp llc xt_CHECKSUM iptable_mangle ipt_REJECT
>> iptable_filter ip
>> _tables ip6t_REJECT ip6table_filter ip6_tables ipv6 iTCO_wdt iTCO_vendor_support ipmi_si
>> ipmi_msghandler microcode pcspkr i2c_i801 joydev sg lpc_ich shpchp igb dca ptp pps_core
>> hwmon ext4 jbd2 mbcache sd_mod crc_t10dif crct10dif_common video ahci libahci xhci_hcd ast
>> ttm drm_kms
>> _helper sysimgblt sysfillrect syscopyarea dm_mirror dm_region_hash dm_log dm_mod
>> CPU: 1 PID: 7147 Comm: qemu-kvm Tainted: G W 3.15.5-1.el6.elrepo.x86_64 #1
>> Hardware name: Supermicro X10SLE-F/HF/X10SLE, BIOS 1.1 07/19/2013
>> 00000000000008b9 ffff88081fc435d8 ffffffff8163ba90 00000000000008b9
>> ffff88081fc43628 ffff88081fc43618 ffffffff8106c30c ffffc90007a06e30
>> 0000000000000000 ffff8807f2b64000 ffff8807f2b64000 0000000000000000
>> Call Trace:
>> <IRQ> [<ffffffff8163ba90>] dump_stack+0x49/0x61
>> [<ffffffff8106c30c>] warn_slowpath_common+0x8c/0xc0
>> [<ffffffff8106c3f6>] warn_slowpath_fmt+0x46/0x50
>> [<ffffffff8156ce93>] skb_warn_bad_offload+0xc3/0xd0
>> [<ffffffff81574a29>] ? dev_hard_start_xmit+0x339/0x640
>> [<ffffffff81574699>] __skb_gso_segment+0x89/0xe0
>> [<ffffffff81574876>] dev_hard_start_xmit+0x186/0x640
>> [<ffffffff81594f5a>] sch_direct_xmit+0xfa/0x1d0
>> [<ffffffff81574f2f>] __dev_queue_xmit+0x1ff/0x4f0
>> [<ffffffff81575240>] dev_queue_xmit+0x10/0x20
>> [<ffffffffa02e6612>] br_dev_queue_push_xmit+0x82/0xb0 [bridge]
>> [<ffffffffa02ee680>] br_nf_dev_queue_xmit+0x20/0x90 [bridge]
>> [<ffffffffa02ef4b8>] br_nf_post_routing+0x2d8/0x300 [bridge]
>> [<ffffffffa02e6590>] ? deliver_clone+0x60/0x60 [bridge]
>> [<ffffffff815a357e>] nf_iterate+0x8e/0xc0
>> [<ffffffffa02e6590>] ? deliver_clone+0x60/0x60 [bridge]
>> [<ffffffff815a37ad>] nf_hook_slow+0x7d/0x150
>> [<ffffffffa02e6590>] ? deliver_clone+0x60/0x60 [bridge]
>> [<ffffffffa02ee6f0>] ? br_nf_dev_queue_xmit+0x90/0x90 [bridge]
>> [<ffffffffa02e6b43>] br_forward_finish+0x43/0x60 [bridge]
>> [<ffffffffa02ee8a8>] br_nf_forward_finish+0x1b8/0x1d0 [bridge]
>> [<ffffffffa02ef178>] br_nf_forward_ip+0x3a8/0x410 [bridge]
>> [<ffffffffa02e6b00>] ? br_flood_deliver+0x20/0x20 [bridge]
>> [<ffffffff815a357e>] nf_iterate+0x8e/0xc0
>> [<ffffffffa02e6b00>] ? br_flood_deliver+0x20/0x20 [bridge]
>> [<ffffffff815a37ad>] nf_hook_slow+0x7d/0x150
>> [<ffffffffa02e6b00>] ? br_flood_deliver+0x20/0x20 [bridge]
>> [<ffffffffa02e66e4>] __br_forward+0xa4/0x100 [bridge]
>> [<ffffffffa02e7800>] ? NF_HOOK.clone.0+0x70/0x70 [bridge]
>> [<ffffffffa02e67d6>] br_forward+0x96/0xb0 [bridge]
>> [<ffffffffa02e7800>] ? NF_HOOK.clone.0+0x70/0x70 [bridge]
>> [<ffffffffa02e7997>] br_handle_frame_finish+0x197/0x3f0 [bridge]
>> [<ffffffffa02e7800>] ? NF_HOOK.clone.0+0x70/0x70 [bridge]
>> [<ffffffffa02ef790>] br_nf_pre_routing_finish+0x2b0/0x370 [bridge]
>> [<ffffffffa02ef4e0>] ? br_nf_post_routing+0x300/0x300 [bridge]
>> [<ffffffffa02ed986>] NF_HOOK_THRESH+0x56/0x60 [bridge]
>> [<ffffffffa02eed2b>] br_nf_pre_routing+0x2fb/0x3a0 [bridge]
>> [<ffffffff815a357e>] nf_iterate+0x8e/0xc0
>> [<ffffffffa02e7800>] ? NF_HOOK.clone.0+0x70/0x70 [bridge]
>> [<ffffffff815a37ad>] nf_hook_slow+0x7d/0x150
>> [<ffffffffa02e7800>] ? NF_HOOK.clone.0+0x70/0x70 [bridge]
>> [<ffffffffa02e7d8c>] br_handle_frame+0x19c/0x240 [bridge]
>> [<ffffffffa02e7bf0>] ? br_handle_frame_finish+0x3f0/0x3f0 [bridge]
>> [<ffffffff81572fa5>] __netif_receive_skb_core+0x1e5/0x620
>> [<ffffffff81573407>] __netif_receive_skb+0x27/0x70
>> [<ffffffff81573553>] process_backlog+0x103/0x200
>> [<ffffffff81573d62>] net_rx_action+0x112/0x2a0
>> [<ffffffff8107111c>] __do_softirq+0xfc/0x2b0
>> [<ffffffff810713cd>] ? irq_exit+0xad/0xd0
>> [<ffffffff8164a81c>] do_softirq_own_stack+0x1c/0x30
>> <EOI> [<ffffffff81070e75>] do_softirq+0x55/0x60
>> [<ffffffff81571e19>] netif_rx_ni+0x39/0x70
>> [<ffffffffa03e84e0>] tun_get_user+0x310/0x6c0 [tun]
>> [<ffffffffa03e8995>] tun_chr_aio_write+0x85/0xa0 [tun]
>> [<ffffffff811beb9d>] do_sync_readv_writev+0x4d/0x80
>> [<ffffffff811c0128>] do_readv_writev+0xc8/0x2c0
>> [<ffffffff811bebd0>] ? do_sync_readv_writev+0x80/0x80
>> [<ffffffff811d2c45>] ? poll_select_set_timeout+0x95/0xb0
>> [<ffffffff811c0357>] vfs_writev+0x37/0x50
>> [<ffffffff811c0496>] SyS_writev+0x56/0xf0
>> [<ffffffff81648ee9>] system_call_fastpath+0x16/0x1b
>> ---[ end trace d26e70ba037ab631 ]---
>>
>>
>> gso_type=5 and ip_summed=0 are always the same (though len, data_len, and gso_size vary).
>>
>> What is causing this?
> The reason that the warning is triggered is ip_summed = 0 which means there is not
> checksum already in the packet and it needs to be calculated. If the packet is GSO,
> then it needs to have partial checksum set (ip_summed == 3).
>
> You might try using systemtap or instrumenting tun and bridge to see what the
> ip_summed value is when this happens.
Who needs systemtap when you have strace ;)
I managed to intercept the raw packet + headers being delivered to the
tun device, though I'm having some trouble making sense of it. I've got
this call:
writev(33, [{"\x00\x01\x42\x00\xa0\x05\x00\x00\x00\x00\x00\x00", 12},
.... ], 4) = 4258
If I ignore the first 12 bytes that were written, I end up with a 4246
byte packet, which matches the warning message:
kernel: igb: caps=(0x0000000390114bb3, 0x0000000000000000) len=4246
data_len=4180 gso_size=1440 gso_type=5 ip_summed=0
Looking at the code (
https://github.com/torvalds/linux/blob/68e370289c29e3beac99d59c6d840d470af9dfcf/drivers/net/tun.c#L1037
) it seems that the tun device is expecting a virtio_net_hdr, but that
structure is only 10 bytes long (
http://lxr.free-electrons.com/source/include/uapi/linux/virtio_net.h#L73
). I'm assuming the last two bytes are padding, because then the rest
of the structure decodes okay:
flags = 0
gso_type = VIRTIO_NET_HDR_GSO_TCPV4
hdr_len = 66
gso_size = 1440
csum_start = 0
csum_offset = 0
This matches what the warning message says, so I'm fairly confident in
it. If I decode the remainder of the write call (ignoring the 2 bytes
after the header), I'm left with a perfectly normal looking TCP packet
(with a 4180 byte payload).
Looking at the packet itself, I see a valid IP checksum, and a valid TCP
checksum. So, it seems like FreeBSD is calculating the packet checksums
correctly, but I'm unsure of why Linux isn't noticing that. I thought
it might be related to VIRTIO_NET_HDR_F_DATA_VALID, but I can't seem to
find any uses of this that seem relevant (not that FreeBSD sets it anyway).
Shouldn't the tun code be setting ip_summed after receiving a packet
with a valid checksum? It's not clear to me where ip_summed should be
getting set.
^ permalink raw reply
* [PATCH ipsec-next v3 2/2] xfrm: configure policy hash table thresholds by netlink
From: Christophe Gouault @ 2014-08-27 15:48 UTC (permalink / raw)
To: Steffen Klassert, David S. Miller; +Cc: netdev, Christophe Gouault
In-Reply-To: <1409154495-1343-1-git-send-email-christophe.gouault@6wind.com>
Enable to specify local and remote prefix length thresholds for the
policy hash table via a netlink XFRM_MSG_NEWSPDINFO message.
prefix length thresholds are specified by XFRMA_SPD_IPV4_HTHRESH and
XFRMA_SPD_IPV6_HTHRESH optional attributes (struct xfrmu_spdhthresh).
example:
struct xfrmu_spdhthresh thresh4 = {
.lbits = 0;
.rbits = 24;
};
struct xfrmu_spdhthresh thresh6 = {
.lbits = 0;
.rbits = 56;
};
struct nlmsghdr *hdr;
struct nl_msg *msg;
msg = nlmsg_alloc();
hdr = nlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, XFRMA_SPD_IPV4_HTHRESH, sizeof(__u32), NLM_F_REQUEST);
nla_put(msg, XFRMA_SPD_IPV4_HTHRESH, sizeof(thresh4), &thresh4);
nla_put(msg, XFRMA_SPD_IPV6_HTHRESH, sizeof(thresh6), &thresh6);
nla_send_auto(sk, msg);
The numbers are the policy selector minimum prefix lengths to put a
policy in the hash table.
- lbits is the local threshold (source address for out policies,
destination address for in and fwd policies).
- rbits is the remote threshold (destination address for out
policies, source address for in and fwd policies).
The default values are:
XFRMA_SPD_IPV4_HTHRESH: 32 32
XFRMA_SPD_IPV6_HTHRESH: 128 128
Dynamic re-building of the SPD is performed when the thresholds values
are changed.
The current thresholds can be read via a XFRM_MSG_GETSPDINFO request:
the kernel replies to XFRM_MSG_GETSPDINFO requests by an
XFRM_MSG_NEWSPDINFO message, with both attributes
XFRMA_SPD_IPV4_HTHRESH and XFRMA_SPD_IPV6_HTHRESH.
Signed-off-by: Christophe Gouault <christophe.gouault@6wind.com>
---
include/net/netns/xfrm.h | 10 ++++++
include/net/xfrm.h | 1 +
include/uapi/linux/xfrm.h | 7 ++++
net/xfrm/xfrm_policy.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++
net/xfrm/xfrm_user.c | 83 ++++++++++++++++++++++++++++++++++++++++++--
5 files changed, 185 insertions(+), 3 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 41902a8..9da7982 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -19,6 +19,15 @@ struct xfrm_policy_hash {
u8 sbits6;
};
+struct xfrm_policy_hthresh {
+ struct work_struct work;
+ seqlock_t lock;
+ u8 lbits4;
+ u8 rbits4;
+ u8 lbits6;
+ u8 rbits6;
+};
+
struct netns_xfrm {
struct list_head state_all;
/*
@@ -45,6 +54,7 @@ struct netns_xfrm {
struct xfrm_policy_hash policy_bydst[XFRM_POLICY_MAX * 2];
unsigned int policy_count[XFRM_POLICY_MAX * 2];
struct work_struct policy_hash_work;
+ struct xfrm_policy_hthresh policy_hthresh;
struct sock *nlsk;
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 721e9c3..dc4865e 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1591,6 +1591,7 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(struct net *net, u32 mark,
struct xfrm_policy *xfrm_policy_byid(struct net *net, u32 mark, u8, int dir,
u32 id, int delete, int *err);
int xfrm_policy_flush(struct net *net, u8 type, bool task_valid);
+void xfrm_policy_hash_rebuild(struct net *net);
u32 xfrm_get_acqseq(void);
int verify_spi_info(u8 proto, u32 min, u32 max);
int xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi);
diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
index 25e5dd9..02d5125 100644
--- a/include/uapi/linux/xfrm.h
+++ b/include/uapi/linux/xfrm.h
@@ -328,6 +328,8 @@ enum xfrm_spdattr_type_t {
XFRMA_SPD_UNSPEC,
XFRMA_SPD_INFO,
XFRMA_SPD_HINFO,
+ XFRMA_SPD_IPV4_HTHRESH,
+ XFRMA_SPD_IPV6_HTHRESH,
__XFRMA_SPD_MAX
#define XFRMA_SPD_MAX (__XFRMA_SPD_MAX - 1)
@@ -347,6 +349,11 @@ struct xfrmu_spdhinfo {
__u32 spdhmcnt;
};
+struct xfrmu_spdhthresh {
+ __u8 lbits;
+ __u8 rbits;
+};
+
struct xfrm_usersa_info {
struct xfrm_selector sel;
struct xfrm_id id;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e6ff7b4..55bcb86 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -566,6 +566,86 @@ static void xfrm_hash_resize(struct work_struct *work)
mutex_unlock(&hash_resize_mutex);
}
+static void xfrm_hash_rebuild(struct work_struct *work)
+{
+ struct net *net = container_of(work, struct net,
+ xfrm.policy_hthresh.work);
+ unsigned int hmask;
+ struct xfrm_policy *pol;
+ struct xfrm_policy *policy;
+ struct hlist_head *chain;
+ struct hlist_head *odst;
+ struct hlist_node *newpos;
+ int i;
+ int dir;
+ unsigned seq;
+ u8 lbits4, rbits4, lbits6, rbits6;
+
+ mutex_lock(&hash_resize_mutex);
+
+ /* read selector prefixlen thresholds */
+ do {
+ seq = read_seqbegin(&net->xfrm.policy_hthresh.lock);
+
+ lbits4 = net->xfrm.policy_hthresh.lbits4;
+ rbits4 = net->xfrm.policy_hthresh.rbits4;
+ lbits6 = net->xfrm.policy_hthresh.lbits6;
+ rbits6 = net->xfrm.policy_hthresh.rbits6;
+ } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq));
+
+ write_lock_bh(&net->xfrm.xfrm_policy_lock);
+
+ /* reset the bydst and inexact table in all directions */
+ for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {
+ INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
+ hmask = net->xfrm.policy_bydst[dir].hmask;
+ odst = net->xfrm.policy_bydst[dir].table;
+ for (i = hmask; i >= 0; i--)
+ INIT_HLIST_HEAD(odst + i);
+ if ((dir & XFRM_POLICY_MASK) == XFRM_POLICY_OUT) {
+ /* dir out => dst = remote, src = local */
+ net->xfrm.policy_bydst[dir].dbits4 = rbits4;
+ net->xfrm.policy_bydst[dir].sbits4 = lbits4;
+ net->xfrm.policy_bydst[dir].dbits6 = rbits6;
+ net->xfrm.policy_bydst[dir].sbits6 = lbits6;
+ } else {
+ /* dir in/fwd => dst = local, src = remote */
+ net->xfrm.policy_bydst[dir].dbits4 = lbits4;
+ net->xfrm.policy_bydst[dir].sbits4 = rbits4;
+ net->xfrm.policy_bydst[dir].dbits6 = lbits6;
+ net->xfrm.policy_bydst[dir].sbits6 = rbits6;
+ }
+ }
+
+ /* re-insert all policies by order of creation */
+ list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
+ newpos = NULL;
+ chain = policy_hash_bysel(net, &policy->selector,
+ policy->family,
+ xfrm_policy_id2dir(policy->index));
+ hlist_for_each_entry(pol, chain, bydst) {
+ if (policy->priority >= pol->priority)
+ newpos = &pol->bydst;
+ else
+ break;
+ }
+ if (newpos)
+ hlist_add_behind(&policy->bydst, newpos);
+ else
+ hlist_add_head(&policy->bydst, chain);
+ }
+
+ write_unlock_bh(&net->xfrm.xfrm_policy_lock);
+
+ mutex_unlock(&hash_resize_mutex);
+}
+
+void xfrm_policy_hash_rebuild(struct net *net)
+{
+ schedule_work(&net->xfrm.policy_hthresh.work);
+}
+EXPORT_SYMBOL(xfrm_policy_hash_rebuild);
+
/* Generate new index... KAME seems to generate them ordered by cost
* of an absolute inpredictability of ordering of rules. This will not pass. */
static u32 xfrm_gen_index(struct net *net, int dir, u32 index)
@@ -2872,9 +2952,16 @@ static int __net_init xfrm_policy_init(struct net *net)
htab->dbits6 = 128;
htab->sbits6 = 128;
}
+ net->xfrm.policy_hthresh.lbits4 = 32;
+ net->xfrm.policy_hthresh.rbits4 = 32;
+ net->xfrm.policy_hthresh.lbits6 = 128;
+ net->xfrm.policy_hthresh.rbits6 = 128;
+
+ seqlock_init(&net->xfrm.policy_hthresh.lock);
INIT_LIST_HEAD(&net->xfrm.policy_all);
INIT_WORK(&net->xfrm.policy_hash_work, xfrm_hash_resize);
+ INIT_WORK(&net->xfrm.policy_hthresh.work, xfrm_hash_rebuild);
if (net_eq(net, &init_net))
register_netdevice_notifier(&xfrm_dev_notifier);
return 0;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index d4db6eb..c6a7f44 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -964,7 +964,9 @@ static inline size_t xfrm_spdinfo_msgsize(void)
{
return NLMSG_ALIGN(4)
+ nla_total_size(sizeof(struct xfrmu_spdinfo))
- + nla_total_size(sizeof(struct xfrmu_spdhinfo));
+ + nla_total_size(sizeof(struct xfrmu_spdhinfo))
+ + nla_total_size(sizeof(struct xfrmu_spdhthresh))
+ + nla_total_size(sizeof(struct xfrmu_spdhthresh));
}
static int build_spdinfo(struct sk_buff *skb, struct net *net,
@@ -973,9 +975,11 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net,
struct xfrmk_spdinfo si;
struct xfrmu_spdinfo spc;
struct xfrmu_spdhinfo sph;
+ struct xfrmu_spdhthresh spt4, spt6;
struct nlmsghdr *nlh;
int err;
u32 *f;
+ unsigned lseq;
nlh = nlmsg_put(skb, portid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0);
if (nlh == NULL) /* shouldn't really happen ... */
@@ -993,9 +997,22 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net,
sph.spdhcnt = si.spdhcnt;
sph.spdhmcnt = si.spdhmcnt;
+ do {
+ lseq = read_seqbegin(&net->xfrm.policy_hthresh.lock);
+
+ spt4.lbits = net->xfrm.policy_hthresh.lbits4;
+ spt4.rbits = net->xfrm.policy_hthresh.rbits4;
+ spt6.lbits = net->xfrm.policy_hthresh.lbits6;
+ spt6.rbits = net->xfrm.policy_hthresh.rbits6;
+ } while (read_seqretry(&net->xfrm.policy_hthresh.lock, lseq));
+
err = nla_put(skb, XFRMA_SPD_INFO, sizeof(spc), &spc);
if (!err)
err = nla_put(skb, XFRMA_SPD_HINFO, sizeof(sph), &sph);
+ if (!err)
+ err = nla_put(skb, XFRMA_SPD_IPV4_HTHRESH, sizeof(spt4), &spt4);
+ if (!err)
+ err = nla_put(skb, XFRMA_SPD_IPV6_HTHRESH, sizeof(spt6), &spt6);
if (err) {
nlmsg_cancel(skb, nlh);
return err;
@@ -1004,6 +1021,54 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net,
return nlmsg_end(skb, nlh);
}
+static int xfrm_set_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
+ struct nlattr **attrs)
+{
+ struct net *net = sock_net(skb->sk);
+ u32 *flags = nlmsg_data(nlh);
+ u32 sportid = NETLINK_CB(skb).portid;
+ u32 seq = nlh->nlmsg_seq;
+ struct xfrmu_spdhthresh *thresh4 = NULL;
+ struct xfrmu_spdhthresh *thresh6 = NULL;
+
+ /* selector prefixlen thresholds to hash policies */
+ if (attrs[XFRMA_SPD_IPV4_HTHRESH]) {
+ struct nlattr *rta = attrs[XFRMA_SPD_IPV4_HTHRESH];
+
+ if (nla_len(rta) < sizeof(*thresh4))
+ return -EINVAL;
+ thresh4 = nla_data(rta);
+ if (thresh4->lbits > 32 || thresh4->rbits > 32)
+ return -EINVAL;
+ }
+ if (attrs[XFRMA_SPD_IPV6_HTHRESH]) {
+ struct nlattr *rta = attrs[XFRMA_SPD_IPV6_HTHRESH];
+
+ if (nla_len(rta) < sizeof(*thresh6))
+ return -EINVAL;
+ thresh6 = nla_data(rta);
+ if (thresh6->lbits > 128 || thresh6->rbits > 128)
+ return -EINVAL;
+ }
+
+ if (thresh4 || thresh6) {
+ write_seqlock(&net->xfrm.policy_hthresh.lock);
+ if (thresh4) {
+ net->xfrm.policy_hthresh.lbits4 = thresh4->lbits;
+ net->xfrm.policy_hthresh.rbits4 = thresh4->rbits;
+ }
+ if (thresh6) {
+ net->xfrm.policy_hthresh.lbits6 = thresh6->lbits;
+ net->xfrm.policy_hthresh.rbits6 = thresh6->rbits;
+ }
+ write_sequnlock(&net->xfrm.policy_hthresh.lock);
+
+ xfrm_policy_hash_rebuild(net);
+ }
+
+ return 0;
+}
+
static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
struct nlattr **attrs)
{
@@ -2274,6 +2339,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
[XFRM_MSG_REPORT - XFRM_MSG_BASE] = XMSGSIZE(xfrm_user_report),
[XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = XMSGSIZE(xfrm_userpolicy_id),
[XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = sizeof(u32),
+ [XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = sizeof(u32),
[XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = sizeof(u32),
};
@@ -2308,10 +2374,17 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
[XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) },
};
+static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
+ [XFRMA_SPD_IPV4_HTHRESH] = { .len = sizeof(struct xfrmu_spdhthresh) },
+ [XFRMA_SPD_IPV6_HTHRESH] = { .len = sizeof(struct xfrmu_spdhthresh) },
+};
+
static const struct xfrm_link {
int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
int (*dump)(struct sk_buff *, struct netlink_callback *);
int (*done)(struct netlink_callback *);
+ const struct nla_policy *nla_pol;
+ int nla_max;
} xfrm_dispatch[XFRM_NR_MSGTYPES] = {
[XFRM_MSG_NEWSA - XFRM_MSG_BASE] = { .doit = xfrm_add_sa },
[XFRM_MSG_DELSA - XFRM_MSG_BASE] = { .doit = xfrm_del_sa },
@@ -2335,6 +2408,9 @@ static const struct xfrm_link {
[XFRM_MSG_GETAE - XFRM_MSG_BASE] = { .doit = xfrm_get_ae },
[XFRM_MSG_MIGRATE - XFRM_MSG_BASE] = { .doit = xfrm_do_migrate },
[XFRM_MSG_GETSADINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_sadinfo },
+ [XFRM_MSG_NEWSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_set_spdinfo,
+ .nla_pol = xfrma_spd_policy,
+ .nla_max = XFRMA_SPD_MAX },
[XFRM_MSG_GETSPDINFO - XFRM_MSG_BASE] = { .doit = xfrm_get_spdinfo },
};
@@ -2371,8 +2447,9 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
}
}
- err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs, XFRMA_MAX,
- xfrma_policy);
+ err = nlmsg_parse(nlh, xfrm_msg_min[type], attrs,
+ link->nla_max ? : XFRMA_MAX,
+ link->nla_pol ? : xfrma_policy);
if (err < 0)
return err;
--
1.9.1
^ permalink raw reply related
* [PATCH ipsec-next v3 1/2] xfrm: hash prefixed policies based on preflen thresholds
From: Christophe Gouault @ 2014-08-27 15:48 UTC (permalink / raw)
To: Steffen Klassert, David S. Miller; +Cc: netdev, Christophe Gouault
In-Reply-To: <1409154495-1343-1-git-send-email-christophe.gouault@6wind.com>
The idea is an extension of the current policy hashing.
Today only non-prefixed policies are stored in a hash table. This
patch relaxes the constraints, and hashes policies whose prefix
lengths are greater or equal to a configurable threshold.
Each hash table (one per direction) maintains its own set of IPv4 and
IPv6 thresholds (dbits4, sbits4, dbits6, sbits6), by default (32, 32,
128, 128).
Example, if the output hash table is configured with values (16, 24,
56, 64):
ip xfrm policy add dir out src 10.22.0.0/20 dst 10.24.1.0/24 ... => hashed
ip xfrm policy add dir out src 10.22.0.0/16 dst 10.24.1.1/32 ... => hashed
ip xfrm policy add dir out src 10.22.0.0/16 dst 10.24.0.0/16 ... => unhashed
ip xfrm policy add dir out \
src 3ffe:304:124:2200::/60 dst 3ffe:304:124:2401::/64 ... => hashed
ip xfrm policy add dir out \
src 3ffe:304:124:2200::/56 dst 3ffe:304:124:2401::2/128 ... => hashed
ip xfrm policy add dir out \
src 3ffe:304:124:2200::/56 dst 3ffe:304:124:2400::/56 ... => unhashed
The high order bits of the addresses (up to the threshold) are used to
compute the hash key.
Signed-off-by: Christophe Gouault <christophe.gouault@6wind.com>
---
include/net/netns/xfrm.h | 4 +++
net/xfrm/xfrm_hash.h | 76 +++++++++++++++++++++++++++++++++++++++++-------
net/xfrm/xfrm_policy.c | 53 +++++++++++++++++++++++++++++----
3 files changed, 117 insertions(+), 16 deletions(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 3492434..41902a8 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -13,6 +13,10 @@ struct ctl_table_header;
struct xfrm_policy_hash {
struct hlist_head *table;
unsigned int hmask;
+ u8 dbits4;
+ u8 sbits4;
+ u8 dbits6;
+ u8 sbits6;
};
struct netns_xfrm {
diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h
index 0622d31..666c5ff 100644
--- a/net/xfrm/xfrm_hash.h
+++ b/net/xfrm/xfrm_hash.h
@@ -3,6 +3,7 @@
#include <linux/xfrm.h>
#include <linux/socket.h>
+#include <linux/jhash.h>
static inline unsigned int __xfrm4_addr_hash(const xfrm_address_t *addr)
{
@@ -28,6 +29,58 @@ static inline unsigned int __xfrm6_daddr_saddr_hash(const xfrm_address_t *daddr,
saddr->a6[2] ^ saddr->a6[3]);
}
+static inline u32 __bits2mask32(__u8 bits)
+{
+ u32 mask32 = 0xffffffff;
+
+ if (bits == 0)
+ mask32 = 0;
+ else if (bits < 32)
+ mask32 <<= (32 - bits);
+
+ return mask32;
+}
+
+static inline unsigned int __xfrm4_dpref_spref_hash(const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr,
+ __u8 dbits,
+ __u8 sbits)
+{
+ return jhash_2words(ntohl(daddr->a4) & __bits2mask32(dbits),
+ ntohl(saddr->a4) & __bits2mask32(sbits),
+ 0);
+}
+
+static inline unsigned int __xfrm6_pref_hash(const xfrm_address_t *addr,
+ __u8 prefixlen)
+{
+ int pdw;
+ int pbi;
+ u32 initval = 0;
+
+ pdw = prefixlen >> 5; /* num of whole u32 in prefix */
+ pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */
+
+ if (pbi) {
+ __be32 mask;
+
+ mask = htonl((0xffffffff) << (32 - pbi));
+
+ initval = (__force u32)(addr->a6[pdw] & mask);
+ }
+
+ return jhash2((__force u32 *)addr->a6, pdw, initval);
+}
+
+static inline unsigned int __xfrm6_dpref_spref_hash(const xfrm_address_t *daddr,
+ const xfrm_address_t *saddr,
+ __u8 dbits,
+ __u8 sbits)
+{
+ return __xfrm6_pref_hash(daddr, dbits) ^
+ __xfrm6_pref_hash(saddr, sbits);
+}
+
static inline unsigned int __xfrm_dst_hash(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
u32 reqid, unsigned short family,
@@ -84,7 +137,8 @@ static inline unsigned int __idx_hash(u32 index, unsigned int hmask)
}
static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
- unsigned short family, unsigned int hmask)
+ unsigned short family, unsigned int hmask,
+ u8 dbits, u8 sbits)
{
const xfrm_address_t *daddr = &sel->daddr;
const xfrm_address_t *saddr = &sel->saddr;
@@ -92,19 +146,19 @@ static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
switch (family) {
case AF_INET:
- if (sel->prefixlen_d != 32 ||
- sel->prefixlen_s != 32)
+ if (sel->prefixlen_d < dbits ||
+ sel->prefixlen_s < sbits)
return hmask + 1;
- h = __xfrm4_daddr_saddr_hash(daddr, saddr);
+ h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
case AF_INET6:
- if (sel->prefixlen_d != 128 ||
- sel->prefixlen_s != 128)
+ if (sel->prefixlen_d < dbits ||
+ sel->prefixlen_s < sbits)
return hmask + 1;
- h = __xfrm6_daddr_saddr_hash(daddr, saddr);
+ h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
}
h ^= (h >> 16);
@@ -113,17 +167,19 @@ static inline unsigned int __sel_hash(const struct xfrm_selector *sel,
static inline unsigned int __addr_hash(const xfrm_address_t *daddr,
const xfrm_address_t *saddr,
- unsigned short family, unsigned int hmask)
+ unsigned short family,
+ unsigned int hmask,
+ u8 dbits, u8 sbits)
{
unsigned int h = 0;
switch (family) {
case AF_INET:
- h = __xfrm4_daddr_saddr_hash(daddr, saddr);
+ h = __xfrm4_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
case AF_INET6:
- h = __xfrm6_daddr_saddr_hash(daddr, saddr);
+ h = __xfrm6_dpref_spref_hash(daddr, saddr, dbits, sbits);
break;
}
h ^= (h >> 16);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index beeed60..e6ff7b4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -344,12 +344,39 @@ static inline unsigned int idx_hash(struct net *net, u32 index)
return __idx_hash(index, net->xfrm.policy_idx_hmask);
}
+/* calculate policy hash thresholds */
+static void __get_hash_thresh(struct net *net,
+ unsigned short family, int dir,
+ u8 *dbits, u8 *sbits)
+{
+ switch (family) {
+ case AF_INET:
+ *dbits = net->xfrm.policy_bydst[dir].dbits4;
+ *sbits = net->xfrm.policy_bydst[dir].sbits4;
+ break;
+
+ case AF_INET6:
+ *dbits = net->xfrm.policy_bydst[dir].dbits6;
+ *sbits = net->xfrm.policy_bydst[dir].sbits6;
+ break;
+
+ default:
+ *dbits = 0;
+ *sbits = 0;
+ }
+}
+
static struct hlist_head *policy_hash_bysel(struct net *net,
const struct xfrm_selector *sel,
unsigned short family, int dir)
{
unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
- unsigned int hash = __sel_hash(sel, family, hmask);
+ unsigned int hash;
+ u8 dbits;
+ u8 sbits;
+
+ __get_hash_thresh(net, family, dir, &dbits, &sbits);
+ hash = __sel_hash(sel, family, hmask, dbits, sbits);
return (hash == hmask + 1 ?
&net->xfrm.policy_inexact[dir] :
@@ -362,25 +389,35 @@ static struct hlist_head *policy_hash_direct(struct net *net,
unsigned short family, int dir)
{
unsigned int hmask = net->xfrm.policy_bydst[dir].hmask;
- unsigned int hash = __addr_hash(daddr, saddr, family, hmask);
+ unsigned int hash;
+ u8 dbits;
+ u8 sbits;
+
+ __get_hash_thresh(net, family, dir, &dbits, &sbits);
+ hash = __addr_hash(daddr, saddr, family, hmask, dbits, sbits);
return net->xfrm.policy_bydst[dir].table + hash;
}
-static void xfrm_dst_hash_transfer(struct hlist_head *list,
+static void xfrm_dst_hash_transfer(struct net *net,
+ struct hlist_head *list,
struct hlist_head *ndsttable,
- unsigned int nhashmask)
+ unsigned int nhashmask,
+ int dir)
{
struct hlist_node *tmp, *entry0 = NULL;
struct xfrm_policy *pol;
unsigned int h0 = 0;
+ u8 dbits;
+ u8 sbits;
redo:
hlist_for_each_entry_safe(pol, tmp, list, bydst) {
unsigned int h;
+ __get_hash_thresh(net, pol->family, dir, &dbits, &sbits);
h = __addr_hash(&pol->selector.daddr, &pol->selector.saddr,
- pol->family, nhashmask);
+ pol->family, nhashmask, dbits, sbits);
if (!entry0) {
hlist_del(&pol->bydst);
hlist_add_head(&pol->bydst, ndsttable+h);
@@ -434,7 +471,7 @@ static void xfrm_bydst_resize(struct net *net, int dir)
write_lock_bh(&net->xfrm.xfrm_policy_lock);
for (i = hmask; i >= 0; i--)
- xfrm_dst_hash_transfer(odst + i, ndst, nhashmask);
+ xfrm_dst_hash_transfer(net, odst + i, ndst, nhashmask, dir);
net->xfrm.policy_bydst[dir].table = ndst;
net->xfrm.policy_bydst[dir].hmask = nhashmask;
@@ -2830,6 +2867,10 @@ static int __net_init xfrm_policy_init(struct net *net)
if (!htab->table)
goto out_bydst;
htab->hmask = hmask;
+ htab->dbits4 = 32;
+ htab->sbits4 = 32;
+ htab->dbits6 = 128;
+ htab->sbits6 = 128;
}
INIT_LIST_HEAD(&net->xfrm.policy_all);
--
1.9.1
^ permalink raw reply related
* [PATCH ipsec-next v3 0/2] xfrm: scalability enhancements for policy database
From: Christophe Gouault @ 2014-08-27 15:48 UTC (permalink / raw)
To: Steffen Klassert, David S. Miller; +Cc: netdev
In-Reply-To: <20140821060944.GC6390@secunet.com>
This patchset enables to hash more policies than just non-prefixed
ones: hash policies whose prefix lengths are greater or equal to
configurable thresholds.
These thresholds are configured via netlink message
XFRM_MSG_NEWSPDINFO, attributes XFRMA_SPD_IPV4_HTHRESH and
XFRMA_SPD_IPV6_HTHRESH.
The related iproute2 patch for configuring the thresholds is available
on demand.
Best Regards,
Christophe
----
v2:
- change configuration API from proc to netlink
v3:
- initialize xfrm_policy_hthresh lock
- remove "rebuilding SPD hash table" log
- replace deprecated hlist_add_after by hlist_add_behind
- remove netlink reply to XFRM_MSG_NEWSPDINFO request
---
include/net/netns/xfrm.h | 14 +++++++
include/net/xfrm.h | 1 +
include/uapi/linux/xfrm.h | 7 ++++
net/xfrm/xfrm_hash.h | 76 +++++++++++++++++++++++++++++++-----
net/xfrm/xfrm_policy.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++
net/xfrm/xfrm_user.c | 83 +++++++++++++++++++++++++++++++++++++--
6 files changed, 302 insertions(+), 19 deletions(-)
^ permalink raw reply
* Re: [PATCH v2] ethernet: arc: Add support for Rockchip SoC layer device tree bindings
From: PERIER Romain @ 2014-08-27 15:28 UTC (permalink / raw)
To: Heiko Stübner
Cc: linux-rockchip, linux-arm-kernel, netdev, Arnd Bergmann
In-Reply-To: <1409122527-17673-1-git-send-email-romain.perier@gmail.com>
This patch is the continuity of "[PATCH v4,3/3] ethernet: arc: Add
support for specific SoC layer device tree bindings", it should be
applied after this one.
2014-08-27 8:55 GMT+02:00 Romain Perier <romain.perier@gmail.com>:
> This patch defines a platform glue layer for Rockchip SoCs which
> support arc-emac driver. It ensures that regulator for the rmii is on
> before trying to connect to the ethernet controller. It applies right
> speed and mode changes to the grf when ethernet settings change.
>
> Signed-off-by: Romain Perier <romain.perier@gmail.com>
> ---
> drivers/net/ethernet/arc/Kconfig | 15 +++
> drivers/net/ethernet/arc/Makefile | 1 +
> drivers/net/ethernet/arc/emac.h | 2 +
> drivers/net/ethernet/arc/emac_main.c | 2 +
> drivers/net/ethernet/arc/emac_rockchip.c | 224 +++++++++++++++++++++++++++++++
> 5 files changed, 244 insertions(+)
> create mode 100644 drivers/net/ethernet/arc/emac_rockchip.c
>
> diff --git a/drivers/net/ethernet/arc/Kconfig b/drivers/net/ethernet/arc/Kconfig
> index 89e04fd..6d96a82 100644
> --- a/drivers/net/ethernet/arc/Kconfig
> +++ b/drivers/net/ethernet/arc/Kconfig
> @@ -32,4 +32,19 @@ config ARC_EMAC
> non-standard on-chip ethernet device ARC EMAC 10/100 is used.
> Say Y here if you have such a board. If unsure, say N.
>
> +config EMAC_ROCKCHIP
> + tristate "Rockchip EMAC support"
> + select ARC_EMAC_CORE
> + depends on OF_IRQ
> + depends on OF_NET
> + depends on ARCH_ROCKCHIP
> + depends on REGULATOR_ACT8865
> + depends on SMSC_PHY
> + depends on MFD_SYSCON
> + ---help---
> + Support for Rockchip RK3066/RK3188 EMAC ethernet controllers.
> + This selects Rockchip SoC glue layer support for the
> + emac device driver. This driver is used for RK3066/RK3188
> + EMAC ethernet controller.
> +
> endif # NET_VENDOR_ARC
> diff --git a/drivers/net/ethernet/arc/Makefile b/drivers/net/ethernet/arc/Makefile
> index 241bb80..79108af 100644
> --- a/drivers/net/ethernet/arc/Makefile
> +++ b/drivers/net/ethernet/arc/Makefile
> @@ -5,3 +5,4 @@
> arc_emac-objs := emac_main.o emac_mdio.o
> obj-$(CONFIG_ARC_EMAC_CORE) += arc_emac.o
> obj-$(CONFIG_ARC_EMAC) += emac_arc.o
> +obj-$(CONFIG_EMAC_ROCKCHIP) += emac_rockchip.o
> diff --git a/drivers/net/ethernet/arc/emac.h b/drivers/net/ethernet/arc/emac.h
> index 164b1c7..2bfe8c76 100644
> --- a/drivers/net/ethernet/arc/emac.h
> +++ b/drivers/net/ethernet/arc/emac.h
> @@ -127,6 +127,8 @@ struct buffer_state {
> struct arc_emac_priv {
> const char *drv_name;
> const char *drv_version;
> + void (*set_mac_speed)(void *priv, unsigned int speed);
> +
> /* Devices */
> struct device *dev;
> struct phy_device *phy_dev;
> diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c
> index b35c69e..a08f343 100644
> --- a/drivers/net/ethernet/arc/emac_main.c
> +++ b/drivers/net/ethernet/arc/emac_main.c
> @@ -48,6 +48,8 @@ static void arc_emac_adjust_link(struct net_device *ndev)
> if (priv->speed != phy_dev->speed) {
> priv->speed = phy_dev->speed;
> state_changed = 1;
> + if (priv->set_mac_speed)
> + priv->set_mac_speed(priv, priv->speed);
> }
>
> if (priv->duplex != phy_dev->duplex) {
> diff --git a/drivers/net/ethernet/arc/emac_rockchip.c b/drivers/net/ethernet/arc/emac_rockchip.c
> new file mode 100644
> index 0000000..ff1a657
> --- /dev/null
> +++ b/drivers/net/ethernet/arc/emac_rockchip.c
> @@ -0,0 +1,224 @@
> +/**
> + * emac-rockchip.c - Rockchip EMAC specific glue layer
> + *
> + * Copyright (C) 2014 Romain Perier
> + *
> + * Romain Perier <romain.perier@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/etherdevice.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/of_net.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +
> +#include "emac.h"
> +
> +#define DRV_NAME "rockchip_emac"
> +#define DRV_VERSION "1.0"
> +
> +#define GRF_MODE_MII BIT(0)
> +#define GRF_MODE_RMII 0x0
> +#define GRF_SPEED_10M 0x0
> +#define GRF_SPEED_100M BIT(1)
> +
> +struct emac_rockchip_soc_data {
> + int grf_offset;
> +};
> +
> +struct rockchip_priv_data {
> + struct arc_emac_priv emac;
> + struct regmap *grf;
> + struct emac_rockchip_soc_data *soc_data;
> + struct regulator *regulator;
> + struct clk *refclk;
> +};
> +
> +static const struct of_device_id emac_rockchip_dt_ids[];
> +
> +static void emac_rockchip_set_mac_speed(void *priv, unsigned int speed)
> +{
> + struct rockchip_priv_data *emac = priv;
> + u32 data;
> + int err = 0;
> +
> + /* write-enable bits */
> + data = BIT(17);
> +
> + switch(speed) {
> + case 10:
> + data |= GRF_SPEED_10M;
> + break;
> + case 100:
> + data |= GRF_SPEED_100M;
> + break;
> + default:
> + pr_err("speed %u not supported\n", speed);
> + return;
> + }
> +
> + err = regmap_write(emac->grf, emac->soc_data->grf_offset, data);
> + if (err)
> + pr_err("unable to apply speed %u to grf (%d)\n", speed, err);
> +}
> +
> +static int emac_rockchip_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct net_device *ndev;
> + struct rockchip_priv_data *priv;
> + const struct of_device_id *match;
> + u32 data, rate;
> + int err, interface;
> +
> + if (!pdev->dev.of_node)
> + return -ENODEV;
> +
> + ndev = alloc_etherdev(sizeof(struct rockchip_priv_data));
> + if (!ndev)
> + return -ENOMEM;
> + platform_set_drvdata(pdev, ndev);
> + SET_NETDEV_DEV(ndev, dev);
> +
> + priv = netdev_priv(ndev);
> + priv->emac.drv_name = DRV_NAME;
> + priv->emac.drv_version = DRV_VERSION;
> + priv->emac.set_mac_speed = emac_rockchip_set_mac_speed;
> +
> + interface = of_get_phy_mode(dev->of_node);
> +
> + /* RK3066 and RK3188 SoCs only support RMII */
> + if (interface != PHY_INTERFACE_MODE_RMII) {
> + dev_err(dev, "unsupported phy interface mode %d\n", interface);
> + err = -ENOTSUPP;
> + goto out_netdev;
> + }
> +
> + priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
> + if (IS_ERR(priv->grf)) {
> + dev_err(dev, "failed to retrieve global register file from the device tree (%ld)\n", PTR_ERR(priv->grf));
> + err = PTR_ERR(priv->grf);
> + goto out_netdev;
> + }
> +
> + match = of_match_node(emac_rockchip_dt_ids, dev->of_node);
> + priv->soc_data = (struct emac_rockchip_soc_data *)match->data;
> +
> + priv->emac.clk = devm_clk_get(dev, "hclk");
> + if (IS_ERR(priv->emac.clk)) {
> + dev_err(dev, "failed to retrieve host clock from device tree (%ld)\n", PTR_ERR(priv->emac.clk));
> + err = PTR_ERR(priv->emac.clk);
> + goto out_netdev;
> + }
> +
> + priv->refclk = devm_clk_get(dev, "macref");
> + if (IS_ERR(priv->refclk)) {
> + dev_err(dev, "failed to retrieve reference clock from device tree (%ld)\n", PTR_ERR(priv->refclk));
> + err = PTR_ERR(priv->refclk);
> + goto out_netdev;
> + }
> +
> + err = clk_prepare_enable(priv->refclk);
> + if (err) {
> + dev_err(dev, "failed to enable reference clock (%d)\n", err);
> + goto out_netdev;
> + }
> +
> + /* Optional regulator for PHY */
> + priv->regulator = devm_regulator_get_optional(dev, "phy");
> + if (IS_ERR(priv->regulator)) {
> + if (PTR_ERR(priv->regulator) == -EPROBE_DEFER)
> + return -EPROBE_DEFER;
> + dev_err(dev, "no regulator found\n");
> + priv->regulator = NULL;
> + }
> +
> + if (priv->regulator) {
> + err = regulator_enable(priv->regulator);
> + if (err) {
> + dev_err(dev, "failed to enable phy-supply (%d)\n", err);
> + goto out_netdev;
> + }
> + }
> +
> + err = arc_emac_probe(ndev, interface);
> + if (err)
> + goto out_netdev;
> +
> + /* write-enable bits */
> + data = BIT(16) | BIT(17);
> +
> + data |= GRF_SPEED_100M;
> + data |= GRF_MODE_RMII;
> + rate = 50000000;
> +
> + err = regmap_write(priv->grf, priv->soc_data->grf_offset, data);
> + if (err) {
> + dev_err(dev, "unable to apply initial settings to grf (%d)\n", err);
> + goto out_netdev;
> + }
> +
> + err = clk_set_rate(priv->refclk, rate);
> + if (err)
> + dev_err(dev, "failed to change reference clock rate (%d)\n", err);
> +
> +out_netdev:
> + if (err)
> + free_netdev(ndev);
> + return err;
> +}
> +
> +static int emac_rockchip_remove(struct platform_device *pdev)
> +{
> + struct net_device *ndev = platform_get_drvdata(pdev);
> + struct rockchip_priv_data *priv = netdev_priv(ndev);
> + int err;
> +
> + clk_disable_unprepare(priv->refclk);
> +
> + if (priv->regulator)
> + regulator_disable(priv->regulator);
> + err = arc_emac_remove(ndev);
> + free_netdev(ndev);
> + return err;
> +}
> +
> +static const struct emac_rockchip_soc_data emac_rockchip_dt_data[] = {
> + { .grf_offset = 0x154 }, /* rk3066 */
> + { .grf_offset = 0x0a4 }, /* rk3188 */
> +};
> +
> +static const struct of_device_id emac_rockchip_dt_ids[] = {
> + { .compatible = "rockchip,rk3066-emac", .data = (void *)&emac_rockchip_dt_data[0]},
> + { .compatible = "rockchip,rk3188-emac", .data = (void *)&emac_rockchip_dt_data[1]},
> + { /* Sentinel */ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, emac_rockchip_dt_ids);
> +
> +static struct platform_driver emac_rockchip_driver = {
> + .probe = emac_rockchip_probe,
> + .remove = emac_rockchip_remove,
> + .driver = {
> + .name = DRV_NAME,
> + .of_match_table = emac_rockchip_dt_ids,
> + },
> +};
> +
> +module_platform_driver(emac_rockchip_driver);
> +
> +MODULE_AUTHOR("Romain Perier <romain.perier@gmail.com>");
> +MODULE_DESCRIPTION("Rockchip EMAC platform driver");
> +MODULE_LICENSE("GPL");
> --
> 1.9.1
>
^ permalink raw reply
* Re: BCM4313 & brcmsmac & 3.12: only semi-working?
From: Arend van Spriel @ 2014-08-27 15:27 UTC (permalink / raw)
To: Michael Tokarev; +Cc: brcm80211-dev-list, linux-wireless, netdev
In-Reply-To: <53FDACD1.8090805@msgid.tls.msk.ru>
On 08/27/14 12:02, Michael Tokarev wrote:
> 27.08.2014 01:37, Arend van Spriel wrote:
>> On 08/26/14 18:15, Michael Tokarev wrote:
> []
>> Well, sorry about that. I did see the other messages fly by and noticed you were using the wl driver so assumed you were fine with that.
>
> That's past already. I had several issues with wl driver,
> and current issue is that even the latest (Aug-2014) version
> of wl driver doesn't work with current kernel. So I can't
> really even compare wl and brcmsmac, -- in kernels< 3.16
> brcmsmac does not work, but wl can't be compiled for 3.16,
> and using different kernels for comparison is a bit wrong
> because there may be differences in other areas.
>
>> Admittedly the brcmsmac got very little attention as all our resources were put on brcmfmac.
>
> That happens. :)
>
> []
>> Ok. Let's put frustration aside and make an effort. So could you make a trace using trace-cmd utility. The log can get quite big. The brcmsmac driver needs to be built with CONFIG_BRCM_TRACING enabled. Please execute the following commands (assuming you use ubuntu with network-manager):
>>
>> $ sudo stop network-manager
>> $ sudo insmod brcmfmac.ko
>> $ sudo trace-cmd record -e brcmsmac:*
>>
>> In another terminal:
>>
>> $ sudo start network-manager
>>
>> The trace-cmd must be stopped using ctrl-c.
>
> Okay. This turned out to be not so simple.
>
> My initial attempt indicated that brcmsmac in 3.16 does
> not work at all. This isn't actually true - subsequent
> attempts shows that it works. I was ready to conclude
> the problem is fixed (after transferring several gigs
> of data over wifi, with tracing enabled or disabled,
> after fresh boot or after reboot from wl-enabled kernel,
> etc - it all worked.
>
> Until I hit the same stall as I described initially, the
> same which happened numerous times with kernel 3.12 ($subj).
>
> After several mins of transferring it stalled. But this
> time (unlike with 3.12), it continued after about 30 secs.
A kernel log (so no trace) of stalling interface might be useful so if
you can provide that and put a marker in there where you believe it
stalled that would be great.
> So, while my initial test of 3.16 indicated the prob is still
> here, at the same (or even worse) state, I can't really
> reproduce it, at least in a reliable way. There's something
> wrong still, but at least current version is significantly
> more useful than before (in a hope it wont stall at the
> very wrong moment exactly ;).
>
> There's one more difference between brcmsmac and wl -- with
> wl, I see significantly better speed, -- it is about 5MB/sec,
> while with brcmsmac it jumps between 2.0..4.5MB/sec (with
> 58..65Mbps connection rate in both cases). Here's a typical
> iwconfig output for brcmsmac version:
>
> wlan0 IEEE 802.11bgn ESSID:"mjt"
> Mode:Managed Frequency:2.412 GHz Access Point: 64:70:02:29:D9:30
> Bit Rate=65 Mb/s Tx-Power=19 dBm
> Retry short limit:7 RTS thr:off Fragment thr:off
> Power Management:off
> Link Quality=58/70 Signal level=-61 dBm
> Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
> Tx excessive retries:56355 Invalid misc:472 Missed beacon:0
>
> I'll keep trying/testing various cases, in attempt to
> understand what's going on. For now, I can't provide the
> requested traces (it wont be very useful, I guess).
>
> BTW, are there other things not implemented in brcmsmac?
> I see the module reminds about power management, what
> does it mean? Anything else missing?
Well, the wireless twiki has that info [1]. Regarding features the
important ones that I know are still not there are 40MHz support, and
power-save. The bcm4313 does not support 40MHz. Community contributions
added ibss, and ap mode. For P2P and TDLS probably some changes would be
needed although most of the legwork is done in mac80211.
Regards,
Arend
[1]
http://wireless.kernel.org/en/users/Drivers/brcm80211#To_be_done_for_softmac_driver
> Thank you!
>
> /mjt
^ permalink raw reply
* Re: [PATCH net-next v4 01/13] net: dsa: reduce number of protocol hooks
From: Alexander Duyck @ 2014-08-27 15:25 UTC (permalink / raw)
To: Florian Fainelli, netdev; +Cc: davem, linville, jhs, alexander.duyck
In-Reply-To: <1409028581-17399-2-git-send-email-f.fainelli@gmail.com>
On 08/25/2014 09:49 PM, Florian Fainelli wrote:
> DSA is currently registering one packet_type function per EtherType it
> needs to intercept in the receive path of a DSA-enabled Ethernet device.
> Right now we have three of them: trailer, DSA and eDSA, and there might
> be more in the future, this will not scale to the addition of new
> protocols.
>
> This patch proceeds with adding a new layer of abstraction and two new
> functions:
>
> dsa_switch_rcv() which will dispatch into the tag-protocol specific
> receive function implemented by net/dsa/tag_*.c
>
> dsa_slave_xmit() which will dispatch into the tag-protocol specific
> transmit function implemented by net/dsa/tag_*.c
>
> When we do create the per-port slave network devices, we iterate over
> the switch protocol to assign the DSA-specific receive and transmit
> operations.
>
> This allows us to greatly simplify the check in eth_type_trans() and
> always override the skb->protocol with ETH_P_DSA for Ethernet switches
> tagged protocol, while also reducing the number repetitive slave
> netdevice_ops assignments.
>
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
> Changes in v4:
> - introduce a level of indirection and dsa_device_ops to limit the
> number of packet_type functions to just one and do the dispatching
> in the core dsa code.
>
> New patch in v3
>
Just a thought, you might want to consider using a protocol value other
than ETH_P_DSA. Maybe we should add a new value named ETH_P_XDSA for
this approach since what we are doing is a multiplexed DSA protocol now.
This would allow for much easier back-porting of this if needed and also
prevents us from possibly triggering any issues if there are any
user-space APIs that might be trying to capture packets based on the
protocol value.
Thanks,
Alex
^ permalink raw reply
* Re: [PATCH V4 3/8] namespaces: expose ns instance serial numbers in proc
From: Richard Guy Briggs @ 2014-08-27 15:17 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Linux API, Linux Containers, linux-kernel@vger.kernel.org,
linux-audit, Eric W. Biederman, netdev, Serge E. Hallyn
In-Reply-To: <CALCETrVVQ2Ugesq8zWK_gmj46Zr6mFL2Riyf=Lrdqy8ze3YfPA@mail.gmail.com>
On 14/08/25, Andy Lutomirski wrote:
> On Mon, Aug 25, 2014 at 9:41 AM, Nicolas Dichtel
> <nicolas.dichtel@6wind.com> wrote:
> > Le 25/08/2014 18:13, Andy Lutomirski a écrit :
> >
> >> On Mon, Aug 25, 2014 at 8:43 AM, Nicolas Dichtel
> >> <nicolas.dichtel@6wind.com> wrote:
> >>>
> >>> Le 25/08/2014 16:04, Andy Lutomirski a écrit :
> >>>
> >>>> On Aug 25, 2014 6:30 AM, "Nicolas Dichtel" <nicolas.dichtel@6wind.com>
> >>>> wrote:
> >>>>>>
> >>>>>>
> >>>>>> CRIU wants to save the complete state of a namespace and then restore
> >>>>>> it. For that to work, any information exposed to things in the
> >>>>>> namespace *cannot* be globally unique or unique per boot, since CRIU
> >>>>>> needs to arrange for that information to match whatever it was when
> >>>>>> CRIU saved it.
> >>>>>
> >>>>>
> >>>>>
> >>>>> How are ifindex of network devices managed? These ifindexes are unique
> >>>>> per boot,
> >>>>> thus can change depending on the order in which netdev are created.
> >>>>> These ifindexes are unique per boot and exposed to userspace ...
> >>>>>
> >>>>
> >>>> This does not appear to be true.
> >>>>
> >>>> $ sudo unshare --net
> >>>> # ip link add veth0 type veth peer name veth1
> >>>> # ip link
> >>>> 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group
> >>>> default
> >>>> link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
> >>>> 2: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
> >>>> DEFAULT group default qlen 1000
> >>>> link/ether 06:0d:59:c7:a6:a8 brd ff:ff:ff:ff:ff:ff
> >>>> 3: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
> >>>> DEFAULT group default qlen 1000
> >>>> link/ether b2:5c:8b:f2:12:28 brd ff:ff:ff:ff:ff:ff
> >>>> # logout
> >>>> $ ip link
> >>>> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
> >>>> link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
> >>>> 3: em1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast
> >>>> state DOWN qlen 1000
> >>>>
> >>> I've probably misunderstood what you're trying to say. ifindexes are
> >>> unique
> >>> per
> >>> boot and per netns.
> >>
> >>
> >> I think we both misunderstood each other. The ifindexes are unique
> >> *per netns*, which means that, if you're unprivileged in a netns,
> >> global information doesn't leak to you. I think this is good.
> >
> > Ok, I agree. I think audit daemons are always running under privileged
> > users.
> >
> >
> >>
> >>>>
> >>>> Let me try again, with emphasis in the right place.
> >>>>
> >>>> I think that *code running in a namespace* has no business even
> >>>> knowing a unique identity of *that namespace* from the perspective of
> >>>> the host.
> >>>>
> >>>> In your example, if there's a veth device between netns A and netns B,
> >>>> then code *in netns A* has no business knowing the identity of its
> >>>> veth peer if its peer (B) is a sibling or ancestor. It also IMO has
> >>>> no business knowing the identity of its own netns (A) other than as
> >>>> "my netns".
> >>>
> >>>
> >>> I do not agree (see the example below).
> >>>
> >>>
> >>>>
> >>>> If A and B are siblings, then their parent needs to know where that
> >>>> veth device goes, but I think this is already the case to a sufficient
> >>>> extent today.
> >>>
> >>>
> >>> I'm not aware of a hierarchy between netns. A daemon should be able to
> >>> got the full network configuration, even if it's started when this
> >>> configuration
> >>> is already applied, ie even if it doesn't know what happen before it
> >>> starts.
> >>>
> >>
> >> I don't know exactly which namespaces have an explicit hierarchy, but
> >> there is certainly a hierarchy of *user* namespaces, and network
> >> namespaces live in user namespaces, so they at least have somewhat of
> >> a hierarchy.
> >>
> >>>
> >>>>
> >>>> I feel like this discussion is falling into a common trap of new API
> >>>> discussions. Can one of you who wants this API please articulate,
> >>>> with a reasonably precise example, what it is that you want to do, why
> >>>> you can't easily do it already, and how this API helps? I currently
> >>>> understand how the API creates problems, but I don't understand how it
> >>>> solves any problems, and I will NAK it (and I suspect that Eric will,
> >>>> too, which is pretty much fatal) unless that changes.
> >>>
> >>>
> >>> What I'm trying to solve is to have full info in netlink messages sent by
> >>> the
> >>> kernel, thus beeing able to identify a peer netns (and this is close from
> >>> what
> >>> audit guys are trying to have). Theorically, messages sent by the kernel
> >>> can
> >>> be
> >>> reused as is to have the same configuration. This is not the case with
> >>> x-netns
> >>> devices. Here is an example, with ip tunnels:
> >>>
> >>> $ ip netns add 1
> >>> $ ip link add ipip1 type ipip remote 10.16.0.121 local 10.16.0.249 dev
> >>> eth0
> >>> $ ip -d link ls ipip1
> >>> 8: ipip1@eth0: <POINTOPOINT,NOARP> mtu 1480 qdisc noop state DOWN mode
> >>> DEFAULT group default
> >>> link/ipip 10.16.0.249 peer 10.16.0.121 promiscuity 0
> >>> ipip remote 10.16.0.121 local 10.16.0.249 dev eth0 ttl inherit
> >>> pmtudisc
> >>> $ ip link set ipip1 netns 1
> >>> $ ip netns exec 1 ip -d link ls ipip1
> >>> 8: ipip1@tunl0: <POINTOPOINT,NOARP,M-DOWN> mtu 1480 qdisc noop state DOWN
> >>> mode DEFAULT group default
> >>> link/ipip 10.16.0.249 peer 10.16.0.121 promiscuity 0
> >>> ipip remote 10.16.0.121 local 10.16.0.249 dev tunl0 ttl inherit
> >>> pmtudisc
> >>>
> >>> Now informations got with 'ip link' are wrong and incomplete:
> >>> - the link dev is now tunl0 instead of eth0, because we only got an
> >>> ifindex
> >>> from the kernel without any netns informations.
> >>> - the encapsulation addresses are not part of this netns but the user
> >>> doesn't
> >>> known that (still because netns info is missing). These IPv4
> >>> addresses
> >>> may
> >>> exist into this netns.
> >>> - it's not possible to create the same netdevice with these infos.
> >>>
> >>
> >> Aha. That's a genuine problem.
> >>
> >> Perhaps we need a concept of which netnses should be able to see each
> >> other.
> >
> > Yes, I agree. This is not required for all netns, only a subset of netns
> > should
> >
> > be able to see each other.
> >
> >>
> >> I think I would be okay with a somewhat different outcome from your
> >> example:
> >>
> >> $ ip netns exec 1 ip -d link ls ipip1
> >> 8: ipip1@[unknown device in another namespace]:
> >> <POINTOPOINT,NOARP,M-DOWN> mtu 1480 qdisc noop state DOWN
> >>
> >> I think this outcome is mandatory if netns 1 lives in a subsidiary
> >> user namespace.
> >
> > Yes.
> >
> >
> >>
> >> Certainly, if you do the 'ip link' in the original namespace, I agree
> >> that this should work.
> >
> > And yes :)
> >
> > I will update my previous proposal
> > (http://thread.gmane.org/gmane.linux.network/315933/focus=321753)
> > to allow to get an id for a peer netns only when the user namespace is the
> > same.
>
> I think it should work if the peer userns is the same or a descendent.
> I also wonder whether the peer's ifindex should be suppressed if peer
> userns is not the same or a descendent.
>
> Now you just have to get Eric to be happy with the id allocation. :)
> This may be nontrivial.
>
> >> For most namespace types, this all works transparently, since
> >> everything has an real identity all the way up the hierarchy. Network
> >> namespaces are different.
> >>
> >> I don't think that exposing serial numbers in /proc is a good
> >> solution, both for the reasons already described and because I don't
> >> think that iproute2 should need to muck around with /proc to function
> >
> > A netlink API is probably enough. But it will help only for the network
> > problem, not for audit. I was hoping to find a common solution.
>
> I still don't understand why audit needs anything beyond the audit
> part of this patch set. I have no problem with audit seeing that
> migrated/restored namespaces are really brand-new namespaces, as long
> as the code in those namespaces isn't exposed to it.
Ok, I'm starting to get this... Perhaps /proc wasn't the best place to
expose this. Audit or an audit aggregator is the only one that needs to
know any of this information. This could be accomplished with
CAP_AUDIT_CONTROL and a new netlink audit message type to fetch
individual or all namespace IDs for a particular PID via auditctl, or by
having a CAP_AUDIT_WRITE-capable application pull the trigger to simply
dump that information to the log.
> >> correctly. Eric, any clever ideas here? Do we need fancier netlink
> >> messages for this?
> >>
> >> --Andy
>
> Andy Lutomirski
- RGB
--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545
^ permalink raw reply
* Re: [PATCH] bonding: bond_alb: Replace rcu_dereference() with rcu_access_pointer()
From: Eric Dumazet @ 2014-08-27 15:15 UTC (permalink / raw)
To: Andreea-Cristina Bernat
Cc: j.vosburgh, vfalico, andy, netdev, linux-kernel, paulmck
In-Reply-To: <20140827141827.GA11520@ada>
On Wed, 2014-08-27 at 17:18 +0300, Andreea-Cristina Bernat wrote:
> The "curr_active_slave" local variable obtained through the rcu_dereference()
> call it is not dereferenced in the rest of the function.
> Therefore, it is recommended to use rcu_access_pointer() instead of
> rcu_dereference().
> This patch makes the replacement.
>
> The first step to detect this was made with the following Coccinelle semantic
> patch:
> @@
> identifier p;
> @@
>
> * p = rcu_dereference(...)
> ... when any
> when != p
> (
> * if( (<+...p...+>) ) { ... }
> |
> * while( (<+...p...+>) ) { ... }
> )
> ... when != p
>
> After the analysis of the output, the change was made manually.
>
> Signed-off-by: Andreea-Cristina Bernat <bernat.ada@gmail.com>
> ---
> drivers/net/bonding/bond_alb.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
> index 1319c5b..6621ac2 100644
> --- a/drivers/net/bonding/bond_alb.c
> +++ b/drivers/net/bonding/bond_alb.c
> @@ -659,7 +659,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
>
> _lock_rx_hashtbl(bond);
>
> - curr_active_slave = rcu_dereference(bond->curr_active_slave);
> + curr_active_slave = rcu_access_pointer(bond->curr_active_slave);
>
> hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
> client_info = &(bond_info->rx_hashtbl[hash_index]);
This is very error prone, for little immediate gain.
What prevents future changes to deref the pointer without sparse or
lockdep support, other than careful code review ?
I would use the __rcu attribute and eventually add _noderef suffix to
the variable name.
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 73c21e233131..4ddccc72db62 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -657,13 +657,14 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
{
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct arp_pkt *arp = arp_pkt(skb);
- struct slave *assigned_slave, *curr_active_slave;
+ struct slave *assigned_slave;
+ struct slave __rcu *curr_active_slave;
struct rlb_client_info *client_info;
u32 hash_index = 0;
_lock_rx_hashtbl(bond);
- curr_active_slave = rcu_dereference(bond->curr_active_slave);
+ curr_active_slave = bond->curr_active_slave;
hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
client_info = &(bond_info->rx_hashtbl[hash_index]);
^ permalink raw reply related
* Re: [RFC] net: ipv4: drop unicast encapsulated in L2 multicast
From: Julian Anastasov @ 2014-08-27 14:31 UTC (permalink / raw)
To: Johannes Berg; +Cc: David Miller, linux-wireless, netdev
In-Reply-To: <1409138967.2505.11.camel@jlt4.sipsolutions.net>
Hello,
On Wed, 27 Aug 2014, Johannes Berg wrote:
> On Wed, 2014-08-27 at 13:23 +0300, Julian Anastasov wrote:
>
> > BTW, what kind of packets (protocol) we want to drop? UDP?
>
> All IP protocols, this comes either from the IPv4 RFC (1122) or from the
> wireless issue which affects all protocols.
I did a grep for inet_add_protocol, in case if
we prefer to use per-protocol checks:
Protocols that look ok to me: TCP, SCTP, DCCP
ICMP: missing check in icmp_rcv
UDP, UDPLITE: need check in __udp4_lib_rcv
IGMP: uses only multicast address?
PIM: not sure if __pim_rcv() needs check, before skb_tunnel_rx()
changes pkt_type?
More protocols are also registered with inet_add_protocol(), I don't
see pkt_type checks there, mostly tunnels:
- IPPROTO_GRE
- IPPROTO_L2TP
- IPPROTO_IPIP
- IPPROTO_IPV6 (tunnel64_rcv)
If going to use a global check I hope there are
no protocols that require exception to this rule.
Regards
--
Julian Anastasov <ja@ssi.bg>
^ permalink raw reply
* Re: [PATCH net-next] bonding: add slave_changelink support and use it for queue_id
From: Jiri Pirko @ 2014-08-27 14:29 UTC (permalink / raw)
To: Nikolay Aleksandrov
Cc: netdev, David S. Miller, Jay Vosburgh, Veaceslav Falico,
Andy Gospodarek
In-Reply-To: <1409148406-5576-1-git-send-email-nikolay@redhat.com>
Wed, Aug 27, 2014 at 04:06:46PM CEST, nikolay@redhat.com wrote:
>This patch adds support for slave_changelink to the bonding and uses it
>to give the ability to change the queue_id of the enslaved devices via
>netlink. It sets slave_maxtype and uses bond_changelink as a prototype for
>bond_slave_changelink.
>Example/test command after the iproute2 patch:
> ip link set eth0 type bond_slave queue_id 10
>
>CC: David S. Miller <davem@davemloft.net>
>CC: Jay Vosburgh <j.vosburgh@gmail.com>
>CC: Veaceslav Falico <vfalico@gmail.com>
>CC: Andy Gospodarek <andy@greyhouse.net>
>
>Suggested-by: Jiri Pirko <jiri@resnulli.us>
>Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
>---
>note: I intend to add a new option flag to indicate it's a slave option
> so a new netdev notifier can be called (NETDEV_CHANGESLAVEINFODATA).
No need fo that atm.
> I believe the bonding is the first user of slave_changelink so I hope
> I haven't missed anything. Once this patch is accepted in some form
> I'll post the iproute2 one.
This patch is looking good to me.
Acked-by: Jiri Pirko <jiri@resnulli.us>
^ permalink raw reply
* Re: [PATCH 1/1] add selftest for virtio-net
From: Michael S. Tsirkin @ 2014-08-27 14:28 UTC (permalink / raw)
To: Jason Wang
Cc: Hengjinxiao, famz, netdev, linux-kernel, virtualization,
linux-api
In-Reply-To: <53FD6542.10708@redhat.com>
On Wed, Aug 27, 2014 at 12:57:38PM +0800, Jason Wang wrote:
> On 08/27/2014 09:45 AM, Hengjinxiao wrote:
> > Selftest is an important part of network driver, this patch adds selftest for
> > virtio-net, including loopback test, negotiate test and reset test. Loopback
> > test checks whether virtio-net can send and receive packets normally. Negotiate test
> > executes feature negotiation between virtio-net driver in Guest OS and virtio-net
> > device in Host OS. Reset test resets virtio-net.
>
> Thanks for the patch. Feature negotiation part brings some complicity
> and need more through. And this could be extended for CVE regression in
> the future. And you probably also need to send a patch of virtio spec to
> implement the loop back mode.
>
> See comments inline.
> >
> > Signed-off-by: Hengjinxiao <hjxiaohust@gmail.com>
> >
> > ---
> > drivers/net/virtio_net.c | 233 +++++++++++++++++++++++++++++++++++++++-
> > include/uapi/linux/virtio_net.h | 9 ++
> > 2 files changed, 241 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 59caa06..f83f6e4 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -28,6 +28,7 @@
> > #include <linux/cpu.h>
> > #include <linux/average.h>
> > #include <net/busy_poll.h>
> > +#include <linux/pci.h>
> >
> > static int napi_weight = NAPI_POLL_WEIGHT;
> > module_param(napi_weight, int, 0444);
> > @@ -51,6 +52,23 @@ module_param(gso, bool, 0444);
> > #define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256)
> >
> > #define VIRTNET_DRIVER_VERSION "1.0.0"
> > +#define __VIRTNET_TESTING 0
> > +
>
> Why need this marco?
> > +enum {
> > + VIRTNET_LOOPBACK_TEST,
> > + VIRTNET_FEATURE_NEG_TEST,
> > + VIRTNET_RESET_TEST,
> > +};
> > +
> > +static const struct {
> > + const char string[ETH_GSTRING_LEN];
> > +} virtnet_gstrings_test[] = {
> > + [VIRTNET_LOOPBACK_TEST] = { "loopback test (offline)" },
> > + [VIRTNET_FEATURE_NEG_TEST] = { "negotiate test (offline)" },
> > + [VIRTNET_RESET_TEST] = { "reset test (offline)" },
> > +};
> > +
> > +#define VIRTNET_NUM_TEST ARRAY_SIZE(virtnet_gstrings_test)
> >
> > struct virtnet_stats {
> > struct u64_stats_sync tx_syncp;
> > @@ -104,6 +122,8 @@ struct virtnet_info {
> > struct send_queue *sq;
> > struct receive_queue *rq;
> > unsigned int status;
> > + unsigned long flags;
> > + atomic_t lb_count;
> >
> > /* Max # of queue pairs supported by the device */
> > u16 max_queue_pairs;
> > @@ -436,6 +456,19 @@ err_buf:
> > return NULL;
> > }
> >
> > +void virtnet_check_lb_frame(struct virtnet_info *vi,
> > + struct sk_buff *skb)
> > +{
> > + unsigned int frame_size = skb->len;
> > +
> > + if (*(skb->data + 3) == 0xFF) {
> > + if ((*(skb->data + frame_size / 2 + 10) == 0xBE) &&
> > + (*(skb->data + frame_size / 2 + 12) == 0xAF)) {
> > + atomic_dec(&vi->lb_count);
> > + }
> > + }
> > +}
> > +
> > static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
> > {
> > struct virtnet_info *vi = rq->vq->vdev->priv;
> > @@ -485,7 +518,12 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
> > } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) {
> > skb->ip_summed = CHECKSUM_UNNECESSARY;
> > }
> > -
> > + /* loopback self test for ethtool */
> > + if (test_bit(__VIRTNET_TESTING, &vi->flags)) {
> > + virtnet_check_lb_frame(vi, skb);
> > + dev_kfree_skb_any(skb);
> > + return;
> > + }
>
> Not sure it's a good choice for adding such in fast path. We may need a
> test specific rx interrupt handler (and disable NAPI) for this.
I agree here.
Since it's an offline test, there's no need to mix
it up with the main mode.
> > skb->protocol = eth_type_trans(skb, dev);
> > pr_debug("Receiving skb proto 0x%04x len %i type %i\n",
> > ntohs(skb->protocol), skb->len, skb->pkt_type);
> > @@ -813,6 +851,9 @@ static int virtnet_open(struct net_device *dev)
> > {
> > struct virtnet_info *vi = netdev_priv(dev);
> > int i;
> > + /* disallow open during test */
> > + if (test_bit(__VIRTNET_TESTING, &vi->flags))
> > + return -EBUSY;
> >
> > for (i = 0; i < vi->max_queue_pairs; i++) {
> > if (i < vi->curr_queue_pairs)
> > @@ -1363,12 +1404,158 @@ static void virtnet_get_channels(struct net_device *dev,
> > channels->other_count = 0;
> > }
> >
> > +static int virtnet_reset(struct virtnet_info *vi);
> > +
Pls avoid forward declarations.
Also this seems to duplicate a bunch of code.
Please don't duplicate code, use functions to
reuse it.
> > +static void virtnet_create_lb_frame(struct sk_buff *skb,
> > + unsigned int frame_size)
> > +{
> > + memset(skb->data, 0xFF, frame_size);
> > + frame_size &= ~1;
> > + memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1);
> > + memset(&skb->data[frame_size / 2 + 10], 0xBE, 1);
> > + memset(&skb->data[frame_size / 2 + 12], 0xAF, 1);
> > +}
> > +
> > +static int virtnet_start_loopback(struct virtnet_info *vi)
> > +{
> > + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_LOOPBACK,
> > + VIRTIO_NET_CTRL_LOOPBACK_SET, NULL, NULL)) {
> > + dev_warn(&vi->dev->dev, "Failed to set loopback.\n");
> > + return -EINVAL;
> > + }
> > + return 0;
>
> You may need to test the feature bit of loop back first and report the
> card does not support loop back in some way.
> > +}
> > +
> > +static int virtnet_run_loopback_test(struct virtnet_info *vi)
> > +{
> > + int i;
> > + netdev_tx_t rc;
> > + struct sk_buff *skb;
> > + unsigned int size = GOOD_COPY_LEN;
> > +
> > + for (i = 0; i < 100; i++) {
> > + skb = netdev_alloc_skb(vi->dev, size);
> > + if (!skb)
> > + return -ENOMEM;
> > +
> > + skb->queue_mapping = 0;
> > + skb_put(skb, size);
> > + virtnet_create_lb_frame(skb, size);
> > + rc = start_xmit(skb, vi->dev);
>
> virtio_net does not use tx interrupt to free old xmit skbs. It poll tx
> completion only during xmit_skb(). So at least the last skb is leaked
> since it was not freed. A possible solution is using tx interrupt here.
> > + if (rc != NETDEV_TX_OK)
> > + return -EPIPE;
>
> It looks to me that start_xmit() never return other value than NETDEV_TX_OK.
> > + atomic_inc(&vi->lb_count);
> > + }
> > + /* Give queue time to settle before testing results. */
> > + msleep(20);
>
> Need to make sure this value is also ok for qemu. ixgbe use 200 to 64
> packets.
Yea this looks very ugly.
Do we really need hard-coded timeouts?
> > + return atomic_read(&vi->lb_count) ? -EIO : 0;
> > +}
> > +
> > +static int virtnet_stop_loopback(struct virtnet_info *vi)
> > +{
> > + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_LOOPBACK,
> > + VIRTIO_NET_CTRL_LOOPBACK_UNSET, NULL, NULL)) {
> > + dev_warn(&vi->dev->dev, "Failed to unset loopback.\n");
> > + return -EINVAL;
> > + }
> > + return 0;
> > +}
> > +
> > +static int virtnet_loopback_test(struct virtnet_info *vi, u64 *data)
> > +{
> > + *data = virtnet_start_loopback(vi);
> > + if (*data)
> > + goto out;
> > + *data = virtnet_run_loopback_test(vi);
> > + if (*data)
>
> Do we need to stop loopback here?
> > + goto out;
> > + *data = virtnet_stop_loopback(vi);
> > +out:
> > + return *data;
> > +}
> > +
> > +static void virtnet_feature_neg_test(struct virtnet_info *vi)
> > +{
> > + struct virtio_device *dev = vi->vdev;
> > + struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
> > + int i;
> > + u32 device_features;
> > +
> > + /* Figure out what features the device supports. */
> > + device_features = dev->config->get_features(dev);
> > +
> > + /* Features supported by both device and driver into dev->features. */
> > + memset(dev->features, 0, sizeof(dev->features));
> > + for (i = 0; i < drv->feature_table_size; i++) {
> > + unsigned int f = drv->feature_table[i];
> > +
> > + BUG_ON(f >= 32);
> > + if (device_features & (1 << f))
> > + set_bit(f, dev->features);
> > + }
> > +
> > + /* Transport features always preserved to pass to finalize_features. */
> > + for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++)
> > + if (device_features & (1 << i))
> > + set_bit(i, dev->features);
> > +
> > + dev->config->finalize_features(dev);
> > +}
>
> A problem of the function is it may be called during DRIVER_OK, not sure
> this is ok since spec suggest to do the feature negotiation after DRIVER
> bit but before DRIVER_OK bit. And this function duplicates some of the
> code from virtio core, may consider a method to share between them.
>
> Another issue is the test never fail which needs more thought.
> > +
> > +static int virtnet_get_sset_count(struct net_device *netdev, int sset)
> > +{
> > + switch (sset) {
> > + case ETH_SS_TEST:
> > + return VIRTNET_NUM_TEST;
> > + default:
> > + return -EOPNOTSUPP;
> > + }
> > +}
> > +
> > +static void virtnet_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
> > +{
> > + switch (stringset) {
> > + case ETH_SS_TEST:
> > + memcpy(buf, &virtnet_gstrings_test,
> > + sizeof(virtnet_gstrings_test));
> > + break;
> > + default:
> > + break;
> > + }
> > +}
> > +
> > +static void virtnet_self_test(struct net_device *netdev,
> > + struct ethtool_test *eth_test, u64 *data)
> > +{
> > + struct virtnet_info *vi = netdev_priv(netdev);
> > + bool if_running = netif_running(netdev);
> > +
> > + set_bit(__VIRTNET_TESTING, &vi->flags);
> > + memset(data, 0, sizeof(u64) * VIRTNET_NUM_TEST);
> > +
> > + if (eth_test->flags == ETH_TEST_FL_OFFLINE) {
> > + if (!if_running) {
> > + dev_warn(&vi->dev->dev, "Failed to execute self test.\n");
> > + eth_test->flags |= ETH_TEST_FL_FAILED;
> > + return;
> > + }
> > + if (virtnet_loopback_test(vi, &data[VIRTNET_LOOPBACK_TEST]))
> > + eth_test->flags |= ETH_TEST_FL_FAILED;
> > + virtnet_feature_neg_test(vi);
> > + virtnet_reset(vi);
> > + }
> > + clear_bit(__VIRTNET_TESTING, &vi->flags);
> > +}
> > +
> > static const struct ethtool_ops virtnet_ethtool_ops = {
> > .get_drvinfo = virtnet_get_drvinfo,
> > .get_link = ethtool_op_get_link,
> > .get_ringparam = virtnet_get_ringparam,
> > .set_channels = virtnet_set_channels,
> > .get_channels = virtnet_get_channels,
> > + .self_test = virtnet_self_test,
> > + .get_strings = virtnet_get_strings,
> > + .get_sset_count = virtnet_get_sset_count,
> > };
> >
> > #define MIN_MTU 68
> > @@ -1957,6 +2144,50 @@ static int virtnet_restore(struct virtio_device *vdev)
> > }
> > #endif
> >
> > +static int virtnet_reset(struct virtnet_info *vi)
>
> If this is needed, better split this into anther patch.
> > +{
> > + struct virtio_device *vdev = vi->vdev;
> > + int err, i;
> > + u8 status;
> > +
> > + mutex_lock(&vi->config_lock);
> > + vi->config_enable = false;
> > + mutex_unlock(&vi->config_lock);
> > +
> > + cancel_delayed_work_sync(&vi->refill);
> > +
> > + if (netif_running(vi->dev))
> > + for (i = 0; i < vi->max_queue_pairs; i++) {
> > + napi_disable(&vi->rq[i].napi);
> > + netif_napi_del(&vi->rq[i].napi);
> > + }
> > +
> > + remove_vq_common(vi);
> > + flush_work(&vi->config_work);
> > +
> > + virtnet_feature_neg_test(vi);
>
> Is this used for feature negotiation? If yes, need a better name and can
> we reuse virtio core function to do this?
> > + err = init_vqs(vi);
> > + if (err)
> > + return err;
> > + if (netif_running(vi->dev)) {
> > + for (i = 0; i < vi->curr_queue_pairs; i++)
> > + if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
> > + schedule_delayed_work(&vi->refill, 0);
> > +
> > + for (i = 0; i < vi->max_queue_pairs; i++)
> > + virtnet_napi_enable(&vi->rq[i]);
> > + }
> > +
> > + mutex_lock(&vi->config_lock);
> > + vi->config_enable = true;
> > + mutex_unlock(&vi->config_lock);
> > +
> > + virtnet_set_queues(vi, vi->curr_queue_pairs);
> > + status = vdev->config->get_status(vdev);
> > + vdev->config->set_status(vdev, status | VIRTIO_CONFIG_S_DRIVER_OK);
> > + return 0;
> > +}
> > +
> > static struct virtio_device_id id_table[] = {
> > { VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID },
> > { 0 },
> > diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
> > index 172a7f0..1f31f90 100644
> > --- a/include/uapi/linux/virtio_net.h
> > +++ b/include/uapi/linux/virtio_net.h
> > @@ -201,4 +201,13 @@ struct virtio_net_ctrl_mq {
> > #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1
> > #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000
> >
> > + /*
> > + * Control Loopback(5 is used by VIRTIO_NET_CTRL_GUEST_OFFLOADS in latest qemu)
> > + *
> > + * The command VIRTIO_NET_CTRL_LOOPBACK_SET is used to require the device come
> > + * into loopback state.
> > + */
> > +#define VIRTIO_NET_CTRL_LOOPBACK 6
> > + #define VIRTIO_NET_CTRL_LOOPBACK_SET 0
> > + #define VIRTIO_NET_CTRL_LOOPBACK_UNSET 1
> > #endif /* _LINUX_VIRTIO_NET_H */
^ permalink raw reply
* Re: IPv6 Policy based routing not working.
From: Hannes Frederic Sowa @ 2014-08-27 14:19 UTC (permalink / raw)
To: Tushar Shinde; +Cc: netdev
In-Reply-To: <CABQpAL4tpfAXNbk7AgqV-FZKSSAMVYN_jvOkj58Sc719xKxB-g@mail.gmail.com>
On Mi, 2014-08-27 at 19:11 +0530, Tushar Shinde wrote:
> ping6 command uses SO_BINDTODEVICE but it looks it is not working. The
> source address in fib6 rule match is 0:::0
>
> strace ping6 -I eth0 2001:2::20 2> t
> socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 4
> setsockopt(4, SOL_SOCKET, SO_BINDTODEVICE, "eth0\0", 5) = 0
> connect(4, {sa_family=AF_INET6, sin6_port=htons(1025),
> inet_pton(AF_INET6, "2001:2::20", &sin6_addr), sin6_flowinfo=0,
> sin6_scope_id=0}, 28) = -1 ENETUNREACH (Network is unreachable)
$ strace ping6 -c1 -I em1 :: |& grep SO_BINDTODEVICE
$
Strange, I have a look... thanks!
^ permalink raw reply
* [PATCH] bonding: bond_alb: Replace rcu_dereference() with rcu_access_pointer()
From: Andreea-Cristina Bernat @ 2014-08-27 14:18 UTC (permalink / raw)
To: j.vosburgh, vfalico, andy, netdev, linux-kernel; +Cc: paulmck
The "curr_active_slave" local variable obtained through the rcu_dereference()
call it is not dereferenced in the rest of the function.
Therefore, it is recommended to use rcu_access_pointer() instead of
rcu_dereference().
This patch makes the replacement.
The first step to detect this was made with the following Coccinelle semantic
patch:
@@
identifier p;
@@
* p = rcu_dereference(...)
... when any
when != p
(
* if( (<+...p...+>) ) { ... }
|
* while( (<+...p...+>) ) { ... }
)
... when != p
After the analysis of the output, the change was made manually.
Signed-off-by: Andreea-Cristina Bernat <bernat.ada@gmail.com>
---
drivers/net/bonding/bond_alb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 1319c5b..6621ac2 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -659,7 +659,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
_lock_rx_hashtbl(bond);
- curr_active_slave = rcu_dereference(bond->curr_active_slave);
+ curr_active_slave = rcu_access_pointer(bond->curr_active_slave);
hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
client_info = &(bond_info->rx_hashtbl[hash_index]);
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 0/2] Get rid of ndo_xmit_flush
From: Eric Dumazet @ 2014-08-27 14:09 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Hannes Frederic Sowa, David Miller, netdev, therbert, jhs,
edumazet, jeffrey.t.kirsher, rusty, dborkman
In-Reply-To: <20140827155651.04fe49d0@redhat.com>
On Wed, 2014-08-27 at 15:56 +0200, Jesper Dangaard Brouer wrote:
> I do worry a bit, if writing skb->xmit_more in a more cache cold
> scenarios could hurt us (as that cacheline seems to be read mostly),
> but this is not a problem right now because it will always be cache
> hot, as we always clear the entire SKB in alloc.
>
Yes, but many of us use things like TCP stack and thousand of packets
sitting in a possibly complex qdisc hierarchy before hitting the
device ;)
In these situations, skb is dirtied at TX completion time, but not in
ndo_start_xmit() (where its only read)
In the (qdisc->dequeue() -> ndo_start_xmit()) stage, only the first
cache line of skb is typically dirtied.
^ permalink raw reply
* [PATCH net-next] bonding: add slave_changelink support and use it for queue_id
From: Nikolay Aleksandrov @ 2014-08-27 14:06 UTC (permalink / raw)
To: netdev
Cc: Nikolay Aleksandrov, David S. Miller, Jay Vosburgh,
Veaceslav Falico, Andy Gospodarek
This patch adds support for slave_changelink to the bonding and uses it
to give the ability to change the queue_id of the enslaved devices via
netlink. It sets slave_maxtype and uses bond_changelink as a prototype for
bond_slave_changelink.
Example/test command after the iproute2 patch:
ip link set eth0 type bond_slave queue_id 10
CC: David S. Miller <davem@davemloft.net>
CC: Jay Vosburgh <j.vosburgh@gmail.com>
CC: Veaceslav Falico <vfalico@gmail.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Suggested-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
---
note: I intend to add a new option flag to indicate it's a slave option
so a new netdev notifier can be called (NETDEV_CHANGESLAVEINFODATA).
I believe the bonding is the first user of slave_changelink so I hope
I haven't missed anything. Once this patch is accepted in some form
I'll post the iproute2 one.
drivers/net/bonding/bond_netlink.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index d163e112f04c..1570deab112e 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -107,6 +107,33 @@ static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
return 0;
}
+static int bond_slave_changelink(struct net_device *bond_dev,
+ struct net_device *slave_dev,
+ struct nlattr *tb[], struct nlattr *data[])
+{
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct bond_opt_value newval;
+ int err;
+
+ if (!data)
+ return 0;
+
+ if (data[IFLA_BOND_SLAVE_QUEUE_ID]) {
+ u16 queue_id = nla_get_u16(data[IFLA_BOND_SLAVE_QUEUE_ID]);
+ char queue_id_str[IFNAMSIZ + 7];
+
+ /* queue_id option setting expects slave_name:queue_id */
+ snprintf(queue_id_str, sizeof(queue_id_str), "%s:%u\n",
+ slave_dev->name, queue_id);
+ bond_opt_initstr(&newval, queue_id_str);
+ err = __bond_opt_set(bond, BOND_OPT_QUEUE_ID, &newval);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int bond_changelink(struct net_device *bond_dev,
struct nlattr *tb[], struct nlattr *data[])
{
@@ -553,10 +580,12 @@ struct rtnl_link_ops bond_link_ops __read_mostly = {
.priv_size = sizeof(struct bonding),
.setup = bond_setup,
.maxtype = IFLA_BOND_MAX,
+ .slave_maxtype = IFLA_BOND_SLAVE_MAX,
.policy = bond_policy,
.validate = bond_validate,
.newlink = bond_newlink,
.changelink = bond_changelink,
+ .slave_changelink = bond_slave_changelink,
.get_size = bond_get_size,
.fill_info = bond_fill_info,
.get_num_tx_queues = bond_get_num_tx_queues,
--
1.9.3
^ permalink raw reply related
* Re: [PATCH 0/2] Get rid of ndo_xmit_flush
From: Jesper Dangaard Brouer @ 2014-08-27 13:56 UTC (permalink / raw)
To: Eric Dumazet
Cc: Hannes Frederic Sowa, David Miller, netdev, therbert, jhs,
edumazet, jeffrey.t.kirsher, rusty, dborkman, brouer
In-Reply-To: <1409145838.3173.41.camel@edumazet-glaptop2.roam.corp.google.com>
On Wed, 27 Aug 2014 06:23:58 -0700
Eric Dumazet <eric.dumazet@gmail.com> wrote:
> I am afraid Jesper tests are not complete to truly have a picture of the
> extra costs, because he made sure no false sharing was possible (A
> single cpu does everything and keeps skb in its cache)
I fully agree. My tests a very artificial benchmarks only for the
optimal case.
I do worry a bit, if writing skb->xmit_more in a more cache cold
scenarios could hurt us (as that cacheline seems to be read mostly),
but this is not a problem right now because it will always be cache
hot, as we always clear the entire SKB in alloc.
--
Best regards,
Jesper Dangaard Brouer
MSc.CS, Sr. Network Kernel Developer at Red Hat
Author of http://www.iptv-analyzer.org
LinkedIn: http://www.linkedin.com/in/brouer
^ permalink raw reply
* [PATCH REPOST net 2/2] mlx4: Set user-space raw Ethernet QPs to properly handle VXLAN traffic
From: Or Gerlitz @ 2014-08-27 13:47 UTC (permalink / raw)
To: davem; +Cc: netdev, amirv, Or Gerlitz
In-Reply-To: <1409147269-21472-1-git-send-email-ogerlitz@mellanox.com>
Raw Ethernet QPs opened from user-space lack the proper setup to
recieve/handle VXLAN traffic when VXLAN offloads are enabled.
Fix that by adding a tunnel steering rule on top of the normal unicast
steering rule and set the tunnel_type field in the QP context.
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
drivers/infiniband/hw/mlx4/main.c | 30 ++++++++++++++++++++++++++++++
drivers/infiniband/hw/mlx4/qp.c | 8 +++++++-
2 files changed, 37 insertions(+), 1 deletions(-)
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index e1e558a..af82563 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -1089,6 +1089,30 @@ static int __mlx4_ib_destroy_flow(struct mlx4_dev *dev, u64 reg_id)
return err;
}
+static int mlx4_ib_tunnel_steer_add(struct ib_qp *qp, struct ib_flow_attr *flow_attr,
+ u64 *reg_id)
+{
+ void *ib_flow;
+ union ib_flow_spec *ib_spec;
+ struct mlx4_dev *dev = to_mdev(qp->device)->dev;
+ int err = 0;
+
+ if (dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
+ return 0; /* do nothing */
+
+ ib_flow = flow_attr + 1;
+ ib_spec = (union ib_flow_spec *)ib_flow;
+
+ if (ib_spec->type != IB_FLOW_SPEC_ETH || flow_attr->num_of_specs != 1)
+ return 0; /* do nothing */
+
+ err = mlx4_tunnel_steer_add(to_mdev(qp->device)->dev, ib_spec->eth.val.dst_mac,
+ flow_attr->port, qp->qp_num,
+ MLX4_DOMAIN_UVERBS | (flow_attr->priority & 0xff),
+ reg_id);
+ return err;
+}
+
static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
struct ib_flow_attr *flow_attr,
int domain)
@@ -1136,6 +1160,12 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
i++;
}
+ if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) {
+ err = mlx4_ib_tunnel_steer_add(qp, flow_attr, &mflow->reg_id[i]);
+ if (err)
+ goto err_free;
+ }
+
return &mflow->ibflow;
err_free:
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 6778045..efb9eff 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1677,9 +1677,15 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
}
}
- if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET)
+ if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
context->pri_path.ackto = (context->pri_path.ackto & 0xf8) |
MLX4_IB_LINK_TYPE_ETH;
+ if (dev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
+ /* set QP to receive both tunneled & non-tunneled packets */
+ if (!(context->flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET)))
+ context->srqn = cpu_to_be32(7 << 28);
+ }
+ }
if (ibqp->qp_type == IB_QPT_UD && (new_state == IB_QPS_RTR)) {
int is_eth = rdma_port_get_link_layer(
--
1.7.1
^ permalink raw reply related
* [PATCH REPOST net 1/2] net/mlx4: Move the tunnel steering helper function to mlx4_core
From: Or Gerlitz @ 2014-08-27 13:47 UTC (permalink / raw)
To: davem; +Cc: netdev, amirv, Or Gerlitz
In-Reply-To: <1409147269-21472-1-git-send-email-ogerlitz@mellanox.com>
Move the function which we use to set VXLAN DMFS (flow-steering) rules
from mlx4_en to mlx4_core. This refactoring will allow the mlx4_ib driver
to call the helper for the use case of user-space RAW Ethernet QPs, such
that they can serve VXLAN traffic too.
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
---
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 31 +------------------
drivers/net/ethernet/mellanox/mlx4/mcg.c | 38 ++++++++++++++++++++++++
include/linux/mlx4/device.h | 3 ++
3 files changed, 43 insertions(+), 29 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index bb536aa..abddcf8 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -474,39 +474,12 @@ static int mlx4_en_tunnel_steer_add(struct mlx4_en_priv *priv, unsigned char *ad
int qpn, u64 *reg_id)
{
int err;
- struct mlx4_spec_list spec_eth_outer = { {NULL} };
- struct mlx4_spec_list spec_vxlan = { {NULL} };
- struct mlx4_spec_list spec_eth_inner = { {NULL} };
-
- struct mlx4_net_trans_rule rule = {
- .queue_mode = MLX4_NET_TRANS_Q_FIFO,
- .exclusive = 0,
- .allow_loopback = 1,
- .promisc_mode = MLX4_FS_REGULAR,
- .priority = MLX4_DOMAIN_NIC,
- };
-
- __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
return 0; /* do nothing */
- rule.port = priv->port;
- rule.qpn = qpn;
- INIT_LIST_HEAD(&rule.list);
-
- spec_eth_outer.id = MLX4_NET_TRANS_RULE_ID_ETH;
- memcpy(spec_eth_outer.eth.dst_mac, addr, ETH_ALEN);
- memcpy(spec_eth_outer.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
-
- spec_vxlan.id = MLX4_NET_TRANS_RULE_ID_VXLAN; /* any vxlan header */
- spec_eth_inner.id = MLX4_NET_TRANS_RULE_ID_ETH; /* any inner eth header */
-
- list_add_tail(&spec_eth_outer.list, &rule.list);
- list_add_tail(&spec_vxlan.list, &rule.list);
- list_add_tail(&spec_eth_inner.list, &rule.list);
-
- err = mlx4_flow_attach(priv->mdev->dev, &rule, reg_id);
+ err = mlx4_tunnel_steer_add(priv->mdev->dev, addr, priv->port, qpn,
+ MLX4_DOMAIN_NIC, reg_id);
if (err) {
en_err(priv, "failed to add vxlan steering rule, err %d\n", err);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx4/mcg.c b/drivers/net/ethernet/mellanox/mlx4/mcg.c
index d80e7a6..ca0f98c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/mcg.c
+++ b/drivers/net/ethernet/mellanox/mlx4/mcg.c
@@ -1020,6 +1020,44 @@ int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id)
}
EXPORT_SYMBOL_GPL(mlx4_flow_detach);
+int mlx4_tunnel_steer_add(struct mlx4_dev *dev, unsigned char *addr,
+ int port, int qpn, u16 prio, u64 *reg_id)
+{
+ int err;
+ struct mlx4_spec_list spec_eth_outer = { {NULL} };
+ struct mlx4_spec_list spec_vxlan = { {NULL} };
+ struct mlx4_spec_list spec_eth_inner = { {NULL} };
+
+ struct mlx4_net_trans_rule rule = {
+ .queue_mode = MLX4_NET_TRANS_Q_FIFO,
+ .exclusive = 0,
+ .allow_loopback = 1,
+ .promisc_mode = MLX4_FS_REGULAR,
+ };
+
+ __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+ rule.port = port;
+ rule.qpn = qpn;
+ rule.priority = prio;
+ INIT_LIST_HEAD(&rule.list);
+
+ spec_eth_outer.id = MLX4_NET_TRANS_RULE_ID_ETH;
+ memcpy(spec_eth_outer.eth.dst_mac, addr, ETH_ALEN);
+ memcpy(spec_eth_outer.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
+
+ spec_vxlan.id = MLX4_NET_TRANS_RULE_ID_VXLAN; /* any vxlan header */
+ spec_eth_inner.id = MLX4_NET_TRANS_RULE_ID_ETH; /* any inner eth header */
+
+ list_add_tail(&spec_eth_outer.list, &rule.list);
+ list_add_tail(&spec_vxlan.list, &rule.list);
+ list_add_tail(&spec_eth_inner.list, &rule.list);
+
+ err = mlx4_flow_attach(dev, &rule, reg_id);
+ return err;
+}
+EXPORT_SYMBOL(mlx4_tunnel_steer_add);
+
int mlx4_FLOW_STEERING_IB_UC_QP_RANGE(struct mlx4_dev *dev, u32 min_range_qpn,
u32 max_range_qpn)
{
diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h
index 071f6b2..511c6e0 100644
--- a/include/linux/mlx4/device.h
+++ b/include/linux/mlx4/device.h
@@ -1196,6 +1196,9 @@ int mlx4_map_sw_to_hw_steering_id(struct mlx4_dev *dev,
enum mlx4_net_trans_rule_id id);
int mlx4_hw_rule_sz(struct mlx4_dev *dev, enum mlx4_net_trans_rule_id id);
+int mlx4_tunnel_steer_add(struct mlx4_dev *dev, unsigned char *addr,
+ int port, int qpn, u16 prio, u64 *reg_id);
+
void mlx4_sync_pkey_table(struct mlx4_dev *dev, int slave, int port,
int i, int val);
--
1.7.1
^ permalink raw reply related
* [PATCH REPOST net 0/2] Setup mlx4 user space Ethernet QPs to properly handle VXLAN
From: Or Gerlitz @ 2014-08-27 13:47 UTC (permalink / raw)
To: davem; +Cc: netdev, amirv, Or Gerlitz
Hi Dave,
A repost -- with Gerrit labels removed
This short series fixes the mlx4 driver setting of user space Ethernet QPs
(e.g those opened by DPDK applications) such that they will properly handle
VXLAN traffic/offloads
Or.
Or Gerlitz (2):
net/mlx4: Move the tunnel steering helper function to mlx4_core
mlx4: Set user-space raw Ethernet QPs to properly handle VXLAN traffic
drivers/infiniband/hw/mlx4/main.c | 30 +++++++++++++++++++
drivers/infiniband/hw/mlx4/qp.c | 8 ++++-
drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 31 +------------------
drivers/net/ethernet/mellanox/mlx4/mcg.c | 38 ++++++++++++++++++++++++
include/linux/mlx4/device.h | 3 ++
5 files changed, 80 insertions(+), 30 deletions(-)
^ permalink raw reply
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