* Re: [PATCH nf-next 5/9] netfilter: conntrack: small refactoring of conntrack seq_printf
From: Pablo Neira Ayuso @ 2016-05-04 9:19 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel, netdev
In-Reply-To: <20160503222736.GK2395@breakpoint.cc>
On Wed, May 04, 2016 at 12:27:36AM +0200, Florian Westphal wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > > - if (NF_CT_DIRECTION(hash))
> > > - goto release;
> > > - if (nf_ct_l3num(ct) != AF_INET)
> > > + /* check if we raced w. object reuse */
> > > + if (!nf_ct_is_confirmed(ct) ||
> >
> > This refactoring includes this new check, is this intentional?
>
> Hmm, yes and no.
>
> I should have put it in an extra commit :-/
>
> Without this, we might erronously print a conntrack that is NEW
> and which isn't confirmed yet.
>
> We won't crash since seq_print doesn't depend on extensions being
> set up properly, but it seems better to only display those conntracks
> that are part of the conntrack hash table (i.e., have the confirmed bit
> set).
I see, a conntrack that shouldn't be printed be sneak in the listing.
> Let me know if you want me to respin this as a separate fix, thanks!
I will just append a notice on the commit message before applying.
^ permalink raw reply
* Re: [PATCH net-next v2] block/drbd: use nla_put_u64_64bit()
From: Lars Ellenberg @ 2016-05-04 9:05 UTC (permalink / raw)
To: David Miller
Cc: netdev-u79uwXL29TY76Z2rM5mHXA,
nicolas.dichtel-pdR9zngts4EAvxtiuMwx3w,
philipp.reisner-63ez5xqkn6DQT0dZR+AlfA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
drbd-dev-cunTk1MwBs8qoQakbn7OcQ
In-Reply-To: <20160503.120556.1317913903199470646.davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>
On Tue, May 03, 2016 at 12:05:56PM -0400, David Miller wrote:
> From: Lars Ellenberg <lars.ellenberg-63ez5xqkn6DQT0dZR+AlfA@public.gmane.org>
> Date: Tue, 3 May 2016 12:06:44 +0200
>
> > Please just NOT use an additional "field",
> > but always use 0 to pad.
>
> You can't, it doesn't work.
I did, and it *did* work.
At least, it appeared to.
I'm not talking about every user of netlink out there.
That I don't know. But specifically for DRBD netlink,
from what my experiments tell me, it works just fine.
> We are adding a new field to every netlink protocol family that has
> this alignment problem.
We don't have an "alignment problem" there, btw.
Last time I checked, we did work fine without this alignment magic,
we already take care of that, yes, even on affected architectures.
On Tue, May 03, 2016 at 12:06:52PM -0400, David Miller wrote:
> From: Lars Ellenberg <lars.ellenberg-63ez5xqkn6DQT0dZR+AlfA@public.gmane.org>
> Date: Tue, 3 May 2016 12:06:44 +0200
>
> > Whereas using some arbitrary value will be wrong,
> > and will needlessly break userland.
>
> It cannot break userland.
It can, if those tags have been used already.
There is DRBD out-of-tree as well,
it usually is ahead of in-tree DRBD.
But yes, I could obviously check and assign and reserve some
not-yet-used tag to all of them.
I don't see why, though, given that 0 (appearently) works fine.
Can you elaborate why and how that does not work?
Lars
^ permalink raw reply
* 我的联系方式在
From: 我的联系方式在 @ 2016-05-04 8:41 UTC (permalink / raw)
To: netdev
你的小姐妹邀你加Q群:546645595 抢红包。
^ permalink raw reply
* Re: [PATCH next-next 2/7] gre: Move utility functions to common headers
From: Jiri Benc @ 2016-05-04 8:35 UTC (permalink / raw)
To: David Miller; +Cc: tom, netdev, kernel-team
In-Reply-To: <20160504.005316.762406965746230352.davem@davemloft.net>
On Wed, 04 May 2016 00:53:16 -0400 (EDT), David Miller wrote:
> From: Jiri Benc <jbenc@redhat.com>
> Date: Tue, 3 May 2016 13:29:44 +0200
>
> > How do we resolve the conflict between net and net-next? I'd prefer
> > gre_parse_header to return the header length. I can submit a patch for
> > net-next that does this; that would substantially ease the merge.
>
> Jiri, I just did the net --> net-next merge. Please send me something on
> top of that which does what you like.
The patch http://patchwork.ozlabs.org/patch/617940/ still applies and
does the right thing even post merge.
Note that the merge reintroduced the bug fixed by b7f8fe251e46 (the
mentioned patch fixes this, too).
Thanks,
Jiri
^ permalink raw reply
* Re: [PATCH 2/2] mac80211_hwsim: Allow managing radios from non-initial namespaces
From: Martin Willi @ 2016-05-04 8:33 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-wireless-u79uwXL29TY76Z2rM5mHXA,
netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1462302992.10444.11.camel-cdvu00un1VgdHxzADdlk8Q@public.gmane.org>
> > +static __net_init int hwsim_init_net(struct net *net)
> > +{
> > + struct mac80211_hwsim_data *data;
> > + bool exists = true;
> > + int netgroup = 0;
> > +
> > + spin_lock_bh(&hwsim_radio_lock);
> > + while (exists) {
> > + exists = false;
> > + list_for_each_entry(data, &hwsim_radios, list) {
> > + if (netgroup == data->netgroup) {
> > + exists = true;
> > + netgroup++;
> > + break;
> > + }
> > + }
> > + }
> > + spin_unlock_bh(&hwsim_radio_lock);
> > +
> > + *(int *)net_generic(net, hwsim_net_id) = netgroup;
>
> This seems somewhat awkward. Why not just take the maximum of all the
> netgroup IDs + 1? We'd run out of memory and radio IDs long before
> netgroup IDs even that way
My intention was to reuse netgroups for the case many namespaces come
and go, but I agree that it is not optimal.
> consider a new netns that doesn't have any hwsim radios yet.
> Now you create *another* one, but it would get the same netgroup.
Correct, that is indeed broken if there are no radios.
> IOW, you should simply use a global counter. Surprising (net)
> namespaces don't have an index like that already, but I don't see
> one.
Ok, will do that in a v2.
> > +static void __net_exit hwsim_exit_net(struct net *net)
> > +{
> > + struct mac80211_hwsim_data *entry, *tmp;
> > +
> > + spin_lock_bh(&hwsim_radio_lock);
> > + list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) {
> > + if (net_eq(wiphy_net(entry->hw->wiphy), net)) {
> > + list_del(&entry->list);
> > + INIT_WORK(&entry->destroy_work, destroy_radio);
> > + schedule_work(&entry->destroy_work);
> > + }
> > + }
> > + spin_unlock_bh(&hwsim_radio_lock);
> > +}
> This changes today's default behaviour of moving the wiphys to the
> default namespace. Did you intend to destroy them based on the
> netgroup, i.e. based on the namespace that created them? Actually,
> maybe they should move back to the namespace that created them, if
> the namespace they are in is destroyed? But that's difficult, I don't
> mind this behaviour, but I'm not sure it's what we want by default
> for radios created in the init_net.
With the proposed approach I destroy all radios if the owning namespace
gets deleted, because we probably don't want them landing in init_net
if they are created from a (unprivileged) userns process. I think this
is what other "virtual" interfaces do (gre tunnels, veth etc.). If we
think of hwsim radios as such a "virtual" device, that makes IMO sense
to delete them.
If we want to keep the existing behavior, we could move radios
belonging to the init_net-associated netgroup back to init_net, that
shouldn't be too difficult.
Moving the radio back to the creators namespace would be the most
consistent behavior, so I'll check how difficult such a reverse lookup
is. We then would delete the radio only if it is in the creators
namespace, or if the creators namespace is gone. Does that make sense?
Martin
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH net-next 4/5] treewide: replace dev->trans_start update with helper
From: Felipe Balbi @ 2016-05-04 8:14 UTC (permalink / raw)
To: Florian Westphal, netdev
Cc: devel, linux-xtensa, linux-omap, linux-scsi,
user-mode-linux-devel, linux-s390, linux-rdma, linux-wireless,
linux-usb, Florian Westphal, linux-can, linux-bluetooth,
linux-parisc, b.a.t.m.a.n, linux-hams, linux1394-devel,
MPT-FusionLinux.pdl
In-Reply-To: <1462285994-31983-1-git-send-email-fw@strlen.de>
[-- Attachment #1.1: Type: text/plain, Size: 1517 bytes --]
Hi,
Florian Westphal <fw@strlen.de> writes:
> Replace all trans_start updates with netif_trans_update helper.
> change was done via spatch:
>
> struct net_device *d;
> @@
> - d->trans_start = jiffies
> + netif_trans_update(d)
>
> Compile tested only.
>
> Cc: user-mode-linux-devel@lists.sourceforge.net
> Cc: linux-xtensa@linux-xtensa.org
> Cc: linux1394-devel@lists.sourceforge.net
> Cc: linux-rdma@vger.kernel.org
> Cc: netdev@vger.kernel.org
> Cc: MPT-FusionLinux.pdl@broadcom.com
> Cc: linux-scsi@vger.kernel.org
> Cc: linux-can@vger.kernel.org
> Cc: linux-parisc@vger.kernel.org
> Cc: linux-omap@vger.kernel.org
> Cc: linux-hams@vger.kernel.org
> Cc: linux-usb@vger.kernel.org
> Cc: linux-wireless@vger.kernel.org
> Cc: linux-s390@vger.kernel.org
> Cc: devel@driverdev.osuosl.org
> Cc: b.a.t.m.a.n@lists.open-mesh.org
> Cc: linux-bluetooth@vger.kernel.org
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
for u_ether.c:
Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>
> diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
> index 637809e..a3f7e7c 100644
> --- a/drivers/usb/gadget/function/u_ether.c
> +++ b/drivers/usb/gadget/function/u_ether.c
> @@ -597,7 +597,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
> DBG(dev, "tx queue err %d\n", retval);
> break;
> case 0:
> - net->trans_start = jiffies;
> + netif_trans_update(net);
> atomic_inc(&dev->tx_qlen);
> }
--
balbi
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]
[-- Attachment #2: Type: text/plain, Size: 169 bytes --]
_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
^ permalink raw reply
* Re: [REGRESSION] asix: Lots of asix_rx_fixup() errors and slow transmissions
From: Dean Jenkins @ 2016-05-04 7:58 UTC (permalink / raw)
To: David B. Robins, Dean Jenkins
Cc: John Stultz, lkml, Mark Craske, David S. Miller, YongQin Liu,
Guodong Xu, linux-usb, netdev, Ivan Vecera
In-Reply-To: <e4efd48d3c16c27de68d464ad3170b02@i4031.net>
On 04/05/16 01:28, David B. Robins wrote:
>
>>
>> Here is the code snippet from the patch with my annotations between #
>> #, I will try to explain my intentions. Feel free to point out any
>> flaws:
>>
>> if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
>> # Only runs when rx->remaining !=0 and the end of the Ethernet
>> frame + next 32-bit header word is within the URB buffer. #
>> # Therefore, this code does not run when the end of an
>> Ethernet frame has been reached in the previous URB #
>> # or when the end of the Ethernet frame + next 32-bit header
>> word will be in a later URB buffer #
>
> It may well be. I don't have the setup with me now, but I can try
> tomorrow to reproduce an environment where I can add some more
> detailed logging.
>
> Since the URB length has to be >= than the remaining data plus a u32,
> the devices that John Stultz and I are using (AX88772B in my case) may
> be adding some additional data/padding after an Ethernet frame,
> expecting it to be discarded, and running into this check and its
> consequences. This may mean the device is badly behaved, if it is
> specified not to send anything extra; in any case, a well-intentioned
> error correction has gone badly, but I better understand the intent
> now. I am curious to know how often the device you are using benefits
> from this block of code.
The issue is that the driver should be robust to cope with missing URBs.
Whilst testing with D-Link DUB-E100 C1 AX88772 USB to Ethernet adaptor
in our ARM embedded system which runs in hostile environments, it was
noticed that URBs could be lost (probably due to a bug elsewhere or low
memory issue). Without this patch, a missing URB causes bad Ethernet
frames to be passed up to the IP stack because rx->remaining spans
multiple URBs.
In the good case of an Ethernet frame spanning 2 URBs, the 1st URB is
processed and copies the 1st part of the Ethernet frame into the netdev
buffer, for the 2nd URB the remaining part of the Ethernet frame is
copied into the same netdev buffer to complete the Ethernet frame. The
netdev buffer is then sent up to the IP stack.
In the case of a missing URB, a bad Ethernet frame is created as follows:
The 1st URB is processed and copies the 1st part of the Ethernet frame
into the netdev buffer, the 2nd URB is lost (somehow), the 3rd URB is
processed and blindly copies what it thinks is the remaining part of the
Ethernet frame in the same netdev buffer which corrupts the Ethernet
frame. The netdev buffer is then sent up to the IP stack. The 3rd URB
and subsequent URBs are processed but synchronisation has been lost so
can misread data as a 32-bit header word. It is likely that some good
Ethernet frames get discarded whilst trying to resynchronise.
A recovery strategy for regaining lock with the 32-bit header word is
necessary otherwise the driver will have difficulty in recovering from a
lost URB.
In the "olden days", the 32-bit header word was always at the start of
the URB buffer so previous URBs did not influence the current URB. So no
recovery strategy was needed at that time. But now we have to remember
what happened in the previous URB and a lost URB can cause a
discontinuity in the data stream because the data is not always aligned
to the start of the URB buffer.
I agree that your environment may never suffer from lost URBs so removal
of the patch would work OK.
I will try to find some time to setup a test environment.
Regards,
Dean
--
Dean Jenkins
Embedded Software Engineer
Linux Transportation Solutions
Mentor Embedded Software Division
Mentor Graphics (UK) Ltd.
^ permalink raw reply
* Re: [PATCH net-next 0/3] gre: receive also TEB packets for lwtunnels
From: Simon Horman @ 2016-05-04 7:52 UTC (permalink / raw)
To: Jiri Benc; +Cc: netdev, Thomas Graf, pravin shelar
In-Reply-To: <cover.1462286214.git.jbenc@redhat.com>
On Tue, May 03, 2016 at 05:10:05PM +0200, Jiri Benc wrote:
> NOTE: this patchset needs net merged to net-next.
>
> This allows lwtunnel users to get also packets with ETH_P_TEB protocol
> specified in GRE header through an ipgre interface. There's really nothing
> special about these packets in the case of lwtunnels - it's just an inner
> protocol like any other. The only complications stem from keeping
> compatibility with other uses of GRE.
>
> This will be used by openvswitch to support eth_push and eth_pop actions.
> I'd also like to see tc support for lwtunnels (this feature included) in the
> future.
>
> The first patch is not directly related and can be submitted standalone if
> needed.
I have exercised this patch-set using Open vSwitch both with
and without the patchset I posted earlier this afternoon to
make use of this new feature:
"[PATCH v9 net-next 0/7] openvswitch: support for layer 3 encapsulated packets"
All three patches:
Tested-by: Simon Horman <simon.horman@netronome.com>
> Jiri Benc (3):
> gre: remove superfluous pskb_may_pull
> gre: move iptunnel_pull_header down to ipgre_rcv
> gre: receive also TEB packets for lwtunnels
>
> include/net/ip_tunnels.h | 1 +
> net/ipv4/gre_demux.c | 5 +----
> net/ipv4/ip_gre.c | 48 +++++++++++++++++++++++++++++++++++-------------
> 3 files changed, 37 insertions(+), 17 deletions(-)
>
> --
> 1.8.3.1
>
^ permalink raw reply
* Re: [v9, 6/7] MAINTAINERS: add entry for Freescale SoC driver
From: Ulf Hansson @ 2016-05-04 7:43 UTC (permalink / raw)
To: Yangbo Lu, Scott Wood, Qiang Zhao
Cc: linux-mmc, linuxppc-dev@lists.ozlabs.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-clk,
linux-i2c@vger.kernel.org, iommu, netdev, Mark Rutland,
Rob Herring, Russell King, Jochen Friedrich, Joerg Roedel,
Claudiu Manoil, Bhupesh Sharma, Kumar Gala, Santosh Shilimkar,
Yang-Leo Li, Xiaobo Xie
In-Reply-To: <1462332274-13744-7-git-send-email-yangbo.lu@nxp.com>
On 4 May 2016 at 05:24, Yangbo Lu <yangbo.lu@nxp.com> wrote:
> Add maintainer entry for Freescale SoC driver including
> the QE library and the GUTS driver now. Also add maintainer
> for QE library.
>
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
So I need an ack from Scott and Qiang for this one, then I intend to
queue up the series.
Kind regards
Uffe
> ---
> Changes for v8:
> - Added this patch
> Changes for v9:
> - Added linux-arm mail list
> - Removed GUTS driver entry
> ---
> MAINTAINERS | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 42e65d1..ce91db7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4622,9 +4622,18 @@ F: drivers/net/ethernet/freescale/fec_ptp.c
> F: drivers/net/ethernet/freescale/fec.h
> F: Documentation/devicetree/bindings/net/fsl-fec.txt
>
> +FREESCALE SOC DRIVER
> +M: Scott Wood <oss@buserror.net>
> +L: linuxppc-dev@lists.ozlabs.org
> +L: linux-arm-kernel@lists.infradead.org
> +S: Maintained
> +F: drivers/soc/fsl/
> +F: include/linux/fsl/
> +
> FREESCALE QUICC ENGINE LIBRARY
> +M: Qiang Zhao <qiang.zhao@nxp.com>
> L: linuxppc-dev@lists.ozlabs.org
> -S: Orphan
> +S: Maintained
> F: drivers/soc/fsl/qe/
> F: include/soc/fsl/*qe*.h
> F: include/soc/fsl/*ucc*.h
> --
> 2.1.0.27.g96db324
>
^ permalink raw reply
* [PATCH v9 net-next 6/7] openvswitch: extend layer 3 support to cover non-IP packets
From: Simon Horman @ 2016-05-04 7:36 UTC (permalink / raw)
To: netdev, dev; +Cc: Simon Horman
In-Reply-To: <1462347393-22354-1-git-send-email-simon.horman@netronome.com>
Extend support for layer 3 packets to cover non-IP packets.
This removes the assumption that the first octet of a layer 3 packet
indicates the IP protocol version - true for IP (v4 and v6), but not
for necessarily for other protocols.
The key motivation for this is to allow forwarding of MPLS packets which
are technically layer 2.5 rather than 3 but the distinction seems unimportant
here.
This sets OVS_KEY_ATTR_PACKET_ETHERTYPE to the ethernet type corresponding
to the protocol of layer 3 packets on a flow miss.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v9
* New patch
---
net/openvswitch/flow_netlink.c | 121 ++++++++++++++++++++---------------------
1 file changed, 59 insertions(+), 62 deletions(-)
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 2bca1e5e9a18..1e1392c3c0ed 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -817,7 +817,7 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
u64 *attrs, const struct nlattr **a,
bool is_mask, bool log)
{
- bool is_layer3;
+ bool is_layer3 = false;
if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
@@ -906,48 +906,40 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
}
- /* For full flow keys the layer is determined based on the presence of
- * OVS_KEY_ATTR_ETHERNET
- */
- if (is_mask)
- /* Always exact match is_layer3 */
- is_layer3 = true;
- else
- is_layer3 = !(*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET));
- /* Packets from user space for execution only have metadata key
- * attributes. OVS_KEY_ATTR_PACKET_ETHERTYPE is then used to specify
- * the starting layer of the packet. Packets with Ethernet headers
- * have this attribute set to 0
+ /* For layer 3 packets the ethernet type is provided by by the
+ * metadata field OVS_KEY_ATTR_PACKET_ETHERTYPE which has a
+ * non-zero value. Otherwise the ethernet type is provided by the
+ * packet and reflected by OVS_KEY_ATTR_PACKET_ETHERTYPE.
*/
if (*attrs & (1ULL << OVS_KEY_ATTR_PACKET_ETHERTYPE)) {
+ /* This is duplicate code from ovs_key_from_nlattrs*/
__be16 eth_type;
- if (is_mask) {
+ if (is_mask)
/* Always exact match packet EtherType */
eth_type = htons(0xffff);
- } else {
+ else
eth_type = nla_get_be16(a[OVS_KEY_ATTR_PACKET_ETHERTYPE]);
- is_layer3 = ((eth_type == htons(ETH_P_IP)) ||
- (eth_type == htons(ETH_P_IPV6)));
+
+ if (eth_type != htons(0)) {
+ is_layer3 = true;
+ SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
}
- SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
+
+ *attrs &= ~(1ULL << OVS_KEY_ATTR_PACKET_ETHERTYPE);
}
- SW_FLOW_KEY_PUT(match, phy.is_layer3, is_layer3, is_mask);
- return 0;
+ /* Always exact match is_layer3 */
+ SW_FLOW_KEY_PUT(match, phy.is_layer3, is_mask ? true : is_layer3,
+ is_mask);
+ return is_layer3;
}
-static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
- u64 attrs, const struct nlattr **a,
- bool is_mask, bool log)
+static int l2_from_nlattrs(struct net *net, struct sw_flow_match *match,
+ u64 *attrs, const struct nlattr **a,
+ bool is_mask, bool log)
{
- int err;
-
- err = metadata_from_nlattrs(net, match, &attrs, a, is_mask, log);
- if (err)
- return err;
-
- if (attrs & (1 << OVS_KEY_ATTR_ETHERNET)) {
+ if (*attrs & (1 << OVS_KEY_ATTR_ETHERNET)) {
const struct ovs_key_ethernet *eth_key;
eth_key = nla_data(a[OVS_KEY_ATTR_ETHERNET]);
@@ -955,10 +947,10 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
eth_key->eth_src, ETH_ALEN, is_mask);
SW_FLOW_KEY_MEMCPY(match, eth.dst,
eth_key->eth_dst, ETH_ALEN, is_mask);
- attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET);
+ *attrs &= ~(1 << OVS_KEY_ATTR_ETHERNET);
}
- if (attrs & (1 << OVS_KEY_ATTR_VLAN)) {
+ if (*attrs & (1 << OVS_KEY_ATTR_VLAN)) {
__be16 tci;
tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
@@ -972,10 +964,10 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
}
SW_FLOW_KEY_PUT(match, eth.tci, tci, is_mask);
- attrs &= ~(1 << OVS_KEY_ATTR_VLAN);
+ *attrs &= ~(1 << OVS_KEY_ATTR_VLAN);
}
- if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
+ if (*attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
__be16 eth_type;
eth_type = nla_get_be16(a[OVS_KEY_ATTR_ETHERTYPE]);
@@ -989,24 +981,34 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
}
SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
- attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
+ *attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
} else if (!is_mask) {
SW_FLOW_KEY_PUT(match, eth.type, htons(ETH_P_802_2), is_mask);
}
- if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
- const struct ovs_key_ipv4 *ipv4_key;
+ return 0;
+}
- /* Add eth.type value for layer 3 flows */
- if (!(attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE))) {
- __be16 eth_type;
+static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
+ u64 attrs, const struct nlattr **a,
+ bool is_mask, bool log)
+{
+ int err;
+ bool is_layer3;
- if (is_mask)
- eth_type = htons(0xffff);
- else
- eth_type = htons(ETH_P_IP);
- SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
- }
+ err = metadata_from_nlattrs(net, match, &attrs, a, is_mask, log);
+ if (err < 0)
+ return err;
+ is_layer3 = err != 0;
+
+ if (!is_layer3) {
+ err = l2_from_nlattrs(net, match, &attrs, a, is_mask, log);
+ if (err < 0)
+ return err;
+ }
+
+ if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
+ const struct ovs_key_ipv4 *ipv4_key;
ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
@@ -1032,17 +1034,6 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
const struct ovs_key_ipv6 *ipv6_key;
- /* Add eth.type value for layer 3 flows */
- if (!(attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE))) {
- __be16 eth_type;
-
- if (is_mask)
- eth_type = htons(0xffff);
- else
- eth_type = htons(ETH_P_IPV6);
- SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
- }
-
ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
OVS_NLERR(log, "IPv6 frag type %d is out of range max %d",
@@ -1465,7 +1456,11 @@ int ovs_nla_get_flow_metadata(struct net *net, const struct nlattr *attr,
memset(&key->ct, 0, sizeof(key->ct));
key->phy.in_port = DP_MAX_PORTS;
- return metadata_from_nlattrs(net, &match, &attrs, a, false, log);
+ err = metadata_from_nlattrs(net, &match, &attrs, a, false, log);
+ if (err < 0)
+ return err;
+
+ return 0;
}
static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
@@ -1551,6 +1546,10 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type))
goto nla_put_failure;
+ } else {
+ if (nla_put_be16(skb, OVS_KEY_ATTR_PACKET_ETHERTYPE,
+ output->eth.type))
+ goto nla_put_failure;
}
if (swkey->eth.type == htons(ETH_P_IP)) {
@@ -2184,8 +2183,6 @@ static int validate_set(const struct nlattr *a,
break;
case OVS_KEY_ATTR_MPLS:
- if (is_layer3)
- return -EINVAL;
if (!eth_p_mpls(eth_type))
return -EINVAL;
break;
@@ -2360,7 +2357,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
case OVS_ACTION_ATTR_PUSH_MPLS: {
const struct ovs_action_push_mpls *mpls = nla_data(a);
- if (is_layer3 || !eth_p_mpls(mpls->mpls_ethertype))
+ if (!eth_p_mpls(mpls->mpls_ethertype))
return -EINVAL;
/* Prohibit push MPLS other than to a white list
* for packets that have a known tag order.
@@ -2377,7 +2374,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
}
case OVS_ACTION_ATTR_POP_MPLS:
- if (is_layer3 || vlan_tci & htons(VLAN_TAG_PRESENT) ||
+ if (vlan_tci & htons(VLAN_TAG_PRESENT) ||
!eth_p_mpls(eth_type))
return -EINVAL;
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related
* [PATCH v9 net-next 7/7] openvswitch: use ipgre tunnel rather than gretap tunnel
From: Simon Horman @ 2016-05-04 7:36 UTC (permalink / raw)
To: netdev, dev; +Cc: Simon Horman
In-Reply-To: <1462347393-22354-1-git-send-email-simon.horman@netronome.com>
This allows GRE tunnels to send and receive both
layer 2 packets (packets with an ethernet header) and
layer 3 packets (packets without an ethernet header).
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v9
New Patch
---
include/net/gre.h | 4 ++--
net/ipv4/ip_gre.c | 8 ++++----
net/openvswitch/vport-gre.c | 4 ++--
net/openvswitch/vport-netdev.c | 12 +++++++++++-
net/openvswitch/vport-netdev.h | 1 +
5 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/include/net/gre.h b/include/net/gre.h
index 29e37322c06e..181357d124b1 100644
--- a/include/net/gre.h
+++ b/include/net/gre.h
@@ -23,8 +23,8 @@ struct gre_protocol {
int gre_add_protocol(const struct gre_protocol *proto, u8 version);
int gre_del_protocol(const struct gre_protocol *proto, u8 version);
-struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
- u8 name_assign_type);
+struct net_device *gre_fb_dev_create(struct net *net, const char *name,
+ u8 name_assign_type);
int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
bool *csum_err, int *hdr_len);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 52011f78e3c7..d542812217d7 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1114,8 +1114,8 @@ static struct rtnl_link_ops ipgre_tap_ops __read_mostly = {
.get_link_net = ip_tunnel_get_link_net,
};
-struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
- u8 name_assign_type)
+struct net_device *gre_fb_dev_create(struct net *net, const char *name,
+ u8 name_assign_type)
{
struct nlattr *tb[IFLA_MAX + 1];
struct net_device *dev;
@@ -1125,7 +1125,7 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
memset(&tb, 0, sizeof(tb));
dev = rtnl_create_link(net, name, name_assign_type,
- &ipgre_tap_ops, tb);
+ &ipgre_link_ops, tb);
if (IS_ERR(dev))
return dev;
@@ -1149,7 +1149,7 @@ out:
free_netdev(dev);
return ERR_PTR(err);
}
-EXPORT_SYMBOL_GPL(gretap_fb_dev_create);
+EXPORT_SYMBOL_GPL(gre_fb_dev_create);
static int __net_init ipgre_tap_init_net(struct net *net)
{
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index f003225de994..b1aa02904ae4 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -60,7 +60,7 @@ static struct vport *gre_tnl_create(const struct vport_parms *parms)
return vport;
rtnl_lock();
- dev = gretap_fb_dev_create(net, parms->name, NET_NAME_USER);
+ dev = gre_fb_dev_create(net, parms->name, NET_NAME_USER);
if (IS_ERR(dev)) {
rtnl_unlock();
ovs_vport_free(vport);
@@ -87,7 +87,7 @@ static struct vport *gre_create(const struct vport_parms *parms)
static struct vport_ops ovs_gre_vport_ops = {
.type = OVS_VPORT_TYPE_GRE,
.create = gre_create,
- .send = ovs_netdev_send_tap,
+ .send = ovs_netdev_send_raw_tun,
.destroy = ovs_netdev_tunnel_destroy,
};
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 0e0b9286dd11..e6a2718204a8 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -99,7 +99,8 @@ struct vport *ovs_netdev_link(struct vport *vport, const char *name)
}
if (vport->dev->flags & IFF_LOOPBACK ||
- vport->dev->type != ARPHRD_ETHER ||
+ (vport->dev->type != ARPHRD_ETHER &&
+ vport->dev->type != ARPHRD_IPGRE) ||
ovs_is_internal_dev(vport->dev)) {
err = -EINVAL;
goto error_put;
@@ -207,6 +208,15 @@ int ovs_netdev_send_tap(struct sk_buff *skb)
}
EXPORT_SYMBOL_GPL(ovs_netdev_send_tap);
+int ovs_netdev_send_raw_tun(struct sk_buff *skb)
+{
+ if (skb->mac_len)
+ skb->protocol = ntohs(ETH_P_TEB);
+
+ return dev_queue_xmit(skb);
+}
+EXPORT_SYMBOL_GPL(ovs_netdev_send_raw_tun);
+
/* Returns null if this device is not attached to a datapath. */
struct vport *ovs_netdev_get_vport(struct net_device *dev)
{
diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h
index 02f38a822334..ae59c02ba6a9 100644
--- a/net/openvswitch/vport-netdev.h
+++ b/net/openvswitch/vport-netdev.h
@@ -35,4 +35,5 @@ void ovs_netdev_exit(void);
void ovs_netdev_tunnel_destroy(struct vport *vport);
int ovs_netdev_send_tap(struct sk_buff *skb);
+int ovs_netdev_send_raw_tun(struct sk_buff *skb);
#endif /* vport_netdev.h */
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related
* [PATCH v9 net-next 4/7] openvswitch: add layer 3 flow/port support
From: Simon Horman @ 2016-05-04 7:36 UTC (permalink / raw)
To: netdev, dev; +Cc: Lorand Jakab, Thomas Morin, Simon Horman
In-Reply-To: <1462347393-22354-1-git-send-email-simon.horman@netronome.com>
From: Lorand Jakab <lojakab@cisco.com>
Implementation of the pop_eth and push_eth actions in the kernel, and
layer 3 flow support.
This doesn't actually do anything yet as no layer 2 tunnel ports are
supported yet. The original patch by Lorand was against the Open vSwtich
tree which has L2 LISP tunnels but that is not supported in mainline Linux.
I (Simon) plan to follow up with support for non-TEB GRE ports based on
work by Thomas Morin.
Cc: Thomas Morin <thomas.morin@orange.com>
Signed-off-by: Lorand Jakab <lojakab@cisco.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v9 [Simon Horman]
* Rebase
* Minor coding style updates
* Prohibit push/pop MPLS on l3 packets
* There are no layer 3 ports supported at this time so only
send and receive layer 2 packets: that is don't actually
use this new infrastructure yet
* Expect that vports that can handle layer 3 packets will: have
a type other than ARPHRD_IPETHER; can also handle layer 2 packets;
and that packets can be differentiated by layer 2 packets having
skb->protocol set to htons(ETH_P_TEB)
v1 - v8 [Lorand Jakub]
---
include/uapi/linux/openvswitch.h | 12 +++
net/openvswitch/actions.c | 48 ++++++++++++
net/openvswitch/flow.c | 63 ++++++++++-----
net/openvswitch/flow.h | 4 +-
net/openvswitch/flow_netlink.c | 148 +++++++++++++++++++++++++----------
net/openvswitch/vport-geneve.c | 2 +-
net/openvswitch/vport-gre.c | 2 +-
net/openvswitch/vport-internal_dev.c | 6 ++
net/openvswitch/vport-netdev.c | 19 ++++-
net/openvswitch/vport-netdev.h | 2 +
net/openvswitch/vport-vxlan.c | 2 +-
11 files changed, 240 insertions(+), 68 deletions(-)
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index bb0d515b7654..53129c03273c 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -699,6 +699,16 @@ enum ovs_nat_attr {
#define OVS_NAT_ATTR_MAX (__OVS_NAT_ATTR_MAX - 1)
+/*
+ * struct ovs_action_push_eth - %OVS_ACTION_ATTR_PUSH_ETH action argument.
+ * @addresses: Source and destination MAC addresses.
+ * @eth_type: Ethernet type
+ */
+struct ovs_action_push_eth {
+ struct ovs_key_ethernet addresses;
+ __be16 eth_type;
+};
+
/**
* enum ovs_action_attr - Action types.
*
@@ -756,6 +766,8 @@ enum ovs_action_attr {
* The data must be zero for the unmasked
* bits. */
OVS_ACTION_ATTR_CT, /* Nested OVS_CT_ATTR_* . */
+ OVS_ACTION_ATTR_PUSH_ETH, /* struct ovs_action_push_eth. */
+ OVS_ACTION_ATTR_POP_ETH, /* No argument. */
__OVS_ACTION_ATTR_MAX, /* Nothing past this will be accepted
* from userspace. */
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index fe885a89f501..63d29263d51a 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -291,6 +291,46 @@ static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *flow_key,
return 0;
}
+static int pop_eth(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ skb_pull_rcsum(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+ skb->mac_len -= ETH_HLEN;
+
+ invalidate_flow_key(key);
+ return 0;
+}
+
+static int push_eth(struct sk_buff *skb, struct sw_flow_key *key,
+ const struct ovs_action_push_eth *ethh)
+{
+ int err;
+
+ /* De-accelerate any hardware accelerated VLAN tag added to a previous
+ * Ethernet header */
+ err = skb_vlan_deaccel(skb);
+ if (unlikely(err))
+ return err;
+
+ /* Add the new Ethernet header */
+ if (skb_cow_head(skb, ETH_HLEN) < 0)
+ return -ENOMEM;
+
+ skb_push(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+ skb_reset_mac_len(skb);
+
+ ether_addr_copy(eth_hdr(skb)->h_source, ethh->addresses.eth_src);
+ ether_addr_copy(eth_hdr(skb)->h_dest, ethh->addresses.eth_dst);
+ eth_hdr(skb)->h_proto = ethh->eth_type;
+
+ skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
+
+ skb->protocol = ethh->eth_type;
+ invalidate_flow_key(key);
+ return 0;
+}
+
static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
__be32 addr, __be32 new_addr)
{
@@ -1079,6 +1119,14 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
err = pop_vlan(skb, key);
break;
+ case OVS_ACTION_ATTR_PUSH_ETH:
+ err = push_eth(skb, key, nla_data(a));
+ break;
+
+ case OVS_ACTION_ATTR_POP_ETH:
+ err = pop_eth(skb, key);
+ break;
+
case OVS_ACTION_ATTR_RECIRC:
err = execute_recirc(dp, skb, key, a, rem);
if (nla_is_last(a, rem)) {
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 0ea128eeeab2..6e174ea5f2bb 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -468,28 +468,31 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
skb_reset_mac_header(skb);
- /* Link layer. We are guaranteed to have at least the 14 byte Ethernet
- * header in the linear data area.
- */
- eth = eth_hdr(skb);
- ether_addr_copy(key->eth.src, eth->h_source);
- ether_addr_copy(key->eth.dst, eth->h_dest);
+ /* Link layer. */
+ if (key->phy.is_layer3) {
+ key->eth.tci = 0;
+ key->eth.type = skb->protocol;
+ } else {
+ eth = eth_hdr(skb);
+ ether_addr_copy(key->eth.src, eth->h_source);
+ ether_addr_copy(key->eth.dst, eth->h_dest);
- __skb_pull(skb, 2 * ETH_ALEN);
- /* We are going to push all headers that we pull, so no need to
- * update skb->csum here.
- */
+ __skb_pull(skb, 2 * ETH_ALEN);
+ /* We are going to push all headers that we pull, so no need to
+ * update skb->csum here.
+ */
- key->eth.tci = 0;
- if (skb_vlan_tag_present(skb))
- key->eth.tci = htons(skb->vlan_tci);
- else if (eth->h_proto == htons(ETH_P_8021Q))
- if (unlikely(parse_vlan(skb, key)))
- return -ENOMEM;
+ key->eth.tci = 0;
+ if (skb_vlan_tag_present(skb))
+ key->eth.tci = htons(skb->vlan_tci);
+ else if (eth->h_proto == htons(ETH_P_8021Q))
+ if (unlikely(parse_vlan(skb, key)))
+ return -ENOMEM;
- key->eth.type = parse_ethertype(skb);
- if (unlikely(key->eth.type == htons(0)))
- return -ENOMEM;
+ key->eth.type = parse_ethertype(skb);
+ if (unlikely(key->eth.type == htons(0)))
+ return -ENOMEM;
+ }
skb_reset_network_header(skb);
skb_reset_mac_len(skb);
@@ -696,11 +699,23 @@ int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
struct sk_buff *skb, struct sw_flow_key *key)
{
+ bool is_layer3 = false;
+ bool is_teb = false;
+ int err;
+
/* Extract metadata from packet. */
if (tun_info) {
key->tun_proto = ip_tunnel_info_af(tun_info);
memcpy(&key->tun_key, &tun_info->key, sizeof(key->tun_key));
+ if (OVS_CB(skb)->input_vport->dev->type != ARPHRD_ETHER) {
+ if (skb->protocol == htons(ETH_P_TEB))
+ is_teb = true;
+ else
+ is_layer3 = true;
+ }
+
+
if (tun_info->options_len) {
BUILD_BUG_ON((1 << (sizeof(tun_info->options_len) *
8)) - 1
@@ -723,9 +738,17 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
key->phy.skb_mark = skb->mark;
ovs_ct_fill_key(skb, key);
key->ovs_flow_hash = 0;
+ key->phy.is_layer3 = is_layer3;
key->recirc_id = 0;
- return key_extract(skb, key);
+ err = key_extract(skb, key);
+ if (err < 0)
+ return err;
+
+ if (is_teb)
+ skb->protocol = key->eth.type;
+
+ return err;
}
int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 03378e75a67c..5395ec0c3c13 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -62,6 +62,7 @@ struct sw_flow_key {
u32 priority; /* Packet QoS priority. */
u32 skb_mark; /* SKB mark. */
u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
+ bool is_layer3; /* Packet has no Ethernet header */
} __packed phy; /* Safe when right after 'tun_key'. */
u8 tun_proto; /* Protocol of encapsulating tunnel. */
u32 ovs_flow_hash; /* Datapath computed hash value. */
@@ -219,8 +220,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key);
int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
- struct sk_buff *skb,
- struct sw_flow_key *key);
+ struct sk_buff *skb, struct sw_flow_key *key);
/* Extract key from packet coming from userspace. */
int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr,
struct sk_buff *skb,
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 0bb650f4f219..d0ef4fa69bea 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -123,7 +123,7 @@ static void update_range(struct sw_flow_match *match,
static bool match_validate(const struct sw_flow_match *match,
u64 key_attrs, u64 mask_attrs, bool log)
{
- u64 key_expected = 1 << OVS_KEY_ATTR_ETHERNET;
+ u64 key_expected = 0;
u64 mask_allowed = key_attrs; /* At most allow all key attributes */
/* The following mask attributes allowed only if they
@@ -145,6 +145,10 @@ static bool match_validate(const struct sw_flow_match *match,
| (1 << OVS_KEY_ATTR_IN_PORT)
| (1 << OVS_KEY_ATTR_ETHERTYPE));
+ /* If Ethertype is present, expect MAC addresses */
+ if (key_attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE))
+ key_expected |= 1ULL << OVS_KEY_ATTR_ETHERNET;
+
/* Check key attributes. */
if (match->key->eth.type == htons(ETH_P_ARP)
|| match->key->eth.type == htons(ETH_P_RARP)) {
@@ -898,6 +902,15 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
sizeof(*cl), is_mask);
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
}
+ if (is_mask) {
+ /* Always exact match is_layer3 */
+ SW_FLOW_KEY_PUT(match, phy.is_layer3, true, is_mask);
+ } else {
+ if (*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET))
+ SW_FLOW_KEY_PUT(match, phy.is_layer3, false, is_mask);
+ else
+ SW_FLOW_KEY_PUT(match, phy.is_layer3, true, is_mask);
+ }
return 0;
}
@@ -961,6 +974,17 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
if (attrs & (1 << OVS_KEY_ATTR_IPV4)) {
const struct ovs_key_ipv4 *ipv4_key;
+ /* Add eth.type value for layer 3 flows */
+ if (!(attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE))) {
+ __be16 eth_type;
+
+ if (is_mask)
+ eth_type = htons(0xffff);
+ else
+ eth_type = htons(ETH_P_IP);
+ SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
+ }
+
ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
OVS_NLERR(log, "IPv4 frag type %d is out of range max %d",
@@ -985,6 +1009,17 @@ static int ovs_key_from_nlattrs(struct net *net, struct sw_flow_match *match,
if (attrs & (1 << OVS_KEY_ATTR_IPV6)) {
const struct ovs_key_ipv6 *ipv6_key;
+ /* Add eth.type value for layer 3 flows */
+ if (!(attrs & (1ULL << OVS_KEY_ATTR_ETHERTYPE))) {
+ __be16 eth_type;
+
+ if (is_mask)
+ eth_type = htons(0xffff);
+ else
+ eth_type = htons(ETH_P_IPV6);
+ SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
+ }
+
ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
OVS_NLERR(log, "IPv6 frag type %d is out of range max %d",
@@ -1415,7 +1450,7 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
struct sk_buff *skb)
{
struct ovs_key_ethernet *eth_key;
- struct nlattr *nla, *encap;
+ struct nlattr *nla, *encap = NULL;
if (nla_put_u32(skb, OVS_KEY_ATTR_RECIRC_ID, output->recirc_id))
goto nla_put_failure;
@@ -1456,42 +1491,44 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
if (ovs_ct_put_key(output, skb))
goto nla_put_failure;
- nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
- if (!nla)
- goto nla_put_failure;
+ if (!swkey->phy.is_layer3) {
+ nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
+ if (!nla)
+ goto nla_put_failure;
- eth_key = nla_data(nla);
- ether_addr_copy(eth_key->eth_src, output->eth.src);
- ether_addr_copy(eth_key->eth_dst, output->eth.dst);
+ eth_key = nla_data(nla);
+ ether_addr_copy(eth_key->eth_src, output->eth.src);
+ ether_addr_copy(eth_key->eth_dst, output->eth.dst);
- if (swkey->eth.tci || swkey->eth.type == htons(ETH_P_8021Q)) {
- __be16 eth_type;
- eth_type = !is_mask ? htons(ETH_P_8021Q) : htons(0xffff);
- if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, eth_type) ||
- nla_put_be16(skb, OVS_KEY_ATTR_VLAN, output->eth.tci))
- goto nla_put_failure;
- encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
- if (!swkey->eth.tci)
- goto unencap;
- } else
- encap = NULL;
-
- if (swkey->eth.type == htons(ETH_P_802_2)) {
- /*
- * Ethertype 802.2 is represented in the netlink with omitted
- * OVS_KEY_ATTR_ETHERTYPE in the flow key attribute, and
- * 0xffff in the mask attribute. Ethertype can also
- * be wildcarded.
- */
- if (is_mask && output->eth.type)
- if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE,
- output->eth.type))
+ if (swkey->eth.tci || swkey->eth.type == htons(ETH_P_8021Q)) {
+ __be16 eth_type;
+ eth_type = !is_mask ? htons(ETH_P_8021Q) : htons(0xffff);
+ if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, eth_type) ||
+ nla_put_be16(skb, OVS_KEY_ATTR_VLAN,
+ output->eth.tci))
goto nla_put_failure;
- goto unencap;
- }
+ encap = nla_nest_start(skb, OVS_KEY_ATTR_ENCAP);
+ if (!swkey->eth.tci)
+ goto unencap;
+ }
- if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type))
- goto nla_put_failure;
+ if (swkey->eth.type == htons(ETH_P_802_2)) {
+ /*
+ * Ethertype 802.2 is represented in the netlink
+ * with omitted OVS_KEY_ATTR_ETHERTYPE in the flow
+ * key attribute, and 0xffff in the mask attribute.
+ * Ethertype can also be wildcarded.
+ */
+ if (is_mask && output->eth.type)
+ if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE,
+ output->eth.type))
+ goto nla_put_failure;
+ goto unencap;
+ }
+
+ if (nla_put_be16(skb, OVS_KEY_ATTR_ETHERTYPE, output->eth.type))
+ goto nla_put_failure;
+ }
if (swkey->eth.type == htons(ETH_P_IP)) {
struct ovs_key_ipv4 *ipv4_key;
@@ -2010,8 +2047,8 @@ static bool validate_masked(u8 *data, int len)
static int validate_set(const struct nlattr *a,
const struct sw_flow_key *flow_key,
- struct sw_flow_actions **sfa,
- bool *skip_copy, __be16 eth_type, bool masked, bool log)
+ struct sw_flow_actions **sfa, bool *skip_copy,
+ __be16 eth_type, bool masked, bool log, bool is_layer3)
{
const struct nlattr *ovs_key = nla_data(a);
int key_type = nla_type(ovs_key);
@@ -2041,7 +2078,11 @@ static int validate_set(const struct nlattr *a,
case OVS_KEY_ATTR_SKB_MARK:
case OVS_KEY_ATTR_CT_MARK:
case OVS_KEY_ATTR_CT_LABELS:
+ break;
+
case OVS_KEY_ATTR_ETHERNET:
+ if (is_layer3)
+ return -EINVAL;
break;
case OVS_KEY_ATTR_TUNNEL:
@@ -2120,6 +2161,8 @@ static int validate_set(const struct nlattr *a,
break;
case OVS_KEY_ATTR_MPLS:
+ if (is_layer3)
+ return -EINVAL;
if (!eth_p_mpls(eth_type))
return -EINVAL;
break;
@@ -2208,6 +2251,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
int depth, struct sw_flow_actions **sfa,
__be16 eth_type, __be16 vlan_tci, bool log)
{
+ bool is_layer3 = key->phy.is_layer3;
const struct nlattr *a;
int rem, err;
@@ -2229,6 +2273,8 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
[OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
[OVS_ACTION_ATTR_CT] = (u32)-1,
+ [OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
+ [OVS_ACTION_ATTR_POP_ETH] = 0,
};
const struct ovs_action_push_vlan *vlan;
int type = nla_type(a);
@@ -2269,10 +2315,14 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
}
case OVS_ACTION_ATTR_POP_VLAN:
+ if (is_layer3)
+ return -EINVAL;
vlan_tci = htons(0);
break;
case OVS_ACTION_ATTR_PUSH_VLAN:
+ if (is_layer3)
+ return -EINVAL;
vlan = nla_data(a);
if (vlan->vlan_tpid != htons(ETH_P_8021Q))
return -EINVAL;
@@ -2287,7 +2337,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
case OVS_ACTION_ATTR_PUSH_MPLS: {
const struct ovs_action_push_mpls *mpls = nla_data(a);
- if (!eth_p_mpls(mpls->mpls_ethertype))
+ if (is_layer3 || !eth_p_mpls(mpls->mpls_ethertype))
return -EINVAL;
/* Prohibit push MPLS other than to a white list
* for packets that have a known tag order.
@@ -2304,7 +2354,7 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
}
case OVS_ACTION_ATTR_POP_MPLS:
- if (vlan_tci & htons(VLAN_TAG_PRESENT) ||
+ if (is_layer3 || vlan_tci & htons(VLAN_TAG_PRESENT) ||
!eth_p_mpls(eth_type))
return -EINVAL;
@@ -2322,14 +2372,16 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
case OVS_ACTION_ATTR_SET:
err = validate_set(a, key, sfa,
- &skip_copy, eth_type, false, log);
+ &skip_copy, eth_type, false, log,
+ is_layer3);
if (err)
return err;
break;
case OVS_ACTION_ATTR_SET_MASKED:
err = validate_set(a, key, sfa,
- &skip_copy, eth_type, true, log);
+ &skip_copy, eth_type, true, log,
+ is_layer3);
if (err)
return err;
break;
@@ -2349,6 +2401,22 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
skip_copy = true;
break;
+ case OVS_ACTION_ATTR_POP_ETH:
+ if (is_layer3)
+ return -EINVAL;
+ if (vlan_tci & htons(VLAN_TAG_PRESENT))
+ return -EINVAL;
+ is_layer3 = true;
+ break;
+
+ case OVS_ACTION_ATTR_PUSH_ETH:
+ /* For now disallow pushing an Ethernet header if one
+ * is already present */
+ if (!is_layer3)
+ return -EINVAL;
+ is_layer3 = false;
+ break;
+
default:
OVS_NLERR(log, "Unknown Action type %d", type);
return -EINVAL;
diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c
index 1a1fcec88695..906ae9c58c2e 100644
--- a/net/openvswitch/vport-geneve.c
+++ b/net/openvswitch/vport-geneve.c
@@ -116,7 +116,7 @@ static struct vport_ops ovs_geneve_vport_ops = {
.create = geneve_create,
.destroy = ovs_netdev_tunnel_destroy,
.get_options = geneve_get_options,
- .send = dev_queue_xmit,
+ .send = ovs_netdev_send_tap,
};
static int __init ovs_geneve_tnl_init(void)
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index 7f8897f33a67..f003225de994 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -87,7 +87,7 @@ static struct vport *gre_create(const struct vport_parms *parms)
static struct vport_ops ovs_gre_vport_ops = {
.type = OVS_VPORT_TYPE_GRE,
.create = gre_create,
- .send = dev_queue_xmit,
+ .send = ovs_netdev_send_tap,
.destroy = ovs_netdev_tunnel_destroy,
};
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 4ce2ad8c3a5c..a20f090bd971 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -256,6 +256,12 @@ static netdev_tx_t internal_dev_recv(struct sk_buff *skb)
struct net_device *netdev = skb->dev;
struct pcpu_sw_netstats *stats;
+ /* Only send/receive L2 packets */
+ if (!skb->mac_len) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
if (unlikely(!(netdev->flags & IFF_UP))) {
kfree_skb(skb);
netdev->stats.rx_dropped++;
diff --git a/net/openvswitch/vport-netdev.c b/net/openvswitch/vport-netdev.c
index 4e3972344aa6..0e0b9286dd11 100644
--- a/net/openvswitch/vport-netdev.c
+++ b/net/openvswitch/vport-netdev.c
@@ -57,8 +57,10 @@ static void netdev_port_receive(struct sk_buff *skb)
if (unlikely(!skb))
return;
- skb_push(skb, ETH_HLEN);
- skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
+ if (vport->dev->type == ARPHRD_ETHER) {
+ skb_push(skb, ETH_HLEN);
+ skb_postpush_rcsum(skb, skb->data, ETH_HLEN);
+ }
ovs_vport_receive(vport, skb, skb_tunnel_info(skb));
return;
error:
@@ -194,6 +196,17 @@ void ovs_netdev_tunnel_destroy(struct vport *vport)
}
EXPORT_SYMBOL_GPL(ovs_netdev_tunnel_destroy);
+int ovs_netdev_send_tap(struct sk_buff *skb)
+{
+ /* Only send L2 packets */
+ if (skb->mac_len)
+ return dev_queue_xmit(skb);
+
+ kfree_skb(skb);
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(ovs_netdev_send_tap);
+
/* Returns null if this device is not attached to a datapath. */
struct vport *ovs_netdev_get_vport(struct net_device *dev)
{
@@ -208,7 +221,7 @@ static struct vport_ops ovs_netdev_vport_ops = {
.type = OVS_VPORT_TYPE_NETDEV,
.create = netdev_create,
.destroy = netdev_destroy,
- .send = dev_queue_xmit,
+ .send = ovs_netdev_send_tap,
};
int __init ovs_netdev_init(void)
diff --git a/net/openvswitch/vport-netdev.h b/net/openvswitch/vport-netdev.h
index 19e29c12adcc..02f38a822334 100644
--- a/net/openvswitch/vport-netdev.h
+++ b/net/openvswitch/vport-netdev.h
@@ -33,4 +33,6 @@ int __init ovs_netdev_init(void);
void ovs_netdev_exit(void);
void ovs_netdev_tunnel_destroy(struct vport *vport);
+
+int ovs_netdev_send_tap(struct sk_buff *skb);
#endif /* vport_netdev.h */
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index 5eb7694348b5..009a4aab505a 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -153,7 +153,7 @@ static struct vport_ops ovs_vxlan_netdev_vport_ops = {
.create = vxlan_create,
.destroy = ovs_netdev_tunnel_destroy,
.get_options = vxlan_get_options,
- .send = dev_queue_xmit,
+ .send = ovs_netdev_send_tap,
};
static int __init ovs_vxlan_tnl_init(void)
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related
* [PATCH v9 net-next 3/7] openvswitch: add support to push and pop mpls for layer3 packets
From: Simon Horman @ 2016-05-04 7:36 UTC (permalink / raw)
To: netdev, dev; +Cc: Simon Horman
In-Reply-To: <1462347393-22354-1-git-send-email-simon.horman@netronome.com>
Allow push and pop mpls actions to act on layer 3 packets by teaching
them not to access non-existent L2 headers of such packets.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v9
* New Patch
---
net/openvswitch/actions.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 879185fe183f..fe885a89f501 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -160,8 +160,10 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);
- hdr = eth_hdr(skb);
- hdr->h_proto = mpls->mpls_ethertype;
+ if (skb->mac_len) {
+ hdr = eth_hdr(skb);
+ hdr->h_proto = mpls->mpls_ethertype;
+ }
if (!skb->inner_protocol)
skb_set_inner_protocol(skb, skb->protocol);
@@ -174,7 +176,6 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
const __be16 ethertype)
{
- struct ethhdr *hdr;
int err;
err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
@@ -189,11 +190,16 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
__skb_pull(skb, MPLS_HLEN);
skb_reset_mac_header(skb);
- /* skb_mpls_header() is used to locate the ethertype
- * field correctly in the presence of VLAN tags.
- */
- hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN);
- hdr->h_proto = ethertype;
+ if (skb->mac_len) {
+ /* skb_mpls_header() is used to locate the ethertype
+ * field correctly in the presence of VLAN tags.
+ */
+ struct ethhdr *hdr;
+
+ hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN);
+ BUG_ON((unsigned char *)hdr < skb_mac_header(skb));
+ hdr->h_proto = ethertype;
+ }
if (eth_p_mpls(skb->protocol))
skb->protocol = ethertype;
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related
* [PATCH v9 net-next 2/7] openvswitch: set skb protocol when receiving on internal device
From: Simon Horman @ 2016-05-04 7:36 UTC (permalink / raw)
To: netdev, dev; +Cc: Simon Horman
In-Reply-To: <1462347393-22354-1-git-send-email-simon.horman@netronome.com>
Set skb protocol based on contents of packet. I have observed this is
necessary to get actual protocol of a packet when it is injected into an
internal device e.g. by libnet in which case skb protocol will be set to
ETH_ALL.
The motivation for this is that support for outputting to layer 3 (non-tap)
GRE tunnels as implemented by a subsequent patch depends on protocol being
set correctly in order to provide the protocol for the inner packet.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v9
* New patch
---
net/openvswitch/vport-internal_dev.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c
index 2ee48e447b72..4ce2ad8c3a5c 100644
--- a/net/openvswitch/vport-internal_dev.c
+++ b/net/openvswitch/vport-internal_dev.c
@@ -48,6 +48,8 @@ static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
{
int len, err;
+ skb->protocol = eth_type_trans(skb, netdev);
+ skb_push(skb, ETH_HLEN);
len = skb->len;
rcu_read_lock();
err = ovs_vport_receive(internal_dev_priv(netdev)->vport, skb, NULL);
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related
* [PATCH v9 net-next 1/7] net: add skb_vlan_deaccel helper
From: Simon Horman @ 2016-05-04 7:36 UTC (permalink / raw)
To: netdev, dev; +Cc: Simon Horman
In-Reply-To: <1462347393-22354-1-git-send-email-simon.horman@netronome.com>
This breaks out the bulk of skb_vlan_push into a separate helper.
This new helper moves any vlan tag present in metadata into packet data.
The existing skb_vlan_push uses this new helper and then pushes a new
vlan tag (into metadata).
The motivation is to allow deaccelerating VLAN tags without adding a new
one. This is in preparation for a push ethernet header support in Open
vSwitch.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v9 [Simon Horman]
* New patch
---
include/linux/skbuff.h | 1 +
net/core/skbuff.c | 50 ++++++++++++++++++++++++++++++++------------------
2 files changed, 33 insertions(+), 18 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c413c588a24f..fa504d28c7e4 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2994,6 +2994,7 @@ int skb_vlan_pop(struct sk_buff *skb);
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci);
struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
gfp_t gfp);
+int skb_vlan_deaccel(struct sk_buff *skb);
static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
{
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 7a1d48983f81..84a3f8cc4b0a 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4516,30 +4516,44 @@ int skb_vlan_pop(struct sk_buff *skb)
}
EXPORT_SYMBOL(skb_vlan_pop);
-int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
+int skb_vlan_deaccel(struct sk_buff *skb)
{
- if (skb_vlan_tag_present(skb)) {
- unsigned int offset = skb->data - skb_mac_header(skb);
- int err;
+ unsigned int offset;
+ int err;
- /* __vlan_insert_tag expect skb->data pointing to mac header.
- * So change skb->data before calling it and change back to
- * original position later
- */
- __skb_push(skb, offset);
- err = __vlan_insert_tag(skb, skb->vlan_proto,
- skb_vlan_tag_get(skb));
- if (err) {
- __skb_pull(skb, offset);
- return err;
- }
+ if (!skb_vlan_tag_present(skb))
+ return 0;
- skb->protocol = skb->vlan_proto;
- skb->mac_len += VLAN_HLEN;
+ offset = skb->data - skb_mac_header(skb);
- skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
+ /* __vlan_insert_tag expect skb->data pointing to mac header.
+ * So change skb->data before calling it and change back to
+ * original position later
+ */
+ __skb_push(skb, offset);
+ err = __vlan_insert_tag(skb, skb->vlan_proto, skb_vlan_tag_get(skb));
+ if (err) {
__skb_pull(skb, offset);
+ return err;
}
+
+ skb->protocol = skb->vlan_proto;
+ skb->mac_len += VLAN_HLEN;
+
+ skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
+ __skb_pull(skb, offset);
+
+ return 0;
+}
+EXPORT_SYMBOL(skb_vlan_deaccel);
+
+int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
+{
+ int err;
+
+ err = skb_vlan_deaccel(skb);
+ if (err)
+ return err;
__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
return 0;
}
--
2.7.0.rc3.207.g0ac5344
^ permalink raw reply related
* [PATCH v9 net-next 5/7] openvswitch: add layer 3 support to ovs_packet_cmd_execute()
From: Simon Horman @ 2016-05-04 7:36 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA, dev-yBygre7rU0TnMu66kgdUjQ; +Cc: Simon Horman
In-Reply-To: <1462347393-22354-1-git-send-email-simon.horman-wFxRvT7yatFl57MIdRCFDg@public.gmane.org>
From: Lorand Jakab <lojakab@cisco.com>
When user space handles a packet back to the kernel datapath for
execution, it is not accompanied by the full flow key, only packet
metadata. This doesn't allow detection of packet type (L2/L3). Add the
OVS_KEY_ATTR_PACKET_ETHERTYPE attribute to the packet metadata,
containing 0 for layer 2 packets and the Ethertype for layer 3 packets.
Signed-off-by: Lorand Jakab <lojakab@cisco.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
---
v9 [Simon Horman]
* Rebase
v8 [Lorand Jakab]
v7 [Lorand Jakab]
* New patch
---
include/uapi/linux/openvswitch.h | 2 ++
net/openvswitch/datapath.c | 13 +------------
net/openvswitch/flow.c | 5 ++++-
net/openvswitch/flow_netlink.c | 39 +++++++++++++++++++++++++++++++--------
4 files changed, 38 insertions(+), 21 deletions(-)
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 53129c03273c..2bc2c12ced78 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -329,6 +329,8 @@ enum ovs_key_attr {
OVS_KEY_ATTR_CT_ZONE, /* u16 connection tracking zone. */
OVS_KEY_ATTR_CT_MARK, /* u32 connection tracking mark */
OVS_KEY_ATTR_CT_LABELS, /* 16-octet connection tracking label */
+ OVS_KEY_ATTR_PACKET_ETHERTYPE, /* be16 Ethernet type for packet
+ * execution */
#ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO, /* struct ip_tunnel_info */
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 856bd8dba676..780957e78d2b 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -546,7 +546,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
struct sw_flow *flow;
struct sw_flow_actions *sf_acts;
struct datapath *dp;
- struct ethhdr *eth;
struct vport *input_vport;
u16 mru = 0;
int len;
@@ -567,17 +566,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
nla_memcpy(__skb_put(packet, len), a[OVS_PACKET_ATTR_PACKET], len);
- skb_reset_mac_header(packet);
- eth = eth_hdr(packet);
-
- /* Normally, setting the skb 'protocol' field would be handled by a
- * call to eth_type_trans(), but it assumes there's a sending
- * device, which we may not have. */
- if (eth_proto_is_802_3(eth->h_proto))
- packet->protocol = eth->h_proto;
- else
- packet->protocol = htons(ETH_P_802_2);
-
/* Set packet's mru */
if (a[OVS_PACKET_ATTR_MRU]) {
mru = nla_get_u16(a[OVS_PACKET_ATTR_MRU]);
@@ -604,6 +592,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
rcu_assign_pointer(flow->sf_acts, acts);
packet->priority = flow->key.phy.priority;
packet->mark = flow->key.phy.skb_mark;
+ packet->protocol = flow->key.eth.type;
rcu_read_lock();
dp = get_dp_rcu(net, ovs_header->dp_ifindex);
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 6e174ea5f2bb..d320c2657627 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -471,7 +471,6 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
/* Link layer. */
if (key->phy.is_layer3) {
key->eth.tci = 0;
- key->eth.type = skb->protocol;
} else {
eth = eth_hdr(skb);
ether_addr_copy(key->eth.src, eth->h_source);
@@ -693,6 +692,8 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
{
+ key->eth.type = skb->protocol;
+
return key_extract(skb, key);
}
@@ -747,6 +748,8 @@ int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info,
if (is_teb)
skb->protocol = key->eth.type;
+ else if (is_layer3)
+ key->eth.type = skb->protocol;
return err;
}
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index d0ef4fa69bea..2bca1e5e9a18 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -286,7 +286,7 @@ size_t ovs_key_attr_size(void)
/* Whenever adding new OVS_KEY_ FIELDS, we should consider
* updating this function.
*/
- BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 26);
+ BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 27);
return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
+ nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
@@ -359,6 +359,7 @@ static const struct ovs_len_tbl ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
[OVS_KEY_ATTR_CT_ZONE] = { .len = sizeof(u16) },
[OVS_KEY_ATTR_CT_MARK] = { .len = sizeof(u32) },
[OVS_KEY_ATTR_CT_LABELS] = { .len = sizeof(struct ovs_key_ct_labels) },
+ [OVS_KEY_ATTR_PACKET_ETHERTYPE] = { .len = sizeof(__be16) },
};
static bool check_attr_len(unsigned int attr_len, unsigned int expected_len)
@@ -816,6 +817,8 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
u64 *attrs, const struct nlattr **a,
bool is_mask, bool log)
{
+ bool is_layer3;
+
if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
@@ -902,15 +905,35 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
sizeof(*cl), is_mask);
*attrs &= ~(1ULL << OVS_KEY_ATTR_CT_LABELS);
}
- if (is_mask) {
+
+ /* For full flow keys the layer is determined based on the presence of
+ * OVS_KEY_ATTR_ETHERNET
+ */
+ if (is_mask)
/* Always exact match is_layer3 */
- SW_FLOW_KEY_PUT(match, phy.is_layer3, true, is_mask);
- } else {
- if (*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET))
- SW_FLOW_KEY_PUT(match, phy.is_layer3, false, is_mask);
- else
- SW_FLOW_KEY_PUT(match, phy.is_layer3, true, is_mask);
+ is_layer3 = true;
+ else
+ is_layer3 = !(*attrs & (1ULL << OVS_KEY_ATTR_ETHERNET));
+ /* Packets from user space for execution only have metadata key
+ * attributes. OVS_KEY_ATTR_PACKET_ETHERTYPE is then used to specify
+ * the starting layer of the packet. Packets with Ethernet headers
+ * have this attribute set to 0
+ */
+ if (*attrs & (1ULL << OVS_KEY_ATTR_PACKET_ETHERTYPE)) {
+ __be16 eth_type;
+
+ if (is_mask) {
+ /* Always exact match packet EtherType */
+ eth_type = htons(0xffff);
+ } else {
+ eth_type = nla_get_be16(a[OVS_KEY_ATTR_PACKET_ETHERTYPE]);
+ is_layer3 = ((eth_type == htons(ETH_P_IP)) ||
+ (eth_type == htons(ETH_P_IPV6)));
+ }
+ SW_FLOW_KEY_PUT(match, eth.type, eth_type, is_mask);
}
+
+ SW_FLOW_KEY_PUT(match, phy.is_layer3, is_layer3, is_mask);
return 0;
}
--
2.7.0.rc3.207.g0ac5344
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev
^ permalink raw reply related
* [PATCH v9 net-next 0/7] openvswitch: support for layer 3 encapsulated packets
From: Simon Horman @ 2016-05-04 7:36 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA, dev-yBygre7rU0TnMu66kgdUjQ; +Cc: Simon Horman
At the core of this patch set is removing the assumption in Open vSwitch
datapath that all packets have Ethernet header. Support for layer 3 GRE
tunnels is also added by this patchset.
The implementation relies on the presence of pop_eth and push_eth actions
in datapath flows to facilitate adding and removing Ethernet headers as
appropriate. The construction of such flows is left up to user-space.
This series is based on work by Lorand Jakab, Thomas Morin and others.
This patch set is comprised of kernel patches against net-next.
It depends on:
"[PATCH net-next 0/3] gre: receive also TEB packets for lwtunnels"
To aid review it and the above dependency is available at:
tree: https://github.com/horms/openvswitch
branch: me/l3-vpn
tag: l3-vpn-v9
There is a companion patch set for the Open vSwitch user-space code
which I will post separately to the dev@openvswitch.org mailing list as:
"[PATCH v10 0/5] userspace: Support for layer 3 encapsulated packets"
Lorand Jakab (1):
openvswitch: add layer 3 flow/port support
Simon Horman (6):
net: add skb_vlan_deaccel helper
openvswitch: set skb protocol when receiving on internal device
openvswitch: add support to push and pop mpls for layer3 packets
openvswitch: add layer 3 support to ovs_packet_cmd_execute()
openvswitch: extend layer 3 support to cover non-IP packets
openvswitch: use ipgre tunnel rather than gretap tunnel
include/linux/skbuff.h | 1 +
include/net/gre.h | 4 +-
include/uapi/linux/openvswitch.h | 14 +++
net/core/skbuff.c | 50 +++++----
net/ipv4/ip_gre.c | 8 +-
net/openvswitch/actions.c | 70 ++++++++++--
net/openvswitch/datapath.c | 13 +--
net/openvswitch/flow.c | 66 ++++++++----
net/openvswitch/flow.h | 4 +-
net/openvswitch/flow_netlink.c | 200 +++++++++++++++++++++++++----------
net/openvswitch/vport-geneve.c | 2 +-
net/openvswitch/vport-gre.c | 4 +-
net/openvswitch/vport-internal_dev.c | 8 ++
net/openvswitch/vport-netdev.c | 31 +++++-
net/openvswitch/vport-netdev.h | 3 +
net/openvswitch/vport-vxlan.c | 2 +-
16 files changed, 350 insertions(+), 130 deletions(-)
--
2.7.0.rc3.207.g0ac5344
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev
^ permalink raw reply
* Re: [RESEND PATCH 1/3] rfkill: Create "rfkill-airplane-mode" LED trigger
From: Pavel Machek @ 2016-05-04 7:29 UTC (permalink / raw)
To: João Paulo Rechi Vita
Cc: Johannes Berg, David S. Miller, Darren Hart, linux-wireless,
netdev, platform-driver-x86, linux-api, linux-doc, linux-kernel,
linux, João Paulo Rechi Vita
In-Reply-To: <1462199948-6424-2-git-send-email-jprvita@endlessm.com>
Hi!
> This creates a new LED trigger to be used by platform drivers as a
> default trigger for airplane-mode indicator LEDs.
>
> By default this trigger will fire when RFKILL_OP_CHANGE_ALL is called
> for all types (RFKILL_TYPE_ALL), setting the LED brightness to LED_FULL
> when the changing the state to blocked, and to LED_OFF when the changing
> the state to unblocked. In the future there will be a mechanism for
> userspace to override the default policy, so it can implement its
> own.
If userspace wants to control the manually, it can do just that --
control it manually. There should not be a need to "override the
default policy".
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply
* RE: [PATCH v5 1/2] can: rcar_canfd: Add Renesas R-Car CAN FD driver
From: Ramesh Shanmugasundaram @ 2016-05-04 6:23 UTC (permalink / raw)
To: Rob Herring
Cc: mkl@pengutronix.de, wg@grandegger.com, socketcan@hartkopp.net,
pawel.moll@arm.com, mark.rutland@arm.com,
ijc+devicetree@hellion.org.uk, galak@codeaurora.org,
linux-renesas-soc@vger.kernel.org, devicetree@vger.kernel.org,
linux-can@vger.kernel.org, netdev@vger.kernel.org, Chris Paterson
In-Reply-To: <20160503164728.GA32640@rob-hp-laptop>
Hi Rob,
> On Thu, Apr 28, 2016 at 01:23:07PM +0100, Ramesh Shanmugasundaram wrote:
> > This patch adds support for the CAN FD controller found in Renesas
> > R-Car SoCs. The controller operates in CAN FD only mode by default.
> >
> > CAN FD mode supports both Classical CAN & CAN FD frame formats. The
> > controller supports ISO 11898-1:2015 CAN FD format only.
> >
> > This controller supports two channels and the driver can enable either
> > or both of the channels.
> >
> > Driver uses Rx FIFOs (one per channel) for reception & Common FIFOs
> > (one per channel) for transmission. Rx filter rules are configured to
> > the minimum (one per channel) and it accepts Standard, Extended, Data
> > & Remote Frame combinations.
> >
> > Note: There are few documentation errors in R-Car Gen3 Hardware User
> > Manual v0.5E with respect to CAN FD controller. They are listed below:
> >
> > 1. CAN FD interrupt numbers 29 & 30 are listed as per channel
> > interrupts. However, they are common to both channels (i.e.) they are
> > global and channel interrupts respectively.
> >
> > 2. CANFD clock is derived from PLL1. This is not documented.
> >
> > 3. CANFD clock is further divided by (1/2) within the CAN FD controller.
> > This is not documented.
> >
> > 4. The minimum value of NTSEG1 in RSCFDnCFDCmNCFG register is 2 Tq. It
> > is specified 4 Tq in the manual.
> >
> > 5. The maximum number of message RAM area the controller can use is
> > 3584 bytes. It is specified 10752 bytes in the manual.
> >
> > Signed-off-by: Ramesh Shanmugasundaram
> > <ramesh.shanmugasundaram@bp.renesas.com>
> > ---
> > .../devicetree/bindings/net/can/rcar_canfd.txt | 89 ++
>
> What happened to my ack?
Sorry, I missed it when I updated the patch. I mentioned it in cover letter though. I will request the CAN maintainer to add it if this is accepted or otherwise I will add it to the next patch series.
---
Changes since v3:
* Split v3 patch into two (Marc K)
(1) Introduce rcar_canfd.c driver in drivers/net/can/rcar dir
(2) Move rcar_can.c driver to new drivers/net/can/rcar dir
* Added Acked-by Rob H for the bindings
---
Thanks,
Ramesh
^ permalink raw reply
* [patch] usbnet: smsc95xx: silence an uninitialized variable warning
From: Dan Carpenter @ 2016-05-04 6:22 UTC (permalink / raw)
To: Steve Glendinning
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb-u79uwXL29TY76Z2rM5mHXA
If the call to fn() fails then "buf" is uninitialized. Just return the
error code in that case.
Signed-off-by: Dan Carpenter <dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 2edc2bc..d9d2806 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -92,9 +92,11 @@ static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
| USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, &buf, 4);
- if (unlikely(ret < 0))
+ if (unlikely(ret < 0)) {
netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
index, ret);
+ return ret;
+ }
le32_to_cpus(&buf);
*data = buf;
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [patch] usbnet/smsc75xx: silence uninitialized variable warning
From: Dan Carpenter @ 2016-05-04 6:21 UTC (permalink / raw)
To: Steve Glendinning
Cc: netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb-u79uwXL29TY76Z2rM5mHXA
If the fn() calls fail then "buf" is uninitialized. Just return early
in that situation.
Signed-off-by: Dan Carpenter <dan.carpenter-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index c369db9..9af9799 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -99,9 +99,11 @@ static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index,
ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
| USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, index, &buf, 4);
- if (unlikely(ret < 0))
+ if (unlikely(ret < 0)) {
netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
index, ret);
+ return ret;
+ }
le32_to_cpus(&buf);
*data = buf;
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [patch] rtlwifi: rtl818x: silence uninitialized variable warning
From: Dan Carpenter @ 2016-05-04 6:16 UTC (permalink / raw)
To: Larry Finger
Cc: Chaoming Li, Kalle Valo, linux-wireless, netdev, linux-kernel,
kernel-janitors
What about if "rtlphy->pwrgroup_cnt" is 2? In that case we would use an
uninitialized "chnlgroup" variable and probably crash. Maybe that can't
happen for some reason which is not obvious but in that case this patch
is harmless.
Setting it to zero seems like a standard default in the surrounding code
so it's probably fine here as well.
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
index 78a81c1..9475aa2 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/rf.c
@@ -208,8 +208,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw,
"Realtek regulatory, 40MHz, writeval = 0x%x\n",
writeval);
} else {
- if (rtlphy->pwrgroup_cnt == 1)
- chnlgroup = 0;
+ chnlgroup = 0;
if (rtlphy->pwrgroup_cnt >= 3) {
if (chnl <= 3)
^ permalink raw reply related
* [PATCH 3/3] vti: Add pmtu handling to vti_xmit.
From: Steffen Klassert @ 2016-05-04 5:40 UTC (permalink / raw)
To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev
In-Reply-To: <1462340454-27922-1-git-send-email-steffen.klassert@secunet.com>
We currently rely on the PMTU discovery of xfrm.
However if a packet is locally sent, the PMTU mechanism
of xfrm tries to do local socket notification what
might not work for applications like ping that don't
check for this. So add pmtu handling to vti_xmit to
report MTU changes immediately.
Reported-by: Mark McKinstry <Mark.McKinstry@alliedtelesis.co.nz>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/ipv4/ip_vti.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 5cf10b7..a917903 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -156,6 +156,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
struct dst_entry *dst = skb_dst(skb);
struct net_device *tdev; /* Device to other host */
int err;
+ int mtu;
if (!dst) {
dev->stats.tx_carrier_errors++;
@@ -192,6 +193,23 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
tunnel->err_count = 0;
}
+ mtu = dst_mtu(dst);
+ if (skb->len > mtu) {
+ skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
+ if (skb->protocol == htons(ETH_P_IP)) {
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
+ htonl(mtu));
+ } else {
+ if (mtu < IPV6_MIN_MTU)
+ mtu = IPV6_MIN_MTU;
+
+ icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+ }
+
+ dst_release(dst);
+ goto tx_error;
+ }
+
skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev)));
skb_dst_set(skb, dst);
skb->dev = skb_dst(skb)->dev;
--
1.9.1
^ permalink raw reply related
* [PATCH 1/3] flowcache: Avoid OOM condition under preasure
From: Steffen Klassert @ 2016-05-04 5:40 UTC (permalink / raw)
To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev
In-Reply-To: <1462340454-27922-1-git-send-email-steffen.klassert@secunet.com>
We can hit an OOM condition if we are under presure because
we can not free the entries in gc_list fast enough. So add
a counter for the not yet freed entries in the gc_list and
refuse new allocations if the value is too high.
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/netns/xfrm.h | 1 +
net/core/flow.c | 14 +++++++++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 730d82a..24cd394 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -80,6 +80,7 @@ struct netns_xfrm {
struct flow_cache flow_cache_global;
atomic_t flow_cache_genid;
struct list_head flow_cache_gc_list;
+ atomic_t flow_cache_gc_count;
spinlock_t flow_cache_gc_lock;
struct work_struct flow_cache_gc_work;
struct work_struct flow_cache_flush_work;
diff --git a/net/core/flow.c b/net/core/flow.c
index 1033725..3937b1b 100644
--- a/net/core/flow.c
+++ b/net/core/flow.c
@@ -92,8 +92,11 @@ static void flow_cache_gc_task(struct work_struct *work)
list_splice_tail_init(&xfrm->flow_cache_gc_list, &gc_list);
spin_unlock_bh(&xfrm->flow_cache_gc_lock);
- list_for_each_entry_safe(fce, n, &gc_list, u.gc_list)
+ list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) {
flow_entry_kill(fce, xfrm);
+ atomic_dec(&xfrm->flow_cache_gc_count);
+ WARN_ON(atomic_read(&xfrm->flow_cache_gc_count) < 0);
+ }
}
static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp,
@@ -101,6 +104,7 @@ static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp,
struct netns_xfrm *xfrm)
{
if (deleted) {
+ atomic_add(deleted, &xfrm->flow_cache_gc_count);
fcp->hash_count -= deleted;
spin_lock_bh(&xfrm->flow_cache_gc_lock);
list_splice_tail(gc_list, &xfrm->flow_cache_gc_list);
@@ -232,6 +236,13 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
if (fcp->hash_count > fc->high_watermark)
flow_cache_shrink(fc, fcp);
+ if (fcp->hash_count > 2 * fc->high_watermark ||
+ atomic_read(&net->xfrm.flow_cache_gc_count) > fc->high_watermark) {
+ atomic_inc(&net->xfrm.flow_cache_genid);
+ flo = ERR_PTR(-ENOBUFS);
+ goto ret_object;
+ }
+
fle = kmem_cache_alloc(flow_cachep, GFP_ATOMIC);
if (fle) {
fle->net = net;
@@ -446,6 +457,7 @@ int flow_cache_init(struct net *net)
INIT_WORK(&net->xfrm.flow_cache_gc_work, flow_cache_gc_task);
INIT_WORK(&net->xfrm.flow_cache_flush_work, flow_cache_flush_task);
mutex_init(&net->xfrm.flow_flush_sem);
+ atomic_set(&net->xfrm.flow_cache_gc_count, 0);
fc->hash_shift = 10;
fc->low_watermark = 2 * flow_cache_hash_size(fc);
--
1.9.1
^ permalink raw reply related
* pull request (net): ipsec 2016-05-04
From: Steffen Klassert @ 2016-05-04 5:40 UTC (permalink / raw)
To: David Miller; +Cc: Herbert Xu, Steffen Klassert, netdev
1) The flowcache can hit an OOM condition if too
many entries are in the gc_list. Fix this by
counting the entries in the gc_list and refuse
new allocations if the value is too high.
2) The inner headers are invalid after a xfrm transformation,
so reset the skb encapsulation field to ensure nobody tries
access the inner headers. Otherwise tunnel devices stacked
on top of xfrm may build the outer headers based on wrong
informations.
3) Add pmtu handling to vti, we need it to report
pmtu informations for local generated packets.
Please pull or let me know if there are problems.
Thanks!
The following changes since commit aac8d3c282e024c344c5b86dc1eab7af88bb9716:
qmi_wwan: add "4G LTE usb-modem U901" (2016-02-16 20:39:32 -0500)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git master
for you to fetch changes up to d6af1a31cc72fbd558c7eddbc36f61bf09d1cf6a:
vti: Add pmtu handling to vti_xmit. (2016-03-31 08:59:56 +0200)
----------------------------------------------------------------
Steffen Klassert (3):
flowcache: Avoid OOM condition under preasure
xfrm: Reset encapsulation field of the skb before transformation
vti: Add pmtu handling to vti_xmit.
include/net/netns/xfrm.h | 1 +
net/core/flow.c | 14 +++++++++++++-
net/ipv4/ip_vti.c | 18 ++++++++++++++++++
net/xfrm/xfrm_output.c | 3 +++
4 files changed, 35 insertions(+), 1 deletion(-)
^ 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