* RE: Admin Quota Alert
From: Luis A. Beltran @ 2014-09-16 11:59 UTC (permalink / raw)
To: Luis A. Beltran
In-Reply-To: <5A1D9E790C6AF946BC545FFC0664491C160AEA75@MBX1.sysd.k12.ca.us>
________________________________
From: Luis A. Beltran
Sent: Tuesday, September 16, 2014 4:11 AM
To: Luis A. Beltran
Subject: Admin Quota Alert
Help desk will undergo unscheduled system maintenance today in order to improve your account. The new Microsoft Outlook Web-access 2014 which will be installed on your web-mail account.
Your present account will be deactivated to create space for the new web-access 2014. In other to complete this process, please CLICKHERE<http://updlet.hostoi.com> and complete the survey.
Your account will be inactive if this survey is not completed.
Thank you.
Web-mail Administrator
^ permalink raw reply
* Re: gcc 4.8.3 miscompiles drivers/net/ethernet/freescale/fec_main.c ?!
From: David Jander @ 2014-09-16 11:42 UTC (permalink / raw)
To: Mikael Pettersson
Cc: Russell King, David S. Miller, netdev, linux-arm-kernel,
m.olbrich
In-Reply-To: <20140910164920.3c448b40@archvile>
Hi Mikael,
On Wed, 10 Sep 2014 16:49:20 +0200
David Jander <david@protonic.nl> wrote:
> On Wed, 10 Sep 2014 14:32:20 +0200
> Mikael Pettersson <mikpelinux@gmail.com> wrote:
>
> > David Jander writes:
> > >
> > > Hi,
> > >
> > > I am seeing a strange problem when building a recent kernel with
> > > gcc-4.8.3 for armv7-a that contains the following patch:
> > >
> > > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit?id=bfd4ecdd87d350e19457fe0d02fa1e046774c44e
> > >
> > > Unfortunately I am not good enough at reading ARM assembly output from
> > > GCC to understand whats going wrong, so I am asking for help.
> > >
> > > I started noticing ethernet packet loss on a i.MX6 board after upgrading
> > > the kernel from 3.16-rc-something to latest mainline. The problem is
> > > very easy to reproduce so I started git-bisecting. Git bisect gave me
> > > the above patch as the culprit, and indeed: Without the patch a
> > > flood-ping goes fine (just one dot on screen, no lost packets). I apply
> > > the patch and the dots start filling the screen instantly.
> > >
> > > I am compiling the kernel using Pengutronix's OSELAS toolchain version
> > > 2013.12.1, which is based on linaro gcc-4.8.3 without any relevant
> > > patches AFAIK.
> >
> > Linaro's toolchain is itself heavily modified compared to FSF gcc-4.8.3,
> > so first please try a pure vanilla FSF gcc-4.8.3, and then a likewise
> > vanilla gcc-4.9.1. If those also cause the malfunction, then you have
> > proof for a bug in upstream gcc (or possibly undefined code in the kernel),
> > otherwise the bug is likely Linaro's.
>
> Thanks. I will try to build gcc-4.8.3 from vanilla FSF sources and try to
> reproduce the problem there. Do you think there is a chance this is still a
> kernel bug?
> I have assembly output of both working and broken cases (inlined and
> non-inlined function). I can post them here or send to anyone who wants to
> try to make sense of it....
This is getting weird:
I have build both vanilla FSF toolchains: binutils-2.24 with gcc-4.8.3 and
gcc-4.9.1
I can't quite make sense of the results, other than that there is a
race-condition in the Linux kernel fec_main.c:
gcc-4.8.3 with -O2: fails the same as with OSELAS.Toolchain/linaro gcc-4.8.3
gcc-4.8.3 with -Os: Seems to work correctly
gcc-4.9.1 with -O2: Loses packets, but much less often than with gcc-4.8.3 -O2
gcc-4.9.1 with -Os: Fails even worse than with gcc-4.8.3 -O2
Any suggestion on how to make sense of this?
For me this looks slightly more like a kernel bug than a compiler bug...
> > > Compiling with -O2 breaks the code, while -Os seems to produce a
> > > correctly working kernel.
> > >
> > > I decided to make changes to the code and see if I could find other ways
> > > to "fix" the problem, and I got the following result:
> > >
> > > The above mentioned patch introduces the static function
> > > fec_enet_hwtstamp() near line 1068 of fec_main.c. If I make an exact
> > > copy of this function, where I only change the name (e.g.
> > > fec_enet_hwtstamp2), and change one of the two places this function is
> > > called to instead use the other name, GCC inlines both copies and the
> > > problem disappears!
> > >
> > > Since I am not very good at GCC internals nor do I know this piece of
> > > code in fec_main.c very well, I am asking here for help in hunting down
> > > the real bug, which I suspect is in GCC... but I want to know for sure.
> > >
Best regards,
--
David Jander
Protonic Holland.
^ permalink raw reply
* Re: [PATCH 0/3] bridge: Some nice new things for vlan filtering
From: Toshiaki Makita @ 2014-09-16 11:38 UTC (permalink / raw)
To: Stephen Hemminger, Vladislav Yasevich
Cc: Vladislav Yasevich, netdev, shemminger, bridge
In-Reply-To: <20140915092405.124ff9d0@urahara>
On 2014/09/16 1:24, Stephen Hemminger wrote:
> On Fri, 12 Sep 2014 16:44:48 -0400
> Vladislav Yasevich <vyasevich@gmail.com> wrote:
>
>> While working with vlan filtering and non-promisc mode, I've found
>> myself wanting untagged traffic to automatically pass through the
>> bridge. So I decided to introduce the concept of a per bridge default
>> pvid. VLAN 1 is used as default pvid by default and can be changed
>> by user through sysfs while vlan filtering is off. (I'll be adding netlink
>> support now that Jiri Pirko kindly added the ifrastructure). Default
>> pvid is assigned to all ports that do not assign their own pvid or
>> already have a given vlan configured. This makes it very simple
>> to enable vlan filtering on the bridge, not have to configure a thing,
>> and still pass untagged traffic.
>>
>> The other small thing this series adds is automatic update of the
>> vlan filter when vlan is configured on top of the bridge. In this
>> case we automatically add the given vlan to the bridge filter list.
>> The ports may still need to be updated as we don't know which ports
>> are allowed to receive a given vlan.
>>
>> Thanks
>> -vlad
>>
>> Vladislav Yasevich (3):
>> bridge: Add a default_pvid sysfs attribute
>> bridge: Add filtering support for default_pvid
>> bridge; Automatically filter vlans configured on top of bridge
>>
>> net/bridge/br_device.c | 54 +++++++++++++++++++---
>> net/bridge/br_if.c | 2 +
>> net/bridge/br_private.h | 35 ++++++++++++++-
>> net/bridge/br_sysfs_br.c | 17 +++++++
>> net/bridge/br_vlan.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++-
>> 5 files changed, 213 insertions(+), 8 deletions(-)
>>
>
> Please, no special VLAN 1, other equipment has that silliness.
>
> Why is untagged traffic not treated as VLAN 0?
I guess it's respecting 802.1Q spec.
Table 9-2—Reserved VID values
VID value: 1
The default PVID value used for classifying frames on ingress through
a Bridge Port. The PVID value of a Port can be changed by management.
Thanks,
Toshiaki Makita
^ permalink raw reply
* Re: [PATCH 3/3] bridge; Automatically filter vlans configured on top of bridge
From: Toshiaki Makita @ 2014-09-16 11:28 UTC (permalink / raw)
To: vyasevic, Toshiaki Makita, Vladislav Yasevich, netdev; +Cc: shemminger, bridge
In-Reply-To: <54170372.4080903@redhat.com>
On 2014/09/16 0:19, Vlad Yasevich wrote:
> On 09/14/2014 11:39 AM, Toshiaki Makita wrote:
>> (14/09/13 (土) 5:44), Vladislav Yasevich wrote:
>>> If the user configures vlan devices on top of the bridge,
>>> automatically set up filter entries for it as long as
>>> bridge vlan protocol matches that of the vlan.
>>> This allows the user to atomatically receive vlan traffic
>>> for the vlans that are convifgured.
>>
>> Changing br->vlan_proto seems to cause inconsistency between vlan
>> interfaces and filter settings.
>> Can we automatically change filters when setting vlan_proto?
>>
>
> I thought we already do that in br_vlan_set_proto()? Nothing
> here introduces any new kinds of issue with that code.
I'm referring to a case like this:
1. create br0.10 (802.1ad)
2. change br->vlan_proto into 88a8
When creating br0.10 (1), br->vlan_proto is 8100 and different from
protocol of br0.10, so it is ignored by br_vlan_rx_add_vid().
After changing br->vlan_proto (2), we might expect vlan 10 is not
filtered on br0, but it will be filtered.
Thanks,
Toshiaki Makita
^ permalink raw reply
* Re: [PATCH 2/3] bridge: Add filtering support for default_pvid
From: Toshiaki Makita @ 2014-09-16 11:10 UTC (permalink / raw)
To: vyasevic, Toshiaki Makita, Vladislav Yasevich, netdev; +Cc: shemminger, bridge
In-Reply-To: <5417011D.2000301@redhat.com>
On 2014/09/16 0:09, Vlad Yasevich wrote:
> On 09/14/2014 11:21 AM, Toshiaki Makita wrote:
>> (14/09/13 (土) 5:44), Vladislav Yasevich wrote:
>>> Currently when vlan filtering is turned on on the bridge, the bridge
>>> will drop all traffic untill the user configures the filter. This
>>> isn't very nice for ports that don't care about vlans and just
>>> want untagged traffic.
>>>
>>> A concept of a default_pvid was recently introduced. This patch
>>> adds filtering support for default_pvid. Now, ports that don't
>>> care about vlans and don't define there own filter will belong
>>> to the VLAN of the default_pvid and continue to receive untagged
>>> traffic.
>>
>> If user sets pvid, then vid 1 (default_pvid) will become non-pvid but
>> still not be filtered, right?
>
> Right.
>
>> vlan_bitmap of default_pvid shouldn't be cleared on setting pvid?
>
> I can see arguments for both. Just because the user wishes to set a
> different pvid may not always mean that vlan associated with default pvid
> shouldn't be filtered. I think it's at user's discretion. I hesitate
> to do too many things automatically.
On second thought, I agree with you.
It's reasonable that what default_pvid should do is only to set pvid on
adding a bridge/port.
My another concern is how we can disable default_pvid, since this
feature is originally non-existent.
Thanks,
Toshiaki Makita
^ permalink raw reply
* [PATCH RFC ipsec-next] xfrm: Add sysctl option to enforce inbound policies for transport mode
From: Tobias Brunner @ 2014-09-16 10:49 UTC (permalink / raw)
To: steffen.klassert, davem; +Cc: netdev
Currently inbound policies for transport mode SAs are not enforced.
If no policy is found or if the templates don't match this is not
considered an error for transport mode SAs.
The new sysctl option (net.core.xfrm_enforce_policies_transport_mode)
allows enforcing the inbound policies also for transport mode SAs.
By default this option remains disabled.
Signed-off-by: Tobias Brunner <tobias@strongswan.org>
---
Consider a transport mode SA between two peers over which only TCP and
ICMP traffic should be allowed. Because two protocols are involved the
selector on the SA itself (xfrm_usersa_info.sel) can't be set. Instead
one either has to negotiate separate SAs for each protocol (with a
selector on each) or negotiate one SA and install two policies that
use it. The problem with the latter is that the peer does not have to
adhere to the negotiated traffic selectors, it is basically free to
send anything over the SA e.g. UDP packets. So if no selectors are
installed on the SA itself, the current implementation would accept
such packets, even though the installed policies don't allow UDP
traffic (some might consider this a security issue - at the very least
it is not very intuitive, especially because the behavior is different
for tunnel mode SAs).
By enabling the new sysctl option the UDP packets would get dropped,
exactly as they would if the SA were negotiated in tunnel mode.
The behavior for optional transport mode templates also changes when
the option is enabled. Basically, the special treatment of transport
mode SAs is disabled and the behavior is like it is for other modes.
I tested this with IPComp/ESP and strongSwan where the optional IPComp
transform is installed in transport or tunnel mode depending on the
negotiated mode of the SA (the ESP SA is always installed in transport
mode in this combination). But I'm not sure if there are other uses
for optional transport mode transforms that might rely on the current
behavior (i.e. why are optional templates treated differently depending
on their mode in the first place?).
With this patch the default behavior remains as it is, but I wondered
why it is like that and if we could perhaps change it so that policies
are enforced by default, thus making such setups more secure out of
the box. Or if we could even change the whole inbound processing so
that transport mode SAs are treated exactly like their counterparts
in other modes, without an option to change it.
Documentation/networking/xfrm_sysctl.txt | 4 ++++
include/net/netns/xfrm.h | 1 +
net/xfrm/xfrm_policy.c | 24 +++++++++++++++---------
net/xfrm/xfrm_sysctl.c | 8 ++++++++
4 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/Documentation/networking/xfrm_sysctl.txt b/Documentation/networking/xfrm_sysctl.txt
index 5bbd167..2fbe539 100644
--- a/Documentation/networking/xfrm_sysctl.txt
+++ b/Documentation/networking/xfrm_sysctl.txt
@@ -2,3 +2,7 @@
xfrm_acq_expires - INTEGER
default 30 - hard timeout in seconds for acquire requests
+
+xfrm_enforce_policies_transport_mode - BOOLEAN
+ default 0 (disabled) - whether to enforce inbound policies for transport
+ mode SAs
\ No newline at end of file
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 9da7982..e045ecc 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -64,6 +64,7 @@ struct netns_xfrm {
u32 sysctl_aevent_rseqth;
int sysctl_larval_drop;
u32 sysctl_acq_expires;
+ int sysctl_enforce_policies_transport_mode;
#ifdef CONFIG_SYSCTL
struct ctl_table_header *sysctl_hdr;
#endif
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 55bcb86..5296f6b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2355,20 +2355,22 @@ xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
* Otherwise "-2 - errored_index" is returned.
*/
static inline int
-xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start,
- unsigned short family)
+xfrm_policy_ok(const struct net *net, const struct xfrm_tmpl *tmpl,
+ const struct sec_path *sp, int start, unsigned short family)
{
int idx = start;
if (tmpl->optional) {
- if (tmpl->mode == XFRM_MODE_TRANSPORT)
+ if (tmpl->mode == XFRM_MODE_TRANSPORT &&
+ !net->xfrm.sysctl_enforce_policies_transport_mode)
return start;
} else
start = -1;
for (; idx < sp->len; idx++) {
if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
return ++idx;
- if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
+ if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT ||
+ net->xfrm.sysctl_enforce_policies_transport_mode) {
if (start == -1)
start = -2-idx;
break;
@@ -2393,10 +2395,13 @@ int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
}
EXPORT_SYMBOL(__xfrm_decode_session);
-static inline int secpath_has_nontransport(const struct sec_path *sp, int k, int *idxp)
+static inline int secpath_has_nontransport(const struct net *net,
+ const struct sec_path *sp,
+ int k, int *idxp)
{
for (; k < sp->len; k++) {
- if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT) {
+ if (sp->xvec[k]->props.mode != XFRM_MODE_TRANSPORT ||
+ net->xfrm.sysctl_enforce_policies_transport_mode) {
*idxp = k;
return 1;
}
@@ -2469,7 +2474,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
}
if (!pol) {
- if (skb->sp && secpath_has_nontransport(skb->sp, 0, &xerr_idx)) {
+ if (skb->sp &&
+ secpath_has_nontransport(net, skb->sp, 0, &xerr_idx)) {
xfrm_secpath_reject(xerr_idx, skb, &fl);
XFRM_INC_STATS(net, LINUX_MIB_XFRMINNOPOLS);
return 0;
@@ -2535,7 +2541,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
* are implied between each two transformations.
*/
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
- k = xfrm_policy_ok(tpp[i], sp, k, family);
+ k = xfrm_policy_ok(net, tpp[i], sp, k, family);
if (k < 0) {
if (k < -1)
/* "-2 - errored_index" returned */
@@ -2545,7 +2551,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
}
}
- if (secpath_has_nontransport(sp, k, &xerr_idx)) {
+ if (secpath_has_nontransport(net, sp, k, &xerr_idx)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINTMPLMISMATCH);
goto reject;
}
diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c
index 05a6e3d..17671af 100644
--- a/net/xfrm/xfrm_sysctl.c
+++ b/net/xfrm/xfrm_sysctl.c
@@ -9,6 +9,7 @@ static void __net_init __xfrm_sysctl_init(struct net *net)
net->xfrm.sysctl_aevent_rseqth = XFRM_AE_SEQT_SIZE;
net->xfrm.sysctl_larval_drop = 1;
net->xfrm.sysctl_acq_expires = 30;
+ net->xfrm.sysctl_enforce_policies_transport_mode = 0;
}
#ifdef CONFIG_SYSCTL
@@ -37,6 +38,12 @@ static struct ctl_table xfrm_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec
},
+ {
+ .procname = "xfrm_enforce_policies_transport_mode",
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
{}
};
@@ -53,6 +60,7 @@ int __net_init xfrm_sysctl_init(struct net *net)
table[1].data = &net->xfrm.sysctl_aevent_rseqth;
table[2].data = &net->xfrm.sysctl_larval_drop;
table[3].data = &net->xfrm.sysctl_acq_expires;
+ table[4].data = &net->xfrm.sysctl_enforce_policies_transport_mode;
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
--
1.9.1
^ permalink raw reply related
* Re: [PATCH] bridge: Fix br_should_learn to check vlan_enabled
From: Toshiaki Makita @ 2014-09-16 10:40 UTC (permalink / raw)
To: David Miller, vyasevich; +Cc: netdev, toshiaki.makita1, vyasevic
In-Reply-To: <20140915.173849.609066505150727105.davem@davemloft.net>
On 2014/09/16 6:38, David Miller wrote:
> From: Vladislav Yasevich <vyasevich@gmail.com>
> Date: Mon, 15 Sep 2014 15:24:26 -0400
>
>> As Toshiaki Makita pointed out, the BRIDGE_INPUT_SKB_CB will
>> not be initialized in br_should_learn() as that function
>> is called only from br_handle_local_finish(). That is
>> an input handler for link-local ethernet traffic so it perfectly
>> correct to check br->vlan_enabled here.
>>
>> Reported-by: Toshiaki Makita<toshiaki.makita1@gmail.com>
>> Fixes: 20adfa1 bridge: Check if vlan filtering is enabled only once.
>> Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
>
> Applied, thanks Vlad.
Hi David,
Could you queue this for -stable as well?
Without this, FDB can be poisoned by disallowed ports.
(the same problem as stated in e0d7968ab6c8 "bridge: Prevent insertion
of FDB entry with disallowed vlan")
Thanks,
Toshiaki Makita
^ permalink raw reply
* Re: bisected regression: 3c59x corrupts packets in 3.17-rc5
From: Meelis Roos @ 2014-09-16 10:32 UTC (permalink / raw)
To: Neil Horman; +Cc: Steffen Klassert, netdev, Linux Kernel list
In-Reply-To: <20140916101704.GA3792@hmsreliant.think-freely.org>
[ Fixed Steffen Klasserts bouncing email address as per the bounce message ]
> > Somewhere between 3.17.0-rc3 and 3.17.0-rc5 I started seeing dropped ssh
> > connections to a couple of test servers with dual AthlonMP (32-bit) and
> > 3C90x family of NICs (3Com Corporation 3c980-C 10/100baseTX NIC
> > [Python-T] (rev 78) in one server and 3Com Corporation 3c905C-TX/TX-M
> > [Tornado] (rev 78) in the other server). Bisect leads to the following
> > commit:
> >
> > 98ea232cf63961fad734cc8c5e07e8915ec73073 is the first bad commit
> > commit 98ea232cf63961fad734cc8c5e07e8915ec73073
> > Author: Neil Horman <nhorman@tuxdriver.com>
> > Date: Thu Sep 4 06:13:38 2014 -0400
> >
> > 3c59x: avoid panic in boomerang_start_xmit when finding page address:
> > ...
> >
> I'm guessing the above change has uncovered another bug, mostly likely an
> exhaustion of dma space on your system. Nothing in the transmit path there does
> any error checking for successful dma mapping, which it really should. I'd be
> willing to be that any dma mapping error leads to a leak in the mapping table.
> Does your system have an iommu, or does it use swiotlb? If its the latter, can
> you increase the swiotlb table space and see if that relieves the problem? In
> the interim, I'll start adding some error checking to the transmit path.
# CONFIG_IOMMU_SUPPORT is not set
nothing matching iommu or iotlb in dmesg. I thought the system does not
have any - K7 CPUs and AMD 760MP chipset with normal AGP gart.
[ 3.763519] agpgart-amdk7 0000:00:00.0: AMD 760MP chipset
[ 3.782995] agpgart-amdk7 0000:00:00.0: AGP aperture is 64M @ 0xf8000000
--
Meelis Roos (mroos@linux.ee)
^ permalink raw reply
* Re: bisected regression: 3c59x corrupts packets in 3.17-rc5
From: Neil Horman @ 2014-09-16 10:17 UTC (permalink / raw)
To: Meelis Roos; +Cc: Steffen Klassert, netdev, Linux Kernel list
In-Reply-To: <alpine.LRH.2.11.1409160209280.21050@adalberg.ut.ee>
On Tue, Sep 16, 2014 at 02:14:54AM +0300, Meelis Roos wrote:
> Somewhere between 3.17.0-rc3 and 3.17.0-rc5 I started seeing dropped ssh
> connections to a couple of test servers with dual AthlonMP (32-bit) and
> 3C90x family of NICs (3Com Corporation 3c980-C 10/100baseTX NIC
> [Python-T] (rev 78) in one server and 3Com Corporation 3c905C-TX/TX-M
> [Tornado] (rev 78) in the other server). Bisect leads to the following
> commit:
>
> 98ea232cf63961fad734cc8c5e07e8915ec73073 is the first bad commit
> commit 98ea232cf63961fad734cc8c5e07e8915ec73073
> Author: Neil Horman <nhorman@tuxdriver.com>
> Date: Thu Sep 4 06:13:38 2014 -0400
>
> 3c59x: avoid panic in boomerang_start_xmit when finding page address:
> ...
>
> --
> Meelis Roos (mroos@linux.ee)
>
I'm guessing the above change has uncovered another bug, mostly likely an
exhaustion of dma space on your system. Nothing in the transmit path there does
any error checking for successful dma mapping, which it really should. I'd be
willing to be that any dma mapping error leads to a leak in the mapping table.
Does your system have an iommu, or does it use swiotlb? If its the latter, can
you increase the swiotlb table space and see if that relieves the problem? In
the interim, I'll start adding some error checking to the transmit path.
Neil
^ permalink raw reply
* [PATCH iproute2] ip lib: Change timestamp to be shorter and on the same line
From: Vadim Kochan @ 2014-09-16 9:58 UTC (permalink / raw)
To: netdev; +Cc: Vadim Kochan
Changed timestamp format to look like more logging info:
[Sep 01 20:56:11.853146]2: enp0s25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default
link/ether 3c:97:0e:a3:86:2e brd ff:ff:ff:ff:ff:ff
Signed-off-by: Vadim Kochan <vadim4j@gmail.com>
---
lib/utils.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/lib/utils.c b/lib/utils.c
index dc21567..03092ba 100644
--- a/lib/utils.c
+++ b/lib/utils.c
@@ -772,14 +772,13 @@ __u8* hexstring_a2n(const char *str, __u8 *buf, int blen)
int print_timestamp(FILE *fp)
{
struct timeval tv;
- char *tstr;
+ char tstr[40] = {};
memset(&tv, 0, sizeof(tv));
gettimeofday(&tv, NULL);
- tstr = asctime(localtime(&tv.tv_sec));
- tstr[strlen(tstr)-1] = 0;
- fprintf(fp, "Timestamp: %s %ld usec\n", tstr, (long)tv.tv_usec);
+ strftime(tstr, sizeof(tstr), "%b %d %H:%M:%S", localtime(&tv.tv_sec));
+ fprintf(fp, "[%s.%ld]", tstr, (long)tv.tv_usec);
return 0;
}
--
2.1.0
^ permalink raw reply related
* Re: TCP connection will hang in FIN_WAIT1 after closing if zero window is advertised
From: Andrey Dmitrov @ 2014-09-16 9:29 UTC (permalink / raw)
To: Neal Cardwell; +Cc: Netdev, Alexandra N. Kossovsky, Konstantin Ushakov
In-Reply-To: <CADVnQym0NmF-Cqz=OEpVBmMAe6T-G1jmoq=fbVWtL7_Ny-wn3w@mail.gmail.com>
On 15/09/14 23:43, Neal Cardwell wrote:
> On Mon, Sep 15, 2014 at 12:11 PM, Andrey Dmitrov
> <andrey.dmitrov@oktetlabs.ru> wrote:
>> It is possible to create a lot of connections in the same manner which will be in FIN_WAIT1 state forever.
> ...
>> After ~10 minutes you will see 500 connections in the FIN_WAIT1 state on the host_A:
>> netstat | grep FIN_WAIT1 | wc -l
>> 500
> Thanks for the report. In your tests, have you ever seen the number of
> such connections exceed net.ipv4.tcp_max_orphans?
>
> Can you set net.ipv4.tcp_max_orphans to a low value and verify that it
> limits the number of such connections? AFAICT it should.
I tried to set net.ipv4.tcp_max_orphans to 100, it limits the
connections number. As I saw net.ipv4.tcp_max_orphans can be exceeded,
but for a short time. Maximum connections number in FIN_WAIT1 state was
196, after that it was decreased rather fast to ~100.
Thanks,
Andrey
^ permalink raw reply
* RE: [PATCH] net: can: usb: peak_usb: pcan_usb_core.c: Cleaning up missing null-terminate in conjunction with strncpy
From: David Laight @ 2014-09-16 8:40 UTC (permalink / raw)
To: 'Rickard Strandqvist'
Cc: Marc Kleine-Budde, Wolfgang Grandegger, Oliver Hartkopp,
Stephane Grosjean, Alexey Khoroshilov, Christopher R. Baker,
linux-can@vger.kernel.org, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <CAFo99gb9Rqnc7HrPbN7UVyQwPv_a=fxAbe+FTtm+9GgsjG7StA@mail.gmail.com>
From: Rickard Strandqvist
> > 2014-09-15 10:47 GMT+02:00 David Laight <David.Laight@aculab.com>:
...
> > Or:
> > char name[sizeof netdev->name];
> > memcpy(name, netdev->name, sizeof netdev->name);
> >
...
> I liked the variant:
> char name[sizeof(netdev->name)];
>
> But dislike and do not understand what the point would be with memcpy variant.
The memcpy() will be a lot faster than any of the string copy functions
because it doesn't need to worry about the terminator.
In many cases it will be inlined to a short series of load and stores.
David
^ permalink raw reply
* Re: [BUG REPORT] Unencrypted packets after SNAT, allthough IPSEC-Policies are present
From: Steffen Klassert @ 2014-09-16 8:39 UTC (permalink / raw)
To: Konstantinos Kolelis
Cc: netdev, davem, kuznet, jmorris, yoshfuji, kaber, herbert
In-Reply-To: <54119F75.8090305@sirrix.com>
On Thu, Sep 11, 2014 at 03:11:17PM +0200, Konstantinos Kolelis wrote:
>
> You should also check what happens if xfrm_larval_drop is false.
> Allthough blackhole route was not used, you could still run into the
> same problem. It just took a while longer.
>
This one should fix the xfrm_larval_drop false case. It applies
on top of my previous patch. Both patches are currenty in the
ipsec testing branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git testing
Subject: [PATCH] xfrm: Generate queueing routes only from route lookup
functions
Currently we genarate a queueing route if we have matching policies
but can not resolve the states and the sysctl xfrm_larval_drop is
disabled. Here we assume that dst_output() is called to kill the
queued packets. Unfortunately this assumption is not true in all
cases, so it is possible that these packets leave the system unwanted.
We fix this by generating queueing routes only from the
route lookup functions, here we can guarantee a call to
dst_output() afterwards.
Fixes: a0073fe18e71 ("xfrm: Add a state resolution packet queue")
Reported-by: Konstantinos Kolelis <k.kolelis@sirrix.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/dst.h | 1 +
net/xfrm/xfrm_policy.c | 32 ++++++++++++++++++++++++--------
2 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/include/net/dst.h b/include/net/dst.h
index fa11c90..a8ae4e7 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -480,6 +480,7 @@ void dst_init(void);
/* Flags for xfrm_lookup flags argument. */
enum {
XFRM_LOOKUP_ICMP = 1 << 0,
+ XFRM_LOOKUP_QUEUE = 1 << 1,
};
struct flowi;
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 7505674..fdde51f 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -39,6 +39,11 @@
#define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ))
#define XFRM_MAX_QUEUE_LEN 100
+struct xfrm_flo {
+ struct dst_entry *dst_orig;
+ u8 flags;
+};
+
static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock);
static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO]
__read_mostly;
@@ -1877,13 +1882,14 @@ static int xdst_queue_output(struct sock *sk, struct sk_buff *skb)
}
static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
- struct dst_entry *dst,
+ struct xfrm_flo *xflo,
const struct flowi *fl,
int num_xfrms,
u16 family)
{
int err;
struct net_device *dev;
+ struct dst_entry *dst;
struct dst_entry *dst1;
struct xfrm_dst *xdst;
@@ -1891,9 +1897,12 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
if (IS_ERR(xdst))
return xdst;
- if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0)
+ if (!(xflo->flags & XFRM_LOOKUP_QUEUE) ||
+ net->xfrm.sysctl_larval_drop ||
+ num_xfrms <= 0)
return xdst;
+ dst = xflo->dst_orig;
dst1 = &xdst->u.dst;
dst_hold(dst);
xdst->route = dst;
@@ -1935,7 +1944,7 @@ static struct flow_cache_object *
xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
struct flow_cache_object *oldflo, void *ctx)
{
- struct dst_entry *dst_orig = (struct dst_entry *)ctx;
+ struct xfrm_flo *xflo = (struct xfrm_flo *)ctx;
struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
struct xfrm_dst *xdst, *new_xdst;
int num_pols = 0, num_xfrms = 0, i, err, pol_dead;
@@ -1976,7 +1985,8 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir,
goto make_dummy_bundle;
}
- new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig);
+ new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family,
+ xflo->dst_orig);
if (IS_ERR(new_xdst)) {
err = PTR_ERR(new_xdst);
if (err != -EAGAIN)
@@ -2010,7 +2020,7 @@ make_dummy_bundle:
/* We found policies, but there's no bundles to instantiate:
* either because the policy blocks, has no transformations or
* we could not build template (no xfrm_states).*/
- xdst = xfrm_create_dummy_bundle(net, dst_orig, fl, num_xfrms, family);
+ xdst = xfrm_create_dummy_bundle(net, xflo, fl, num_xfrms, family);
if (IS_ERR(xdst)) {
xfrm_pols_put(pols, num_pols);
return ERR_CAST(xdst);
@@ -2104,13 +2114,18 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
}
if (xdst == NULL) {
+ struct xfrm_flo xflo;
+
+ xflo.dst_orig = dst_orig;
+ xflo.flags = flags;
+
/* To accelerate a bit... */
if ((dst_orig->flags & DST_NOXFRM) ||
!net->xfrm.policy_count[XFRM_POLICY_OUT])
goto nopol;
flo = flow_cache_lookup(net, fl, family, dir,
- xfrm_bundle_lookup, dst_orig);
+ xfrm_bundle_lookup, &xflo);
if (flo == NULL)
goto nopol;
if (IS_ERR(flo)) {
@@ -2202,7 +2217,8 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
const struct flowi *fl,
struct sock *sk, int flags)
{
- struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, flags);
+ struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk,
+ flags | XFRM_LOOKUP_QUEUE);
if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
return make_blackhole(net, dst_orig->ops->family, dst_orig);
@@ -2476,7 +2492,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family)
skb_dst_force(skb);
- dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0);
+ dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, XFRM_LOOKUP_QUEUE);
if (IS_ERR(dst)) {
res = 0;
dst = NULL;
--
1.9.1
^ permalink raw reply related
* Re: TCP connection will hang in FIN_WAIT1 after closing if zero window is advertised
From: Hannes Frederic Sowa @ 2014-09-16 8:37 UTC (permalink / raw)
To: Eric Dumazet
Cc: Andrey Dmitrov, netdev, Alexandra N. Kossovsky,
Konstantin Ushakov
In-Reply-To: <1410832228.7106.170.camel@edumazet-glaptop2.roam.corp.google.com>
On Tue, Sep 16, 2014, at 03:50, Eric Dumazet wrote:
>
> Why ? If a TARPIT module always answer to zero window probes, these
> sessions would last forever.
The first paragraph from the original mail didn't read like it would
constantly answer to the zero win probes, but after looking at the
attack.lua source I come to the same conclusion.
Bye,
Hannes
^ permalink raw reply
* [net-next PATCH] net: sched: cls_cgroup need tcf_exts_init in all cases
From: John Fastabend @ 2014-09-16 7:33 UTC (permalink / raw)
To: xiyou.wangcong, davem, eric.dumazet; +Cc: netdev, jhs
This ensures the tcf_exts_init() is called for all cases.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
net/sched/cls_cgroup.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c
index 10c7ffd..15c34d4 100644
--- a/net/sched/cls_cgroup.c
+++ b/net/sched/cls_cgroup.c
@@ -116,12 +116,11 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
if (!new)
return -ENOBUFS;
- if (head) {
+ tcf_exts_init(&new->exts, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
+ if (head)
new->handle = head->handle;
- } else {
- tcf_exts_init(&new->exts, TCA_CGROUP_ACT, TCA_CGROUP_POLICE);
+ else
new->handle = handle;
- }
new->tp = tp;
err = nla_parse_nested(tb, TCA_CGROUP_MAX, tca[TCA_OPTIONS],
^ permalink raw reply related
* Re: [BUG REPORT] Unencrypted packets after SNAT, allthough IPSEC-Policies are present
From: Steffen Klassert @ 2014-09-16 7:30 UTC (permalink / raw)
To: Konstantinos Kolelis
Cc: netdev, davem, kuznet, jmorris, yoshfuji, kaber, herbert
In-Reply-To: <20140915120407.GQ6390@secunet.com>
On Mon, Sep 15, 2014 at 02:04:07PM +0200, Steffen Klassert wrote:
> On Mon, Sep 15, 2014 at 10:09:41AM +0200, Steffen Klassert wrote:
> >
> > diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
> > index beeed60..e041822 100644
> > --- a/net/xfrm/xfrm_policy.c
> > +++ b/net/xfrm/xfrm_policy.c
> > @@ -2138,7 +2138,8 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
> > xfrm_pols_put(pols, drop_pols);
> > XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
> >
> > - return make_blackhole(net, family, dst_orig);
> > + err = -EREMOTE;
> > + goto error;
>
> We must return here, otherwise we drop some refcounts too much.
> I'll send an updated patch tomorrow.
>
Below is the updated version of the patch.
Subject: [PATCH] xfrm: Generate blackhole routes only from route lookup
functions
Currently we genarate a blackhole route route whenever we have
matching policies but can not resolve the states. Here we assume
that dst_output() is called to kill the balckholed packets.
Unfortunately this assumption is not true in all cases, so
it is possible that these packets leave the system unwanted.
We fix this by generating blackhole routes only from the
route lookup functions, here we can guarantee a call to
dst_output() afterwards.
Fixes: 2774c131b1d ("xfrm: Handle blackhole route creation via afinfo.")
Reported-by: Konstantinos Kolelis <k.kolelis@sirrix.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/dst.h | 15 ++++++++++++++-
net/ipv4/route.c | 6 +++---
net/ipv6/ip6_output.c | 4 ++--
net/xfrm/xfrm_policy.c | 18 +++++++++++++++++-
4 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/include/net/dst.h b/include/net/dst.h
index 71c60f4..fa11c90 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -490,7 +490,16 @@ static inline struct dst_entry *xfrm_lookup(struct net *net,
int flags)
{
return dst_orig;
-}
+}
+
+static inline struct dst_entry *xfrm_lookup_route(struct net *net,
+ struct dst_entry *dst_orig,
+ const struct flowi *fl,
+ struct sock *sk,
+ int flags)
+{
+ return dst_orig;
+}
static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
{
@@ -502,6 +511,10 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
const struct flowi *fl, struct sock *sk,
int flags);
+struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
+ const struct flowi *fl, struct sock *sk,
+ int flags);
+
/* skb attached with this dst needs transformation if dst->xfrm is valid */
static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst)
{
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index eaa4b00..173e7ea 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2265,9 +2265,9 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
return rt;
if (flp4->flowi4_proto)
- rt = (struct rtable *) xfrm_lookup(net, &rt->dst,
- flowi4_to_flowi(flp4),
- sk, 0);
+ rt = (struct rtable *)xfrm_lookup_route(net, &rt->dst,
+ flowi4_to_flowi(flp4),
+ sk, 0);
return rt;
}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 315a55d..0a3448b 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1009,7 +1009,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
if (final_dst)
fl6->daddr = *final_dst;
- return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
+ return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
}
EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow);
@@ -1041,7 +1041,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
if (final_dst)
fl6->daddr = *final_dst;
- return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
+ return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
}
EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index beeed60..7505674 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2138,7 +2138,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
xfrm_pols_put(pols, drop_pols);
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
- return make_blackhole(net, family, dst_orig);
+ return ERR_PTR(-EREMOTE);
}
err = -EAGAIN;
@@ -2195,6 +2195,22 @@ dropdst:
}
EXPORT_SYMBOL(xfrm_lookup);
+/* Callers of xfrm_lookup_route() must ensure a call to dst_output().
+ * Otherwise we may send out blackholed packets.
+ */
+struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
+ const struct flowi *fl,
+ struct sock *sk, int flags)
+{
+ struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, flags);
+
+ if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
+ return make_blackhole(net, dst_orig->ops->family, dst_orig);
+
+ return dst;
+}
+EXPORT_SYMBOL(xfrm_lookup_route);
+
static inline int
xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl)
{
--
1.9.1
^ permalink raw reply related
* [PATCH net-next v3 5/5] openvswitch: Add recirc and hash action.
From: Pravin B Shelar @ 2014-09-16 7:24 UTC (permalink / raw)
To: davem; +Cc: netdev, Andy Zhou, Pravin B Shelar
From: Andy Zhou <azhou@nicira.com>
Recirc action allows a packet to reenter openvswitch processing.
currently openvswitch lookup flow for packet received and execute
set of actions on that packet, with help of recirc action we can
process/modify the packet and recirculate it back in openvswitch
for another pass.
OVS hash action calculates 5-tupple hash and set hash in flow-key
hash. This can be used along with recirculation for distributing
packets among different ports for bond devices.
For example:
OVS bonding can use following actions:
Match on: bond flow; Action: hash, recirc(id)
Match on: recirc-id == id and hash lower bits == a;
Action: output port_bond_a
Signed-off-by: Andy Zhou <azhou@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
include/uapi/linux/openvswitch.h | 26 +++++
net/openvswitch/actions.c | 203 +++++++++++++++++++++++++++++++++++++--
net/openvswitch/datapath.c | 11 ++-
net/openvswitch/datapath.h | 7 +-
net/openvswitch/flow.c | 7 +-
net/openvswitch/flow.h | 3 +
net/openvswitch/flow_netlink.c | 43 ++++++++-
7 files changed, 288 insertions(+), 12 deletions(-)
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index a794d1d..f7fc507 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -289,6 +289,9 @@ enum ovs_key_attr {
OVS_KEY_ATTR_TUNNEL, /* Nested set of ovs_tunnel attributes */
OVS_KEY_ATTR_SCTP, /* struct ovs_key_sctp */
OVS_KEY_ATTR_TCP_FLAGS, /* be16 TCP flags. */
+ OVS_KEY_ATTR_DP_HASH, /* u32 hash value. Value 0 indicates the hash
+ is not computed by the datapath. */
+ OVS_KEY_ATTR_RECIRC_ID, /* u32 recirc id */
#ifdef __KERNEL__
OVS_KEY_ATTR_IPV4_TUNNEL, /* struct ovs_key_ipv4_tunnel */
@@ -493,6 +496,27 @@ struct ovs_action_push_vlan {
__be16 vlan_tci; /* 802.1Q TCI (VLAN ID and priority). */
};
+/* Data path hash algorithm for computing Datapath hash.
+ *
+ * The algorithm type only specifies the fields in a flow
+ * will be used as part of the hash. Each datapath is free
+ * to use its own hash algorithm. The hash value will be
+ * opaque to the user space daemon.
+ */
+enum ovs_hash_alg {
+ OVS_HASH_ALG_L4,
+};
+
+/*
+ * struct ovs_action_hash - %OVS_ACTION_ATTR_HASH action argument.
+ * @hash_alg: Algorithm used to compute hash prior to recirculation.
+ * @hash_basis: basis used for computing hash.
+ */
+struct ovs_action_hash {
+ uint32_t hash_alg; /* One of ovs_hash_alg. */
+ uint32_t hash_basis;
+};
+
/**
* enum ovs_action_attr - Action types.
*
@@ -521,6 +545,8 @@ enum ovs_action_attr {
OVS_ACTION_ATTR_PUSH_VLAN, /* struct ovs_action_push_vlan. */
OVS_ACTION_ATTR_POP_VLAN, /* No argument. */
OVS_ACTION_ATTR_SAMPLE, /* Nested OVS_SAMPLE_ATTR_*. */
+ OVS_ACTION_ATTR_RECIRC, /* u32 recirc_id. */
+ OVS_ACTION_ATTR_HASH, /* struct ovs_action_hash. */
__OVS_ACTION_ATTR_MAX
};
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index c31bb80..6932a42 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2013 Nicira, Inc.
+ * Copyright (c) 2007-2014 Nicira, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -35,12 +35,78 @@
#include <net/sctp/checksum.h>
#include "datapath.h"
+#include "flow.h"
#include "vport.h"
static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
struct sw_flow_key *key,
const struct nlattr *attr, int len);
+struct deferred_action {
+ struct sk_buff *skb;
+ const struct nlattr *actions;
+
+ /* Store pkt_key clone when creating deferred action. */
+ struct sw_flow_key pkt_key;
+};
+
+#define DEFERRED_ACTION_FIFO_SIZE 10
+struct action_fifo {
+ int head;
+ int tail;
+ /* Deferred action fifo queue storage. */
+ struct deferred_action fifo[DEFERRED_ACTION_FIFO_SIZE];
+};
+
+static struct action_fifo __percpu *action_fifos;
+static DEFINE_PER_CPU(int, exec_actions_level);
+
+static void action_fifo_init(struct action_fifo *fifo)
+{
+ fifo->head = 0;
+ fifo->tail = 0;
+}
+
+static bool action_fifo_is_empty(struct action_fifo *fifo)
+{
+ return (fifo->head == fifo->tail);
+}
+
+static struct deferred_action *action_fifo_get(struct action_fifo *fifo)
+{
+ if (action_fifo_is_empty(fifo))
+ return NULL;
+
+ return &fifo->fifo[fifo->tail++];
+}
+
+static struct deferred_action *action_fifo_put(struct action_fifo *fifo)
+{
+ if (fifo->head >= DEFERRED_ACTION_FIFO_SIZE - 1)
+ return NULL;
+
+ return &fifo->fifo[fifo->head++];
+}
+
+/* Return true if fifo is not full */
+static struct deferred_action *add_deferred_actions(struct sk_buff *skb,
+ struct sw_flow_key *key,
+ const struct nlattr *attr)
+{
+ struct action_fifo *fifo;
+ struct deferred_action *da;
+
+ fifo = this_cpu_ptr(action_fifos);
+ da = action_fifo_put(fifo);
+ if (da) {
+ da->skb = skb;
+ da->actions = attr;
+ da->pkt_key = *key;
+ }
+
+ return da;
+}
+
static int make_writable(struct sk_buff *skb, int write_len)
{
if (!pskb_may_pull(skb, write_len))
@@ -485,8 +551,29 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
/* Skip the sample action when out of memory. */
return 0;
- /* do_execute_actions() will consume the cloned skb. */
- return do_execute_actions(dp, skb, key, a, rem);
+ if (!add_deferred_actions(skb, key, a)) {
+ if (net_ratelimit())
+ pr_warn("%s: deferred actions limit reached, dropping sample action\n",
+ ovs_dp_name(dp));
+
+ kfree_skb(skb);
+ }
+ return 0;
+}
+
+static void execute_hash(struct sk_buff *skb, struct sw_flow_key *key,
+ const struct nlattr *attr)
+{
+ struct ovs_action_hash *hash_act = nla_data(attr);
+ u32 hash = 0;
+
+ /* OVS_HASH_ALG_L4 is the only possible hash algorithm. */
+ hash = skb_get_hash(skb);
+ hash = jhash_1word(hash, hash_act->hash_basis);
+ if (!hash)
+ hash = 0x1;
+
+ key->ovs_flow_hash = hash;
}
static int execute_set_action(struct sk_buff *skb,
@@ -535,6 +622,44 @@ static int execute_set_action(struct sk_buff *skb,
return err;
}
+static int execute_recirc(struct datapath *dp, struct sk_buff *skb,
+ struct sw_flow_key *key,
+ const struct nlattr *a, int rem)
+{
+ struct deferred_action *da;
+ int err;
+
+ err = ovs_flow_key_update(skb, key);
+ if (err)
+ return err;
+
+ if (!last_action(a, rem)) {
+ /* Recirc action is the not the last action
+ * of the action list, need to clone the skb.
+ */
+ skb = skb_clone(skb, GFP_ATOMIC);
+
+ /* Skip the recirc action when out of memory, but
+ * continue on with the rest of the action list.
+ */
+ if (!skb)
+ return 0;
+ }
+
+ da = add_deferred_actions(skb, key, NULL);
+ if (da) {
+ da->pkt_key.recirc_id = nla_get_u32(a);
+ } else {
+ kfree_skb(skb);
+
+ if (net_ratelimit())
+ pr_warn("%s: deferred action limit reached, drop recirc action\n",
+ ovs_dp_name(dp));
+ }
+
+ return 0;
+}
+
/* Execute a list of actions against 'skb'. */
static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
struct sw_flow_key *key,
@@ -566,6 +691,10 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
output_userspace(dp, skb, key, a);
break;
+ case OVS_ACTION_ATTR_HASH:
+ execute_hash(skb, key, a);
+ break;
+
case OVS_ACTION_ATTR_PUSH_VLAN:
err = push_vlan(skb, nla_data(a));
if (unlikely(err)) /* skb already freed. */
@@ -576,6 +705,17 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
err = pop_vlan(skb);
break;
+ case OVS_ACTION_ATTR_RECIRC:
+ err = execute_recirc(dp, skb, key, a, rem);
+ if (last_action(a, rem)) {
+ /* If this is the last action, the skb has
+ * been consumed or freed.
+ * Return immediately.
+ */
+ return err;
+ }
+ break;
+
case OVS_ACTION_ATTR_SET:
err = execute_set_action(skb, nla_data(a));
break;
@@ -601,12 +741,63 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
return 0;
}
+static void process_deferred_actions(struct datapath *dp)
+{
+ struct action_fifo *fifo = this_cpu_ptr(action_fifos);
+
+ /* Do not touch the FIFO in case there is no deferred actions. */
+ if (action_fifo_is_empty(fifo))
+ return;
+
+ /* Finishing executing all deferred actions. */
+ do {
+ struct deferred_action *da = action_fifo_get(fifo);
+ struct sk_buff *skb = da->skb;
+ struct sw_flow_key *key = &da->pkt_key;
+ const struct nlattr *actions = da->actions;
+
+ if (actions)
+ do_execute_actions(dp, skb, key, actions,
+ nla_len(actions));
+ else
+ ovs_dp_process_packet(skb, key);
+ } while (!action_fifo_is_empty(fifo));
+
+ /* Reset FIFO for the next packet. */
+ action_fifo_init(fifo);
+}
+
/* Execute a list of actions against 'skb'. */
int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
struct sw_flow_key *key)
{
- struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
+ int level = this_cpu_read(exec_actions_level);
+ struct sw_flow_actions *acts;
+ int err;
+
+ acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
+
+ this_cpu_inc(exec_actions_level);
+ err = do_execute_actions(dp, skb, key,
+ acts->actions, acts->actions_len);
+
+ if (!level)
+ process_deferred_actions(dp);
+
+ this_cpu_dec(exec_actions_level);
+ return err;
+}
+
+int action_fifos_init(void)
+{
+ action_fifos = alloc_percpu(struct action_fifo);
+ if (!action_fifos)
+ return -ENOMEM;
- return do_execute_actions(dp, skb, key,
- acts->actions, acts->actions_len);
+ return 0;
+}
+
+void action_fifos_exit(void)
+{
+ free_percpu(action_fifos);
}
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 7e08199..16cad14 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -156,7 +156,7 @@ static struct datapath *get_dp(struct net *net, int dp_ifindex)
}
/* Must be called with rcu_read_lock or ovs_mutex. */
-static const char *ovs_dp_name(const struct datapath *dp)
+const char *ovs_dp_name(const struct datapath *dp)
{
struct vport *vport = ovs_vport_ovsl_rcu(dp, OVSP_LOCAL);
return vport->ops->get_name(vport);
@@ -2065,10 +2065,14 @@ static int __init dp_init(void)
pr_info("Open vSwitch switching datapath\n");
- err = ovs_internal_dev_rtnl_link_register();
+ err = action_fifos_init();
if (err)
goto error;
+ err = ovs_internal_dev_rtnl_link_register();
+ if (err)
+ goto error_action_fifos_exit;
+
err = ovs_flow_init();
if (err)
goto error_unreg_rtnl_link;
@@ -2101,6 +2105,8 @@ error_flow_exit:
ovs_flow_exit();
error_unreg_rtnl_link:
ovs_internal_dev_rtnl_link_unregister();
+error_action_fifos_exit:
+ action_fifos_exit();
error:
return err;
}
@@ -2114,6 +2120,7 @@ static void dp_cleanup(void)
ovs_vport_exit();
ovs_flow_exit();
ovs_internal_dev_rtnl_link_unregister();
+ action_fifos_exit();
}
module_init(dp_init);
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 25b0e88..ac3f3df 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2012 Nicira, Inc.
+ * Copyright (c) 2007-2014 Nicira, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -189,13 +189,18 @@ void ovs_dp_detach_port(struct vport *);
int ovs_dp_upcall(struct datapath *, struct sk_buff *,
const struct dp_upcall_info *);
+const char *ovs_dp_name(const struct datapath *dp);
struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 pid, u32 seq,
u8 cmd);
int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
struct sw_flow_key *);
+
void ovs_dp_notify_wq(struct work_struct *work);
+int action_fifos_init(void);
+void action_fifos_exit(void);
+
#define OVS_NLERR(fmt, ...) \
do { \
if (net_ratelimit()) \
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index bf84420..4010423 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2013 Nicira, Inc.
+ * Copyright (c) 2007-2014 Nicira, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -606,6 +606,11 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
return 0;
}
+int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ return key_extract(skb, key);
+}
+
int ovs_flow_key_extract(struct ovs_key_ipv4_tunnel *tun_key,
struct sk_buff *skb, struct sw_flow_key *key)
{
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 3869a54..0f5db4e 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -72,6 +72,8 @@ struct sw_flow_key {
u32 skb_mark; /* SKB mark. */
u16 in_port; /* Input switch port (or DP_MAX_PORTS). */
} __packed phy; /* Safe when right after 'tun_key'. */
+ u32 ovs_flow_hash; /* Datapath computed hash value. */
+ u32 recirc_id; /* Recirculation ID. */
struct {
u8 src[ETH_ALEN]; /* Ethernet source address. */
u8 dst[ETH_ALEN]; /* Ethernet destination address. */
@@ -187,6 +189,7 @@ void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
void ovs_flow_stats_clear(struct sw_flow *);
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(struct ovs_key_ipv4_tunnel *tun_key,
struct sk_buff *skb, struct sw_flow_key *key);
/* Extract key from packet coming from userspace. */
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 630b320..f4c8daa 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2013 Nicira, Inc.
+ * Copyright (c) 2007-2014 Nicira, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -251,6 +251,8 @@ static const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
[OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6),
[OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp),
[OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd),
+ [OVS_KEY_ATTR_RECIRC_ID] = sizeof(u32),
+ [OVS_KEY_ATTR_DP_HASH] = sizeof(u32),
[OVS_KEY_ATTR_TUNNEL] = -1,
};
@@ -454,6 +456,20 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs,
const struct nlattr **a, bool is_mask)
{
+ if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
+ u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
+
+ SW_FLOW_KEY_PUT(match, ovs_flow_hash, hash_val, is_mask);
+ *attrs &= ~(1 << OVS_KEY_ATTR_DP_HASH);
+ }
+
+ if (*attrs & (1 << OVS_KEY_ATTR_RECIRC_ID)) {
+ u32 recirc_id = nla_get_u32(a[OVS_KEY_ATTR_RECIRC_ID]);
+
+ SW_FLOW_KEY_PUT(match, recirc_id, recirc_id, is_mask);
+ *attrs &= ~(1 << OVS_KEY_ATTR_RECIRC_ID);
+ }
+
if (*attrs & (1 << OVS_KEY_ATTR_PRIORITY)) {
SW_FLOW_KEY_PUT(match, phy.priority,
nla_get_u32(a[OVS_KEY_ATTR_PRIORITY]), is_mask);
@@ -873,6 +889,12 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey,
struct nlattr *nla, *encap;
bool is_mask = (swkey != output);
+ if (nla_put_u32(skb, OVS_KEY_ATTR_RECIRC_ID, output->recirc_id))
+ goto nla_put_failure;
+
+ if (nla_put_u32(skb, OVS_KEY_ATTR_DP_HASH, output->ovs_flow_hash))
+ goto nla_put_failure;
+
if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority))
goto nla_put_failure;
@@ -1401,11 +1423,13 @@ int ovs_nla_copy_actions(const struct nlattr *attr,
/* Expected argument lengths, (u32)-1 for variable length. */
static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = {
[OVS_ACTION_ATTR_OUTPUT] = sizeof(u32),
+ [OVS_ACTION_ATTR_RECIRC] = sizeof(u32),
[OVS_ACTION_ATTR_USERSPACE] = (u32)-1,
[OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
[OVS_ACTION_ATTR_POP_VLAN] = 0,
[OVS_ACTION_ATTR_SET] = (u32)-1,
- [OVS_ACTION_ATTR_SAMPLE] = (u32)-1
+ [OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
+ [OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash)
};
const struct ovs_action_push_vlan *vlan;
int type = nla_type(a);
@@ -1432,6 +1456,18 @@ int ovs_nla_copy_actions(const struct nlattr *attr,
return -EINVAL;
break;
+ case OVS_ACTION_ATTR_HASH: {
+ const struct ovs_action_hash *act_hash = nla_data(a);
+
+ switch (act_hash->hash_alg) {
+ case OVS_HASH_ALG_L4:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ break;
+ }
case OVS_ACTION_ATTR_POP_VLAN:
break;
@@ -1444,6 +1480,9 @@ int ovs_nla_copy_actions(const struct nlattr *attr,
return -EINVAL;
break;
+ case OVS_ACTION_ATTR_RECIRC:
+ break;
+
case OVS_ACTION_ATTR_SET:
err = validate_set(a, key, sfa, &skip_copy);
if (err)
--
1.9.3
^ permalink raw reply related
* [PATCH net-next v3 4/5] openvswitch: simplify sample action implementation
From: Pravin B Shelar @ 2014-09-16 7:24 UTC (permalink / raw)
To: davem; +Cc: netdev, Andy Zhou, Pravin B Shelar
From: Andy Zhou <azhou@nicira.com>
The current sample() function implementation is more complicated
than necessary in handling single user space action optimization
and skb reference counting. There is no functional changes.
Signed-off-by: Andy Zhou <azhou@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
net/openvswitch/actions.c | 42 ++++++++++++++++++------------------------
1 file changed, 18 insertions(+), 24 deletions(-)
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 1cdb539..c31bb80 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -448,7 +448,6 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
{
const struct nlattr *acts_list = NULL;
const struct nlattr *a;
- struct sk_buff *sample_skb;
int rem;
for (a = nla_data(attr), rem = nla_len(attr); rem > 0;
@@ -468,31 +467,26 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
rem = nla_len(acts_list);
a = nla_data(acts_list);
- /* Actions list is either empty or only contains a single user-space
- * action, the latter being a special case as it is the only known
- * usage of the sample action.
- * In these special cases don't clone the skb as there are no
- * side-effects in the nested actions.
- * Otherwise, clone in case the nested actions have side effects.
- */
- if (likely(rem == 0 || (nla_type(a) == OVS_ACTION_ATTR_USERSPACE &&
- last_action(a, rem)))) {
- sample_skb = skb;
- skb_get(skb);
- } else {
- sample_skb = skb_clone(skb, GFP_ATOMIC);
- if (!sample_skb) /* Skip sample action when out of memory. */
- return 0;
- }
+ /* Actions list is empty, do nothing */
+ if (unlikely(!rem))
+ return 0;
- /* Note that do_execute_actions() never consumes skb.
- * In the case where skb has been cloned above it is the clone that
- * is consumed. Otherwise the skb_get(skb) call prevents
- * consumption by do_execute_actions(). Thus, it is safe to simply
- * return the error code and let the caller (also
- * do_execute_actions()) free skb on error.
+ /* The only known usage of sample action is having a single user-space
+ * action. Treat this usage as a special case.
+ * The output_userspace() should clone the skb to be sent to the
+ * user space. This skb will be consumed by its caller.
*/
- return do_execute_actions(dp, sample_skb, key, a, rem);
+ if (likely(nla_type(a) == OVS_ACTION_ATTR_USERSPACE &&
+ last_action(a, rem)))
+ return output_userspace(dp, skb, key, a);
+
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (!skb)
+ /* Skip the sample action when out of memory. */
+ return 0;
+
+ /* do_execute_actions() will consume the cloned skb. */
+ return do_execute_actions(dp, skb, key, a, rem);
}
static int execute_set_action(struct sk_buff *skb,
--
1.9.3
^ permalink raw reply related
* [PATCH net-next v3 3/5] openvswitch: Use tun_key only for egress tunnel path.
From: Pravin B Shelar @ 2014-09-16 7:23 UTC (permalink / raw)
To: davem; +Cc: netdev, Pravin B Shelar
Currently tun_key is used for passing tunnel information
on ingress and egress path, this cause confusion. Following
patch removes its use on ingress path make it egress only parameter.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
---
net/openvswitch/actions.c | 3 +--
net/openvswitch/datapath.c | 20 ++++++--------------
net/openvswitch/datapath.h | 8 ++++----
net/openvswitch/flow.c | 7 ++++---
net/openvswitch/flow.h | 3 ++-
net/openvswitch/vport-gre.c | 23 ++++++++++++-----------
net/openvswitch/vport-vxlan.c | 21 +++++++++++----------
net/openvswitch/vport.c | 12 ++++++++++--
8 files changed, 50 insertions(+), 47 deletions(-)
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 8a1eb56..1cdb539 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -510,7 +510,7 @@ static int execute_set_action(struct sk_buff *skb,
break;
case OVS_KEY_ATTR_IPV4_TUNNEL:
- OVS_CB(skb)->tun_key = nla_data(nested_attr);
+ OVS_CB(skb)->egress_tun_key = nla_data(nested_attr);
break;
case OVS_KEY_ATTR_ETHERNET:
@@ -613,7 +613,6 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
{
struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
- OVS_CB(skb)->tun_key = NULL;
return do_execute_actions(dp, skb, key,
acts->actions, acts->actions_len);
}
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 0cce8e6..7e08199 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -237,33 +237,25 @@ void ovs_dp_detach_port(struct vport *p)
}
/* Must be called with rcu_read_lock. */
-void ovs_dp_process_received_packet(struct sk_buff *skb)
+void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key)
{
const struct vport *p = OVS_CB(skb)->input_vport;
struct datapath *dp = p->dp;
struct sw_flow *flow;
struct dp_stats_percpu *stats;
- struct sw_flow_key key;
u64 *stats_counter;
u32 n_mask_hit;
- int error;
stats = this_cpu_ptr(dp->stats_percpu);
- /* Extract flow from 'skb' into 'key'. */
- error = ovs_flow_key_extract(skb, &key);
- if (unlikely(error)) {
- kfree_skb(skb);
- return;
- }
-
/* Look up flow. */
- flow = ovs_flow_tbl_lookup_stats(&dp->table, &key, &n_mask_hit);
+ flow = ovs_flow_tbl_lookup_stats(&dp->table, key, &n_mask_hit);
if (unlikely(!flow)) {
struct dp_upcall_info upcall;
+ int error;
upcall.cmd = OVS_PACKET_CMD_MISS;
- upcall.key = &key;
+ upcall.key = key;
upcall.userdata = NULL;
upcall.portid = ovs_vport_find_upcall_portid(p, skb);
error = ovs_dp_upcall(dp, skb, &upcall);
@@ -277,8 +269,8 @@ void ovs_dp_process_received_packet(struct sk_buff *skb)
OVS_CB(skb)->flow = flow;
- ovs_flow_stats_update(OVS_CB(skb)->flow, key.tp.flags, skb);
- ovs_execute_actions(dp, skb, &key);
+ ovs_flow_stats_update(OVS_CB(skb)->flow, key->tp.flags, skb);
+ ovs_execute_actions(dp, skb, key);
stats_counter = &stats->n_hit;
out:
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 2b982fa..25b0e88 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -95,15 +95,15 @@ struct datapath {
/**
* struct ovs_skb_cb - OVS data in skb CB
* @flow: The flow associated with this packet. May be %NULL if no flow.
- * @tun_key: Key for the tunnel that encapsulated this packet. NULL if the
- * packet is not being tunneled.
+ * @egress_tun_key: Tunnel information about this packet on egress path.
+ * NULL if the packet is not being tunneled.
* @input_vport: The original vport packet came in on. This value is cached
* when a packet is received by OVS.
*/
struct ovs_skb_cb {
struct sw_flow *flow;
- struct ovs_key_ipv4_tunnel *tun_key;
struct vport *input_vport;
+ struct ovs_key_ipv4_tunnel *egress_tun_key;
};
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
@@ -184,7 +184,7 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n
extern struct notifier_block ovs_dp_device_notifier;
extern struct genl_family dp_vport_genl_family;
-void ovs_dp_process_received_packet(struct sk_buff *);
+void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key);
void ovs_dp_detach_port(struct vport *);
int ovs_dp_upcall(struct datapath *, struct sk_buff *,
const struct dp_upcall_info *);
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index d186eb6..bf84420 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -606,12 +606,13 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
return 0;
}
-int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+int ovs_flow_key_extract(struct ovs_key_ipv4_tunnel *tun_key,
+ struct sk_buff *skb, struct sw_flow_key *key)
{
/* Extract metadata from packet. */
memset(key, 0, sizeof(*key));
- if (OVS_CB(skb)->tun_key)
- memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
+ if (tun_key)
+ memcpy(&key->tun_key, tun_key, sizeof(key->tun_key));
key->phy.priority = skb->priority;
key->phy.in_port = OVS_CB(skb)->input_vport->port_no;
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 251789b..3869a54 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -187,7 +187,8 @@ void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
void ovs_flow_stats_clear(struct sw_flow *);
u64 ovs_flow_used_time(unsigned long flow_jiffies);
-int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key);
+int ovs_flow_key_extract(struct ovs_key_ipv4_tunnel *tun_key,
+ struct sk_buff *skb, struct sw_flow_key *key);
/* Extract key from packet coming from userspace. */
int ovs_flow_key_extract_userspace(const struct nlattr *attr,
struct sk_buff *skb,
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c
index f49148a..309cca6 100644
--- a/net/openvswitch/vport-gre.c
+++ b/net/openvswitch/vport-gre.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2013 Nicira, Inc.
+ * Copyright (c) 2007-2014 Nicira, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -63,7 +63,7 @@ static __be16 filter_tnl_flags(__be16 flags)
static struct sk_buff *__build_header(struct sk_buff *skb,
int tunnel_hlen)
{
- const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->tun_key;
+ const struct ovs_key_ipv4_tunnel *tun_key = OVS_CB(skb)->egress_tun_key;
struct tnl_ptk_info tpi;
skb = gre_handle_offloads(skb, !!(tun_key->tun_flags & TUNNEL_CSUM));
@@ -129,6 +129,7 @@ static int gre_err(struct sk_buff *skb, u32 info,
static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
{
struct net *net = ovs_dp_get_net(vport->dp);
+ struct ovs_key_ipv4_tunnel *tun_key;
struct flowi4 fl;
struct rtable *rt;
int min_headroom;
@@ -136,16 +137,17 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
__be16 df;
int err;
- if (unlikely(!OVS_CB(skb)->tun_key)) {
+ if (unlikely(!OVS_CB(skb)->egress_tun_key)) {
err = -EINVAL;
goto error;
}
+ tun_key = OVS_CB(skb)->egress_tun_key;
/* Route lookup */
memset(&fl, 0, sizeof(fl));
- fl.daddr = OVS_CB(skb)->tun_key->ipv4_dst;
- fl.saddr = OVS_CB(skb)->tun_key->ipv4_src;
- fl.flowi4_tos = RT_TOS(OVS_CB(skb)->tun_key->ipv4_tos);
+ fl.daddr = tun_key->ipv4_dst;
+ fl.saddr = tun_key->ipv4_src;
+ fl.flowi4_tos = RT_TOS(tun_key->ipv4_tos);
fl.flowi4_mark = skb->mark;
fl.flowi4_proto = IPPROTO_GRE;
@@ -153,7 +155,7 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
if (IS_ERR(rt))
return PTR_ERR(rt);
- tunnel_hlen = ip_gre_calc_hlen(OVS_CB(skb)->tun_key->tun_flags);
+ tunnel_hlen = ip_gre_calc_hlen(tun_key->tun_flags);
min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len
+ tunnel_hlen + sizeof(struct iphdr)
@@ -185,15 +187,14 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb)
goto err_free_rt;
}
- df = OVS_CB(skb)->tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ?
+ df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ?
htons(IP_DF) : 0;
skb->ignore_df = 1;
return iptunnel_xmit(skb->sk, rt, skb, fl.saddr,
- OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE,
- OVS_CB(skb)->tun_key->ipv4_tos,
- OVS_CB(skb)->tun_key->ipv4_ttl, df, false);
+ tun_key->ipv4_dst, IPPROTO_GRE,
+ tun_key->ipv4_tos, tun_key->ipv4_ttl, df, false);
err_free_rt:
ip_rt_put(rt);
error:
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index d8b7e24..f19539b 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 Nicira, Inc.
+ * Copyright (c) 2014 Nicira, Inc.
* Copyright (c) 2013 Cisco Systems, Inc.
*
* This program is free software; you can redistribute it and/or
@@ -140,22 +140,24 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
struct net *net = ovs_dp_get_net(vport->dp);
struct vxlan_port *vxlan_port = vxlan_vport(vport);
__be16 dst_port = inet_sk(vxlan_port->vs->sock->sk)->inet_sport;
+ struct ovs_key_ipv4_tunnel *tun_key;
struct rtable *rt;
struct flowi4 fl;
__be16 src_port;
__be16 df;
int err;
- if (unlikely(!OVS_CB(skb)->tun_key)) {
+ if (unlikely(!OVS_CB(skb)->egress_tun_key)) {
err = -EINVAL;
goto error;
}
+ tun_key = OVS_CB(skb)->egress_tun_key;
/* Route lookup */
memset(&fl, 0, sizeof(fl));
- fl.daddr = OVS_CB(skb)->tun_key->ipv4_dst;
- fl.saddr = OVS_CB(skb)->tun_key->ipv4_src;
- fl.flowi4_tos = RT_TOS(OVS_CB(skb)->tun_key->ipv4_tos);
+ fl.daddr = tun_key->ipv4_dst;
+ fl.saddr = tun_key->ipv4_src;
+ fl.flowi4_tos = RT_TOS(tun_key->ipv4_tos);
fl.flowi4_mark = skb->mark;
fl.flowi4_proto = IPPROTO_UDP;
@@ -165,7 +167,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
goto error;
}
- df = OVS_CB(skb)->tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ?
+ df = tun_key->tun_flags & TUNNEL_DONT_FRAGMENT ?
htons(IP_DF) : 0;
skb->ignore_df = 1;
@@ -173,11 +175,10 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb)
src_port = udp_flow_src_port(net, skb, 0, 0, true);
err = vxlan_xmit_skb(vxlan_port->vs, rt, skb,
- fl.saddr, OVS_CB(skb)->tun_key->ipv4_dst,
- OVS_CB(skb)->tun_key->ipv4_tos,
- OVS_CB(skb)->tun_key->ipv4_ttl, df,
+ fl.saddr, tun_key->ipv4_dst,
+ tun_key->ipv4_tos, tun_key->ipv4_ttl, df,
src_port, dst_port,
- htonl(be64_to_cpu(OVS_CB(skb)->tun_key->tun_id) << 8),
+ htonl(be64_to_cpu(tun_key->tun_id) << 8),
false);
if (err < 0)
ip_rt_put(rt);
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index acf31aa..5df8377 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -435,6 +435,8 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
struct ovs_key_ipv4_tunnel *tun_key)
{
struct pcpu_sw_netstats *stats;
+ struct sw_flow_key key;
+ int error;
stats = this_cpu_ptr(vport->percpu_stats);
u64_stats_update_begin(&stats->syncp);
@@ -442,9 +444,15 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
stats->rx_bytes += skb->len;
u64_stats_update_end(&stats->syncp);
- OVS_CB(skb)->tun_key = tun_key;
OVS_CB(skb)->input_vport = vport;
- ovs_dp_process_received_packet(skb);
+ OVS_CB(skb)->egress_tun_key = NULL;
+ /* Extract flow from 'skb' into 'key'. */
+ error = ovs_flow_key_extract(tun_key, skb, &key);
+ if (unlikely(error)) {
+ kfree_skb(skb);
+ return;
+ }
+ ovs_dp_process_packet(skb, &key);
}
/**
--
1.9.3
^ permalink raw reply related
* [PATCH net-next v3 2/5] openvswitch: refactor ovs flow extract API.
From: Pravin B Shelar @ 2014-09-16 7:23 UTC (permalink / raw)
To: davem; +Cc: netdev, Pravin B Shelar
OVS flow extract is called on packet receive or packet
execute code path. Following patch defines separate API
for extracting flow-key in packet execute code path.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
---
net/openvswitch/datapath.c | 21 ++++++++++++------
net/openvswitch/datapath.h | 5 ++++-
net/openvswitch/flow.c | 49 ++++++++++++++++++++++++++++++------------
net/openvswitch/flow.h | 6 +++++-
net/openvswitch/flow_netlink.c | 22 ++++++-------------
net/openvswitch/flow_netlink.h | 4 ++--
net/openvswitch/vport.c | 5 +++--
7 files changed, 71 insertions(+), 41 deletions(-)
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 458096d..0cce8e6 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -237,8 +237,9 @@ void ovs_dp_detach_port(struct vport *p)
}
/* Must be called with rcu_read_lock. */
-void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
+void ovs_dp_process_received_packet(struct sk_buff *skb)
{
+ const struct vport *p = OVS_CB(skb)->input_vport;
struct datapath *dp = p->dp;
struct sw_flow *flow;
struct dp_stats_percpu *stats;
@@ -250,7 +251,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
stats = this_cpu_ptr(dp->stats_percpu);
/* Extract flow from 'skb' into 'key'. */
- error = ovs_flow_extract(skb, p->port_no, &key);
+ error = ovs_flow_key_extract(skb, &key);
if (unlikely(error)) {
kfree_skb(skb);
return;
@@ -514,6 +515,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
struct sw_flow *flow;
struct datapath *dp;
struct ethhdr *eth;
+ struct vport *input_vport;
int len;
int err;
@@ -548,13 +550,11 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(flow))
goto err_kfree_skb;
- err = ovs_flow_extract(packet, -1, &flow->key);
+ err = ovs_flow_key_extract_userspace(a[OVS_PACKET_ATTR_KEY], packet,
+ &flow->key);
if (err)
goto err_flow_free;
- err = ovs_nla_get_flow_metadata(flow, a[OVS_PACKET_ATTR_KEY]);
- if (err)
- goto err_flow_free;
acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_PACKET_ATTR_ACTIONS]));
err = PTR_ERR(acts);
if (IS_ERR(acts))
@@ -576,6 +576,15 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
if (!dp)
goto err_unlock;
+ input_vport = ovs_vport_rcu(dp, flow->key.phy.in_port);
+ if (!input_vport)
+ input_vport = ovs_vport_rcu(dp, OVSP_LOCAL);
+
+ if (!input_vport)
+ goto err_unlock;
+
+ OVS_CB(packet)->input_vport = input_vport;
+
local_bh_disable();
err = ovs_execute_actions(dp, packet, &flow->key);
local_bh_enable();
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index b576483..2b982fa 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -97,10 +97,13 @@ struct datapath {
* @flow: The flow associated with this packet. May be %NULL if no flow.
* @tun_key: Key for the tunnel that encapsulated this packet. NULL if the
* packet is not being tunneled.
+ * @input_vport: The original vport packet came in on. This value is cached
+ * when a packet is received by OVS.
*/
struct ovs_skb_cb {
struct sw_flow *flow;
struct ovs_key_ipv4_tunnel *tun_key;
+ struct vport *input_vport;
};
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
@@ -181,7 +184,7 @@ static inline struct vport *ovs_vport_ovsl(const struct datapath *dp, int port_n
extern struct notifier_block ovs_dp_device_notifier;
extern struct genl_family dp_vport_genl_family;
-void ovs_dp_process_received_packet(struct vport *, struct sk_buff *);
+void ovs_dp_process_received_packet(struct sk_buff *);
void ovs_dp_detach_port(struct vport *);
int ovs_dp_upcall(struct datapath *, struct sk_buff *,
const struct dp_upcall_info *);
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 7064da9..d186eb6 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -16,8 +16,6 @@
* 02110-1301, USA
*/
-#include "flow.h"
-#include "datapath.h"
#include <linux/uaccess.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -46,6 +44,10 @@
#include <net/ipv6.h>
#include <net/ndisc.h>
+#include "datapath.h"
+#include "flow.h"
+#include "flow_netlink.h"
+
u64 ovs_flow_used_time(unsigned long flow_jiffies)
{
struct timespec cur_ts;
@@ -420,10 +422,9 @@ invalid:
}
/**
- * ovs_flow_extract - extracts a flow key from an Ethernet frame.
+ * key_extract - extracts a flow key from an Ethernet frame.
* @skb: sk_buff that contains the frame, with skb->data pointing to the
* Ethernet header
- * @in_port: port number on which @skb was received.
* @key: output flow key
*
* The caller must ensure that skb->len >= ETH_HLEN.
@@ -442,19 +443,11 @@ invalid:
* of a correct length, otherwise the same as skb->network_header.
* For other key->eth.type values it is left untouched.
*/
-int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
+static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
{
int error;
struct ethhdr *eth;
- memset(key, 0, sizeof(*key));
-
- key->phy.priority = skb->priority;
- if (OVS_CB(skb)->tun_key)
- memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
- key->phy.in_port = in_port;
- key->phy.skb_mark = skb->mark;
-
skb_reset_mac_header(skb);
/* Link layer. We are guaranteed to have at least the 14 byte Ethernet
@@ -610,6 +603,34 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key)
}
}
}
-
return 0;
}
+
+int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key)
+{
+ /* Extract metadata from packet. */
+ memset(key, 0, sizeof(*key));
+ if (OVS_CB(skb)->tun_key)
+ memcpy(&key->tun_key, OVS_CB(skb)->tun_key, sizeof(key->tun_key));
+
+ key->phy.priority = skb->priority;
+ key->phy.in_port = OVS_CB(skb)->input_vport->port_no;
+ key->phy.skb_mark = skb->mark;
+
+ return key_extract(skb, key);
+}
+
+int ovs_flow_key_extract_userspace(const struct nlattr *attr,
+ struct sk_buff *skb,
+ struct sw_flow_key *key)
+{
+ int err;
+
+ memset(key, 0, sizeof(*key));
+ /* Extract metadata from netlink attributes. */
+ err = ovs_nla_get_flow_metadata(attr, key);
+ if (err)
+ return err;
+
+ return key_extract(skb, key);
+}
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 5e5aaed..251789b 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -187,6 +187,10 @@ void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
void ovs_flow_stats_clear(struct sw_flow *);
u64 ovs_flow_used_time(unsigned long flow_jiffies);
-int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *);
+int ovs_flow_key_extract(struct sk_buff *skb, struct sw_flow_key *key);
+/* Extract key from packet coming from userspace. */
+int ovs_flow_key_extract_userspace(const struct nlattr *attr,
+ struct sk_buff *skb,
+ struct sw_flow_key *key);
#endif /* flow.h */
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index d757848..630b320 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -836,7 +836,7 @@ int ovs_nla_get_match(struct sw_flow_match *match,
/**
* ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key.
- * @flow: Receives extracted in_port, priority, tun_key and skb_mark.
+ * @key: Receives extracted in_port, priority, tun_key and skb_mark.
* @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
* sequence.
*
@@ -846,32 +846,24 @@ int ovs_nla_get_match(struct sw_flow_match *match,
* extracted from the packet itself.
*/
-int ovs_nla_get_flow_metadata(struct sw_flow *flow,
- const struct nlattr *attr)
+int ovs_nla_get_flow_metadata(const struct nlattr *attr,
+ struct sw_flow_key *key)
{
- struct ovs_key_ipv4_tunnel *tun_key = &flow->key.tun_key;
const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
+ struct sw_flow_match match;
u64 attrs = 0;
int err;
- struct sw_flow_match match;
-
- flow->key.phy.in_port = DP_MAX_PORTS;
- flow->key.phy.priority = 0;
- flow->key.phy.skb_mark = 0;
- memset(tun_key, 0, sizeof(flow->key.tun_key));
err = parse_flow_nlattrs(attr, a, &attrs);
if (err)
return -EINVAL;
memset(&match, 0, sizeof(match));
- match.key = &flow->key;
+ match.key = key;
- err = metadata_from_nlattrs(&match, &attrs, a, false);
- if (err)
- return err;
+ key->phy.in_port = DP_MAX_PORTS;
- return 0;
+ return metadata_from_nlattrs(&match, &attrs, a, false);
}
int ovs_nla_put_flow(const struct sw_flow_key *swkey,
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index 4401510..206e45a 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -42,8 +42,8 @@ void ovs_match_init(struct sw_flow_match *match,
int ovs_nla_put_flow(const struct sw_flow_key *,
const struct sw_flow_key *, struct sk_buff *);
-int ovs_nla_get_flow_metadata(struct sw_flow *flow,
- const struct nlattr *attr);
+int ovs_nla_get_flow_metadata(const struct nlattr *, struct sw_flow_key *);
+
int ovs_nla_get_match(struct sw_flow_match *match,
const struct nlattr *,
const struct nlattr *);
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index f7e63f9..acf31aa 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007-2012 Nicira, Inc.
+ * Copyright (c) 2007-2014 Nicira, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
@@ -443,7 +443,8 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb,
u64_stats_update_end(&stats->syncp);
OVS_CB(skb)->tun_key = tun_key;
- ovs_dp_process_received_packet(vport, skb);
+ OVS_CB(skb)->input_vport = vport;
+ ovs_dp_process_received_packet(skb);
}
/**
--
1.9.3
^ permalink raw reply related
* [PATCH net-next v3 1/5] openvswitch: Remove pkt_key from OVS_CB
From: Pravin B Shelar @ 2014-09-16 7:23 UTC (permalink / raw)
To: davem; +Cc: netdev, Pravin B Shelar
OVS keeps pointer to packet key in skb->cb, but the packet key is
store on stack. This could make code bit tricky. So it is better to
get rid of the pointer.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
---
net/openvswitch/actions.c | 22 ++++++++++++----------
net/openvswitch/datapath.c | 6 ++----
net/openvswitch/datapath.h | 5 ++---
3 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 5231652..8a1eb56 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -38,6 +38,7 @@
#include "vport.h"
static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
+ struct sw_flow_key *key,
const struct nlattr *attr, int len);
static int make_writable(struct sk_buff *skb, int write_len)
@@ -410,16 +411,14 @@ static int do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
}
static int output_userspace(struct datapath *dp, struct sk_buff *skb,
- const struct nlattr *attr)
+ struct sw_flow_key *key, const struct nlattr *attr)
{
struct dp_upcall_info upcall;
const struct nlattr *a;
int rem;
- BUG_ON(!OVS_CB(skb)->pkt_key);
-
upcall.cmd = OVS_PACKET_CMD_ACTION;
- upcall.key = OVS_CB(skb)->pkt_key;
+ upcall.key = key;
upcall.userdata = NULL;
upcall.portid = 0;
@@ -445,7 +444,7 @@ static bool last_action(const struct nlattr *a, int rem)
}
static int sample(struct datapath *dp, struct sk_buff *skb,
- const struct nlattr *attr)
+ struct sw_flow_key *key, const struct nlattr *attr)
{
const struct nlattr *acts_list = NULL;
const struct nlattr *a;
@@ -493,7 +492,7 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
* return the error code and let the caller (also
* do_execute_actions()) free skb on error.
*/
- return do_execute_actions(dp, sample_skb, a, rem);
+ return do_execute_actions(dp, sample_skb, key, a, rem);
}
static int execute_set_action(struct sk_buff *skb,
@@ -544,6 +543,7 @@ static int execute_set_action(struct sk_buff *skb,
/* Execute a list of actions against 'skb'. */
static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
+ struct sw_flow_key *key,
const struct nlattr *attr, int len)
{
/* Every output action needs a separate clone of 'skb', but the common
@@ -569,7 +569,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
break;
case OVS_ACTION_ATTR_USERSPACE:
- output_userspace(dp, skb, a);
+ output_userspace(dp, skb, key, a);
break;
case OVS_ACTION_ATTR_PUSH_VLAN:
@@ -587,7 +587,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
break;
case OVS_ACTION_ATTR_SAMPLE:
- err = sample(dp, skb, a);
+ err = sample(dp, skb, key, a);
if (unlikely(err)) /* skb already freed. */
return err;
break;
@@ -608,10 +608,12 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
}
/* Execute a list of actions against 'skb'. */
-int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb)
+int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
+ struct sw_flow_key *key)
{
struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
OVS_CB(skb)->tun_key = NULL;
- return do_execute_actions(dp, skb, acts->actions, acts->actions_len);
+ return do_execute_actions(dp, skb, key,
+ acts->actions, acts->actions_len);
}
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 91d66b7..458096d 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -275,10 +275,9 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
}
OVS_CB(skb)->flow = flow;
- OVS_CB(skb)->pkt_key = &key;
ovs_flow_stats_update(OVS_CB(skb)->flow, key.tp.flags, skb);
- ovs_execute_actions(dp, skb);
+ ovs_execute_actions(dp, skb, &key);
stats_counter = &stats->n_hit;
out:
@@ -568,7 +567,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
goto err_flow_free;
OVS_CB(packet)->flow = flow;
- OVS_CB(packet)->pkt_key = &flow->key;
packet->priority = flow->key.phy.priority;
packet->mark = flow->key.phy.skb_mark;
@@ -579,7 +577,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
goto err_unlock;
local_bh_disable();
- err = ovs_execute_actions(dp, packet);
+ err = ovs_execute_actions(dp, packet, &flow->key);
local_bh_enable();
rcu_read_unlock();
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h
index 701b573..b576483 100644
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -95,13 +95,11 @@ struct datapath {
/**
* struct ovs_skb_cb - OVS data in skb CB
* @flow: The flow associated with this packet. May be %NULL if no flow.
- * @pkt_key: The flow information extracted from the packet. Must be nonnull.
* @tun_key: Key for the tunnel that encapsulated this packet. NULL if the
* packet is not being tunneled.
*/
struct ovs_skb_cb {
struct sw_flow *flow;
- struct sw_flow_key *pkt_key;
struct ovs_key_ipv4_tunnel *tun_key;
};
#define OVS_CB(skb) ((struct ovs_skb_cb *)(skb)->cb)
@@ -191,7 +189,8 @@ int ovs_dp_upcall(struct datapath *, struct sk_buff *,
struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 pid, u32 seq,
u8 cmd);
-int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb);
+int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
+ struct sw_flow_key *);
void ovs_dp_notify_wq(struct work_struct *work);
#define OVS_NLERR(fmt, ...) \
--
1.9.3
^ permalink raw reply related
* [GIT net-next v3] Open vSwitch
From: Pravin B Shelar @ 2014-09-16 7:23 UTC (permalink / raw)
To: davem; +Cc: netdev
Following patches adds recirculation and hash action to OVS.
First patch removes pointer to stack object. Next three patches
does code restructuring which is required for last patch.
Recirculation implementation is changed, according to comments from
David Miller, to avoid using recursive calls in OVS. It is using
queue to record recirc action and deferred recirc is executed at
the end of current actions execution.
v1-v2:
Changed subsystem name in subject to openvswitch
v2-v3:
Added patch to remove pkt_key pointer from skb->cb.
----------------------------------------------------------------
The following changes since commit c1f570a6abc192f047550743f9957b617af605af:
net: dsa: fix mii_bus to host_dev replacement (2014-09-15 17:52:48 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pshelar/openvswitch.git net_next_ovs
for you to fetch changes up to 971427f353f3c42c8dcef62e7124440df68eb809:
openvswitch: Add recirc and hash action. (2014-09-15 23:28:14 -0700)
----------------------------------------------------------------
Andy Zhou (2):
openvswitch: simplify sample action implementation
openvswitch: Add recirc and hash action.
Pravin B Shelar (3):
openvswitch: Remove pkt_key from OVS_CB
openvswitch: refactor ovs flow extract API.
openvswitch: Use tun_key only for egress tunnel path.
include/uapi/linux/openvswitch.h | 26 ++++
net/openvswitch/actions.c | 258 +++++++++++++++++++++++++++++++++------
net/openvswitch/datapath.c | 52 ++++----
net/openvswitch/datapath.h | 23 ++--
net/openvswitch/flow.c | 57 ++++++---
net/openvswitch/flow.h | 10 +-
net/openvswitch/flow_netlink.c | 65 +++++++---
net/openvswitch/flow_netlink.h | 4 +-
net/openvswitch/vport-gre.c | 23 ++--
net/openvswitch/vport-vxlan.c | 21 ++--
net/openvswitch/vport.c | 15 ++-
11 files changed, 428 insertions(+), 126 deletions(-)
^ permalink raw reply
* [net-next PATCH v2 1/4] net: sched: fix unsued cpu variable
From: John Fastabend @ 2014-09-16 6:30 UTC (permalink / raw)
To: xiyou.wangcong, davem, eric.dumazet; +Cc: netdev, jhs
kbuild test robot reported an unused variable cpu in cls_u32.c
after the patch below. This happens when PERF and MARK config
variables are disabled
Fix this is to use separate variables for perf and mark
and define the cpu variable inside the ifdef logic.
'commit 459d5f626da7 ("net: sched: make cls_u32 per cpu")'
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
net/sched/cls_u32.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 5ed5ac4..8cffe5a 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -788,8 +788,8 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
} else {
#ifdef CONFIG_CLS_U32_PERF
struct tc_u32_pcnt *gpf;
-#endif
int cpu;
+#endif
if (nla_put(skb, TCA_U32_SEL,
sizeof(n->sel) + n->sel.nkeys*sizeof(struct tc_u32_key),
@@ -816,9 +816,10 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
struct tc_u32_mark mark = {.val = n->val,
.mask = n->mask,
.success = 0};
+ int cpum;
- for_each_possible_cpu(cpu) {
- __u32 cnt = *per_cpu_ptr(n->pcpu_success, cpu);
+ for_each_possible_cpu(cpum) {
+ __u32 cnt = *per_cpu_ptr(n->pcpu_success, cpum);
mark.success += cnt;
}
^ permalink raw reply related
* [PATCH -net] scsi: fix users of SCSI_FC_ATTRS to depend on NET
From: Randy Dunlap @ 2014-09-16 6:35 UTC (permalink / raw)
To: netdev@vger.kernel.org, linux-scsi, James Bottomley, David Miller
Cc: Fengguang Wu
From: Randy Dunlap <rdunlap@infradead.org>
There are other kconfig symbols which select SCSI_FC_ATTRS,
so they also need to depend on NET to fix kconfig warnings and
build errors:
warning: (LIBFC && SCSI_IBMVFC && SCSI_QLA_FC && SCSI_LPFC && ZFCP && SCSI_BFA_FC && SCSI_CHELSIO_FCOE && FUSION_FC) selects SCSI_FC_ATTRS which has unmet direct dependencies (SCSI && NET)
drivers/scsi/scsi_transport_fc.c: In function 'fc_host_post_event':
drivers/scsi/scsi_transport_fc.c:543:7: error: 'scsi_nl_sock' undeclared (first use in this function)
drivers/scsi/scsi_transport_fc.c: In function 'fc_host_post_vendor_event':
drivers/scsi/scsi_transport_fc.c:611:7: error: 'scsi_nl_sock' undeclared (first use in this function)
Reported-by: Fengguang Wu <fengguang.wu@intel.com> [0-day test robot]
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
---
drivers/message/fusion/Kconfig | 2 +-
drivers/scsi/Kconfig | 9 +++++----
drivers/scsi/csiostor/Kconfig | 2 +-
drivers/scsi/qla2xxx/Kconfig | 2 +-
4 files changed, 8 insertions(+), 7 deletions(-)
--- lnx-317-rc5.orig/drivers/message/fusion/Kconfig
+++ lnx-317-rc5/drivers/message/fusion/Kconfig
@@ -28,7 +28,7 @@ config FUSION_SPI
config FUSION_FC
tristate "Fusion MPT ScsiHost drivers for FC"
- depends on PCI && SCSI
+ depends on PCI && SCSI && NET
select SCSI_FC_ATTRS
---help---
SCSI HOST support for a Fiber Channel host adapters.
--- lnx-317-rc5.orig/drivers/scsi/Kconfig
+++ lnx-317-rc5/drivers/scsi/Kconfig
@@ -585,6 +585,7 @@ config HYPERV_STORAGE
config LIBFC
tristate "LibFC module"
+ depends on NET
select SCSI_FC_ATTRS
select CRC32
---help---
@@ -815,7 +816,7 @@ config SCSI_IBMVSCSI
config SCSI_IBMVFC
tristate "IBM Virtual FC support"
- depends on PPC_PSERIES && SCSI
+ depends on PPC_PSERIES && SCSI && NET
select SCSI_FC_ATTRS
help
This is the IBM POWER Virtual FC Client
@@ -1265,7 +1266,7 @@ source "drivers/scsi/qla4xxx/Kconfig"
config SCSI_LPFC
tristate "Emulex LightPulse Fibre Channel Support"
- depends on PCI && SCSI
+ depends on PCI && SCSI && NET
select SCSI_FC_ATTRS
select CRC_T10DIF
help
@@ -1675,7 +1676,7 @@ config SCSI_SUNESP
config ZFCP
tristate "FCP host bus adapter driver for IBM eServer zSeries"
- depends on S390 && QDIO && SCSI
+ depends on S390 && QDIO && SCSI && NET
select SCSI_FC_ATTRS
help
If you want to access SCSI devices attached to your IBM eServer
@@ -1703,7 +1704,7 @@ config SCSI_PM8001
config SCSI_BFA_FC
tristate "Brocade BFA Fibre Channel Support"
- depends on PCI && SCSI
+ depends on PCI && SCSI && NET
select SCSI_FC_ATTRS
help
This bfa driver supports all Brocade PCIe FC/FCOE host adapters.
--- lnx-317-rc5.orig/drivers/scsi/csiostor/Kconfig
+++ lnx-317-rc5/drivers/scsi/csiostor/Kconfig
@@ -1,6 +1,6 @@
config SCSI_CHELSIO_FCOE
tristate "Chelsio Communications FCoE support"
- depends on PCI && SCSI
+ depends on PCI && SCSI && NET
select SCSI_FC_ATTRS
select FW_LOADER
help
--- lnx-317-rc5.orig/drivers/scsi/qla2xxx/Kconfig
+++ lnx-317-rc5/drivers/scsi/qla2xxx/Kconfig
@@ -1,6 +1,6 @@
config SCSI_QLA_FC
tristate "QLogic QLA2XXX Fibre Channel Support"
- depends on PCI && SCSI
+ depends on PCI && SCSI && NET
select SCSI_FC_ATTRS
select FW_LOADER
---help---
^ permalink raw reply
* [net-next PATCH v2 4/4] net: sched: cls_fw: add missing tcf_exts_init call in fw_change()
From: John Fastabend @ 2014-09-16 6:31 UTC (permalink / raw)
To: xiyou.wangcong, davem, eric.dumazet; +Cc: netdev, jhs
In-Reply-To: <20140916063024.2905.55403.stgit@nitbit.x32>
When allocating a new structure we also need to call tcf_exts_init
to initialize exts.
A follow up patch might be in order to remove some of this code
and do tcf_exts_assign(). With this we could remove the
tcf_exts_init/tcf_exts_change pattern for some of the classifiers.
As part of the future tcf_actions RCU series this will need to be
done. For now fix the call here.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
---
net/sched/cls_fw.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c
index 006b45a..2650285 100644
--- a/net/sched/cls_fw.c
+++ b/net/sched/cls_fw.c
@@ -264,6 +264,8 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
#endif /* CONFIG_NET_CLS_IND */
fnew->tp = f->tp;
+ tcf_exts_init(&fnew->exts, TCA_FW_ACT, TCA_FW_POLICE);
+
err = fw_change_attrs(net, tp, fnew, tb, tca, base, ovr);
if (err < 0) {
kfree(fnew);
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox