* [PATCHv5 net-next 3/5] sctp: implement sender-side procedures for SSN/TSN Reset Request Parameter
From: Xin Long @ 2017-01-21 10:24 UTC (permalink / raw)
To: network dev, linux-sctp
Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem
In-Reply-To: <cover.1484993773.git.lucien.xin@gmail.com>
This patch is to implement Sender-Side Procedures for the SSN/TSN
Reset Request Parameter descibed in rfc6525 section 5.1.4.
It is also to add sockopt SCTP_RESET_ASSOC in rfc6525 section 6.3.3
for users.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/net/sctp/sctp.h | 1 +
include/uapi/linux/sctp.h | 1 +
net/sctp/socket.c | 29 +++++++++++++++++++++++++++++
net/sctp/stream.c | 40 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 71 insertions(+)
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 3cfd365b..b93820f 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -198,6 +198,7 @@ int sctp_offload_init(void);
*/
int sctp_send_reset_streams(struct sctp_association *asoc,
struct sctp_reset_streams *params);
+int sctp_send_reset_assoc(struct sctp_association *asoc);
/*
* Module global variables
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 03c27ce..c0bd8c3 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -117,6 +117,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_PR_ASSOC_STATUS 115
#define SCTP_ENABLE_STREAM_RESET 118
#define SCTP_RESET_STREAMS 119
+#define SCTP_RESET_ASSOC 120
/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index bee4dd3..2c5c9ca 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -3812,6 +3812,32 @@ static int sctp_setsockopt_reset_streams(struct sock *sk,
return retval;
}
+static int sctp_setsockopt_reset_assoc(struct sock *sk,
+ char __user *optval,
+ unsigned int optlen)
+{
+ struct sctp_association *asoc;
+ sctp_assoc_t associd;
+ int retval = -EINVAL;
+
+ if (optlen != sizeof(associd))
+ goto out;
+
+ if (copy_from_user(&associd, optval, optlen)) {
+ retval = -EFAULT;
+ goto out;
+ }
+
+ asoc = sctp_id2assoc(sk, associd);
+ if (!asoc)
+ goto out;
+
+ retval = sctp_send_reset_assoc(asoc);
+
+out:
+ return retval;
+}
+
/* API 6.2 setsockopt(), getsockopt()
*
* Applications use setsockopt() and getsockopt() to set or retrieve
@@ -3984,6 +4010,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
case SCTP_RESET_STREAMS:
retval = sctp_setsockopt_reset_streams(sk, optval, optlen);
break;
+ case SCTP_RESET_ASSOC:
+ retval = sctp_setsockopt_reset_assoc(sk, optval, optlen);
+ break;
default:
retval = -ENOPROTOOPT;
break;
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 6a686e3..53e49fc 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -177,3 +177,43 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
out:
return retval;
}
+
+int sctp_send_reset_assoc(struct sctp_association *asoc)
+{
+ struct sctp_chunk *chunk = NULL;
+ int retval;
+ __u16 i;
+
+ if (!asoc->peer.reconf_capable ||
+ !(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
+ return -ENOPROTOOPT;
+
+ if (asoc->strreset_outstanding)
+ return -EINPROGRESS;
+
+ chunk = sctp_make_strreset_tsnreq(asoc);
+ if (!chunk)
+ return -ENOMEM;
+
+ /* Block further xmit of data until this request is completed */
+ for (i = 0; i < asoc->stream->outcnt; i++)
+ asoc->stream->out[i].state = SCTP_STREAM_CLOSED;
+
+ asoc->strreset_chunk = chunk;
+ sctp_chunk_hold(asoc->strreset_chunk);
+
+ retval = sctp_send_reconf(asoc, chunk);
+ if (retval) {
+ sctp_chunk_put(asoc->strreset_chunk);
+ asoc->strreset_chunk = NULL;
+
+ for (i = 0; i < asoc->stream->outcnt; i++)
+ asoc->stream->out[i].state = SCTP_STREAM_OPEN;
+
+ return retval;
+ }
+
+ asoc->strreset_outstanding = 1;
+
+ return 0;
+}
--
2.1.0
^ permalink raw reply related
* [PATCHv5 net-next 2/5] sctp: add support for generating stream reconf ssn/tsn reset request chunk
From: Xin Long @ 2017-01-21 10:24 UTC (permalink / raw)
To: network dev, linux-sctp
Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem
In-Reply-To: <cover.1484993773.git.lucien.xin@gmail.com>
This patch is to define SSN/TSN Reset Request Parameter described
in rfc6525 section 4.3.
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
include/linux/sctp.h | 5 +++++
include/net/sctp/sm.h | 2 ++
net/sctp/sm_make_chunk.c | 29 +++++++++++++++++++++++++++++
3 files changed, 36 insertions(+)
diff --git a/include/linux/sctp.h b/include/linux/sctp.h
index a9e7906..95b8ed3 100644
--- a/include/linux/sctp.h
+++ b/include/linux/sctp.h
@@ -737,4 +737,9 @@ struct sctp_strreset_inreq {
__u16 list_of_streams[0];
} __packed;
+struct sctp_strreset_tsnreq {
+ sctp_paramhdr_t param_hdr;
+ __u32 request_seq;
+} __packed;
+
#endif /* __LINUX_SCTP_H__ */
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 430ed13..ac37c17 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -265,6 +265,8 @@ struct sctp_chunk *sctp_make_strreset_req(
const struct sctp_association *asoc,
__u16 stream_num, __u16 *stream_list,
bool out, bool in);
+struct sctp_chunk *sctp_make_strreset_tsnreq(
+ const struct sctp_association *asoc);
void sctp_chunk_assign_tsn(struct sctp_chunk *);
void sctp_chunk_assign_ssn(struct sctp_chunk *);
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index ad3445b..801450c 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3660,3 +3660,32 @@ struct sctp_chunk *sctp_make_strreset_req(
return retval;
}
+
+/* RE-CONFIG 4.3 (SSN/TSN RESET ALL)
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Parameter Type = 15 | Parameter Length = 8 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Re-configuration Request Sequence Number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct sctp_chunk *sctp_make_strreset_tsnreq(
+ const struct sctp_association *asoc)
+{
+ struct sctp_strreset_tsnreq tsnreq;
+ __u16 length = sizeof(tsnreq);
+ struct sctp_chunk *retval;
+
+ retval = sctp_make_reconf(asoc, length);
+ if (!retval)
+ return NULL;
+
+ tsnreq.param_hdr.type = SCTP_PARAM_RESET_TSN_REQUEST;
+ tsnreq.param_hdr.length = htons(length);
+ tsnreq.request_seq = htonl(asoc->strreset_outseq);
+
+ sctp_addto_chunk(retval, sizeof(tsnreq), &tsnreq);
+
+ return retval;
+}
--
2.1.0
^ permalink raw reply related
* [PATCHv5 net-next 1/5] sctp: streams should be recovered when it fails to send request.
From: Xin Long @ 2017-01-21 10:24 UTC (permalink / raw)
To: network dev, linux-sctp
Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem
In-Reply-To: <cover.1484993773.git.lucien.xin@gmail.com>
Now when sending stream reset request, it closes the streams to
block further xmit of data until this request is completed, then
calls sctp_send_reconf to send the chunk.
But if sctp_send_reconf returns err, and it doesn't recover the
streams' states back, which means the request chunk would not be
queued and sent, so the asoc will get stuck, streams are closed
and no packet is even queued.
This patch is to fix it by recovering the streams' states when
it fails to send the request, it is also to fix a return value.
Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
---
net/sctp/stream.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index 13d5e07..6a686e3 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -136,8 +136,10 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
goto out;
chunk = sctp_make_strreset_req(asoc, str_nums, str_list, out, in);
- if (!chunk)
+ if (!chunk) {
+ retval = -ENOMEM;
goto out;
+ }
if (out) {
if (str_nums)
@@ -149,7 +151,6 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
stream->out[i].state = SCTP_STREAM_CLOSED;
}
- asoc->strreset_outstanding = out + in;
asoc->strreset_chunk = chunk;
sctp_chunk_hold(asoc->strreset_chunk);
@@ -157,8 +158,22 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
if (retval) {
sctp_chunk_put(asoc->strreset_chunk);
asoc->strreset_chunk = NULL;
+ if (!out)
+ goto out;
+
+ if (str_nums)
+ for (i = 0; i < str_nums; i++)
+ stream->out[str_list[i]].state =
+ SCTP_STREAM_OPEN;
+ else
+ for (i = 0; i < stream->outcnt; i++)
+ stream->out[i].state = SCTP_STREAM_OPEN;
+
+ goto out;
}
+ asoc->strreset_outstanding = out + in;
+
out:
return retval;
}
--
2.1.0
^ permalink raw reply related
* [PATCHv5 net-next 0/5] sctp: add sender-side procedures for stream reconf asoc reset and add streams
From: Xin Long @ 2017-01-21 10:24 UTC (permalink / raw)
To: network dev, linux-sctp
Cc: Marcelo Ricardo Leitner, Neil Horman, Vlad Yasevich, davem
Patch 3/5 is to implement sender-side procedures for the SSN/TSN Reset
Request Parameter described in rfc6525 section 5.1.4, patch 2/5 is
ahead of it to define a function to make the request chunk for it.
Patch 5/5 is to implement sender-side procedures for the Add Incoming
and Outgoing Streams Request Parameter Request Parameter described in
rfc6525 section 5.1.5 and 5.1.6, patch 4/5 is ahead of it to define a
function to make the request chunk for it.
Patch 1/5 is a fix to recover streams states when it fails to send
request.
v1->v2:
- put these into a smaller group.
- rename some temporary variables in the codes.
- rename the titles of the commits and improve some changelogs.
v2->v3:
- re-split the patchset and make sure it has no dead codes for review.
- move some codes into stream.c from socket.c.
v3->v4:
- add one more patch to fix a send reset stream request issue.
- doing actual work only when request is sent successfully.
- reduce some indents in sctp_send_add_streams.
v4->v5:
- close streams before sending request and recover them when sending
fails in patch 1/5 and patch 3/5
Xin Long (5):
sctp: streams should be recovered when it fails to send request.
sctp: add support for generating stream reconf ssn/tsn reset request
chunk
sctp: implement sender-side procedures for SSN/TSN Reset Request
Parameter
sctp: add support for generating stream reconf add incoming/outgoing
streams request chunk
sctp: implement sender-side procedures for Add Incoming/Outgoing
Streams Request Parameter
include/linux/sctp.h | 12 ++++
include/net/sctp/sctp.h | 3 +
include/net/sctp/sm.h | 5 ++
include/uapi/linux/sctp.h | 8 +++
net/sctp/sm_make_chunk.c | 75 +++++++++++++++++++++++++
net/sctp/socket.c | 58 +++++++++++++++++++
net/sctp/stream.c | 138 +++++++++++++++++++++++++++++++++++++++++++++-
7 files changed, 298 insertions(+), 1 deletion(-)
--
2.1.0
^ permalink raw reply
* (unknown),
From: tomsue2000 @ 2017-01-21 9:56 UTC (permalink / raw)
To: netdev
[-- Attachment #1: EMAIL_9865442338_netdev.zip --]
[-- Type: application/zip, Size: 2646 bytes --]
^ permalink raw reply
* Re: [PATCH cumulus-4.1.y 4/5] vxlan: don't flush static fdb entries on admin down
From: kbuild test robot @ 2017-01-21 9:25 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: kbuild-all, davem, netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984410-3304-4-git-send-email-roopa@cumulusnetworks.com>
[-- Attachment #1: Type: text/plain, Size: 2613 bytes --]
Hi Roopa,
[auto build test ERROR on net-next/master]
[also build test ERROR on v4.10-rc4 next-20170120]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Roopa-Prabhu/vxlan-flush-fdb-entries-on-oper-down/20170121-163042
config: x86_64-randconfig-x017-201703 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
drivers/net/vxlan.c: In function 'vxlan_netdevice_event':
drivers/net/vxlan.c:3295:27: error: 'vxlan_netdev_ops' undeclared (first use in this function)
if (dev->netdev_ops == &vxlan_netdev_ops) {
^~~~~~~~~~~~~~~~
drivers/net/vxlan.c:3295:27: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/net/vxlan.c:3297:5: error: too few arguments to function 'vxlan_flush'
vxlan_flush(netdev_priv(dev));
^~~~~~~~~~~
drivers/net/vxlan.c:2368:13: note: declared here
static void vxlan_flush(struct vxlan_dev *vxlan, int do_all)
^~~~~~~~~~~
vim +/vxlan_flush +3297 drivers/net/vxlan.c
acaf4e7099 Daniel Borkmann 2014-01-13 3289
783c146335 Daniel Borkmann 2014-01-22 3290 if (event == NETDEV_UNREGISTER)
acaf4e7099 Daniel Borkmann 2014-01-13 3291 vxlan_handle_lowerdev_unregister(vn, dev);
7c46a640de Alexander Duyck 2016-06-16 3292 else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO)
b7aade1548 Hannes Frederic Sowa 2016-04-18 3293 vxlan_push_rx_ports(dev);
d8ef10fd7d Balakrishnan Raman 2017-01-20 3294 else if (event == NETDEV_CHANGE) {
d8ef10fd7d Balakrishnan Raman 2017-01-20 @3295 if (dev->netdev_ops == &vxlan_netdev_ops) {
d8ef10fd7d Balakrishnan Raman 2017-01-20 3296 if (netif_running(dev) && !netif_oper_up(dev))
d8ef10fd7d Balakrishnan Raman 2017-01-20 @3297 vxlan_flush(netdev_priv(dev));
d8ef10fd7d Balakrishnan Raman 2017-01-20 3298 }
d8ef10fd7d Balakrishnan Raman 2017-01-20 3299 }
acaf4e7099 Daniel Borkmann 2014-01-13 3300
:::::: The code at line 3297 was first introduced by commit
:::::: d8ef10fd7d083cc5551d83db6317a692fee076ba vxlan: flush fdb entries on oper down
:::::: TO: Balakrishnan Raman <ramanb@cumulusnetworks.com>
:::::: CC: 0day robot <fengguang.wu@intel.com>
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27495 bytes --]
^ permalink raw reply
* Re: [PATCH cumulus-4.1.y 1/5] vxlan: flush fdb entries on oper down
From: kbuild test robot @ 2017-01-21 8:58 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: kbuild-all, davem, netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984410-3304-1-git-send-email-roopa@cumulusnetworks.com>
[-- Attachment #1: Type: text/plain, Size: 2760 bytes --]
Hi Balakrishnan,
[auto build test WARNING on net-next/master]
[also build test WARNING on v4.10-rc4 next-20170120]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Roopa-Prabhu/vxlan-flush-fdb-entries-on-oper-down/20170121-163042
config: i386-randconfig-x005-201703 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=i386
All warnings (new ones prefixed by >>):
In file included from include/linux/linkage.h:4:0,
from include/linux/kernel.h:6,
from drivers/net/vxlan.c:13:
drivers/net/vxlan.c: In function 'vxlan_netdevice_event':
drivers/net/vxlan.c:3280:27: error: 'vxlan_netdev_ops' undeclared (first use in this function)
if (dev->netdev_ops == &vxlan_netdev_ops) {
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
>> drivers/net/vxlan.c:3280:3: note: in expansion of macro 'if'
if (dev->netdev_ops == &vxlan_netdev_ops) {
^~
drivers/net/vxlan.c:3280:27: note: each undeclared identifier is reported only once for each function it appears in
if (dev->netdev_ops == &vxlan_netdev_ops) {
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
>> drivers/net/vxlan.c:3280:3: note: in expansion of macro 'if'
if (dev->netdev_ops == &vxlan_netdev_ops) {
^~
vim +/if +3280 drivers/net/vxlan.c
3264 }
3265
3266 unregister_netdevice_many(&list_kill);
3267 }
3268
3269 static int vxlan_netdevice_event(struct notifier_block *unused,
3270 unsigned long event, void *ptr)
3271 {
3272 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
3273 struct vxlan_net *vn = net_generic(dev_net(dev), vxlan_net_id);
3274
3275 if (event == NETDEV_UNREGISTER)
3276 vxlan_handle_lowerdev_unregister(vn, dev);
3277 else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO)
3278 vxlan_push_rx_ports(dev);
3279 else if (event == NETDEV_CHANGE) {
> 3280 if (dev->netdev_ops == &vxlan_netdev_ops) {
3281 if (netif_running(dev) && !netif_oper_up(dev))
3282 vxlan_flush(netdev_priv(dev));
3283 }
3284 }
3285
3286 return NOTIFY_DONE;
3287 }
3288
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29748 bytes --]
^ permalink raw reply
* Re: [PATCH cumulus-4.1.y 1/5] vxlan: flush fdb entries on oper down
From: kbuild test robot @ 2017-01-21 8:54 UTC (permalink / raw)
To: Roopa Prabhu; +Cc: kbuild-all, davem, netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984410-3304-1-git-send-email-roopa@cumulusnetworks.com>
[-- Attachment #1: Type: text/plain, Size: 1551 bytes --]
Hi Balakrishnan,
[auto build test ERROR on net-next/master]
[also build test ERROR on v4.10-rc4 next-20170120]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Roopa-Prabhu/vxlan-flush-fdb-entries-on-oper-down/20170121-163042
config: x86_64-randconfig-x017-201703 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
drivers/net/vxlan.c: In function 'vxlan_netdevice_event':
>> drivers/net/vxlan.c:3280:27: error: 'vxlan_netdev_ops' undeclared (first use in this function)
if (dev->netdev_ops == &vxlan_netdev_ops) {
^~~~~~~~~~~~~~~~
drivers/net/vxlan.c:3280:27: note: each undeclared identifier is reported only once for each function it appears in
vim +/vxlan_netdev_ops +3280 drivers/net/vxlan.c
3274
3275 if (event == NETDEV_UNREGISTER)
3276 vxlan_handle_lowerdev_unregister(vn, dev);
3277 else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO)
3278 vxlan_push_rx_ports(dev);
3279 else if (event == NETDEV_CHANGE) {
> 3280 if (dev->netdev_ops == &vxlan_netdev_ops) {
3281 if (netif_running(dev) && !netif_oper_up(dev))
3282 vxlan_flush(netdev_priv(dev));
3283 }
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 27495 bytes --]
^ permalink raw reply
* [RESEND PATCH net] macsec: fix validation failed in asynchronous operation.
From: Ryder Lee @ 2017-01-21 8:42 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, Sabrina Dubroca, linux-mediatek, Ryder Lee
Add missing "macsec_skb_cb(skb)->valid = true" in callback
function macsec_decrypt_done(), this fixes packet validation
failed while decrypting asynchronously.
Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
---
drivers/net/macsec.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index f83cf66..73d8d39 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -880,6 +880,9 @@ static void macsec_decrypt_done(struct crypto_async_request *base, int err)
aead_request_free(macsec_skb_cb(skb)->req);
rcu_read_lock_bh();
+ if (err == 0)
+ macsec_skb_cb(skb)->valid = true;
+
pn = ntohl(macsec_ethhdr(skb)->packet_number);
if (!macsec_post_decrypt(skb, &macsec->secy, pn)) {
rcu_read_unlock_bh();
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 4/4] xfrm_user: Add new 32/64-agnostic netlink messages
From: kbuild test robot @ 2017-01-21 8:21 UTC (permalink / raw)
To: Kevin Cernekee
Cc: kbuild-all, steffen.klassert, herbert, davem, paul, sds, eparis,
linux-kernel, netdev, selinux, fw, fan.du, dianders, dtor
In-Reply-To: <20170121000507.34381-5-cernekee@chromium.org>
[-- Attachment #1: Type: text/plain, Size: 9722 bytes --]
Hi Kevin,
[auto build test ERROR on ipsec-next/master]
[also build test ERROR on v4.10-rc4 next-20170120]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Kevin-Cernekee/Make-xfrm-usable-by-32-bit-programs/20170121-150712
base: https://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec-next.git master
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.2.0
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=ia64
All errors (new ones prefixed by >>):
>> net/xfrm/xfrm_user_legacy.c:845:5: error: redefinition of 'xfrm_exp_state_notify_legacy'
int xfrm_exp_state_notify_legacy(const struct xfrm_state *x,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from net/xfrm/xfrm_user_legacy.c:30:0:
net/xfrm/xfrm_user.h:131:19: note: previous definition of 'xfrm_exp_state_notify_legacy' was here
static inline int xfrm_exp_state_notify_legacy(const struct xfrm_state *x,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> net/xfrm/xfrm_user_legacy.c:863:5: error: redefinition of 'xfrm_notify_sa_legacy'
int xfrm_notify_sa_legacy(const struct xfrm_state *x, const struct km_event *c)
^~~~~~~~~~~~~~~~~~~~~
In file included from net/xfrm/xfrm_user_legacy.c:30:0:
net/xfrm/xfrm_user.h:137:19: note: previous definition of 'xfrm_notify_sa_legacy' was here
static inline int xfrm_notify_sa_legacy(const struct xfrm_state *x,
^~~~~~~~~~~~~~~~~~~~~
>> net/xfrm/xfrm_user_legacy.c:983:5: error: redefinition of 'xfrm_send_acquire_legacy'
int xfrm_send_acquire_legacy(struct xfrm_state *x,
^~~~~~~~~~~~~~~~~~~~~~~~
In file included from net/xfrm/xfrm_user_legacy.c:30:0:
net/xfrm/xfrm_user.h:143:19: note: previous definition of 'xfrm_send_acquire_legacy' was here
static inline int xfrm_send_acquire_legacy(struct xfrm_state *x,
^~~~~~~~~~~~~~~~~~~~~~~~
>> net/xfrm/xfrm_user_legacy.c:1043:5: error: redefinition of 'xfrm_exp_policy_notify_legacy'
int xfrm_exp_policy_notify_legacy(const struct xfrm_policy *xp,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from net/xfrm/xfrm_user_legacy.c:30:0:
net/xfrm/xfrm_user.h:150:19: note: previous definition of 'xfrm_exp_policy_notify_legacy' was here
static inline int xfrm_exp_policy_notify_legacy(const struct xfrm_policy *xp,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> net/xfrm/xfrm_user_legacy.c:1060:5: error: redefinition of 'xfrm_notify_policy_legacy'
int xfrm_notify_policy_legacy(const struct xfrm_policy *xp,
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from net/xfrm/xfrm_user_legacy.c:30:0:
net/xfrm/xfrm_user.h:157:19: note: previous definition of 'xfrm_notify_policy_legacy' was here
static inline int xfrm_notify_policy_legacy(const struct xfrm_policy *xp,
^~~~~~~~~~~~~~~~~~~~~~~~~
vim +/xfrm_exp_state_notify_legacy +845 net/xfrm/xfrm_user_legacy.c
839 return err;
840
841 nlmsg_end(skb, nlh);
842 return 0;
843 }
844
> 845 int xfrm_exp_state_notify_legacy(const struct xfrm_state *x,
846 const struct km_event *c)
847 {
848 struct net *net = xs_net(x);
849 struct sk_buff *skb;
850
851 skb = nlmsg_new(xfrm_expire_msgsize(), GFP_ATOMIC);
852 if (skb == NULL)
853 return -ENOMEM;
854
855 if (build_expire(skb, x, c) < 0) {
856 kfree_skb(skb);
857 return -EMSGSIZE;
858 }
859
860 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_EXPIRE);
861 }
862
> 863 int xfrm_notify_sa_legacy(const struct xfrm_state *x, const struct km_event *c)
864 {
865 struct net *net = xs_net(x);
866 struct xfrm_usersa_info_legacy *p;
867 struct xfrm_usersa_id *id;
868 struct nlmsghdr *nlh;
869 struct sk_buff *skb;
870 int len = xfrm_sa_len(x);
871 int headlen, err;
872 u32 event = 0;
873
874 headlen = sizeof(*p);
875 if (c->event == XFRM_MSG_DELSA) {
876 len += nla_total_size(headlen);
877 headlen = sizeof(*id);
878 len += nla_total_size(sizeof(struct xfrm_mark));
879 }
880 len += NLMSG_ALIGN(headlen);
881
882 skb = nlmsg_new(len, GFP_ATOMIC);
883 if (skb == NULL)
884 return -ENOMEM;
885
886 switch (c->event) {
887 case XFRM_MSG_NEWSA:
888 event = XFRM_MSG_NEWSA_LEGACY;
889 break;
890 case XFRM_MSG_UPDSA:
891 event = XFRM_MSG_UPDSA_LEGACY;
892 break;
893 case XFRM_MSG_DELSA:
894 event = XFRM_MSG_DELSA_LEGACY;
895 break;
896 }
897
898 nlh = nlmsg_put(skb, c->portid, c->seq, event, headlen, 0);
899 err = -EMSGSIZE;
900 if (nlh == NULL)
901 goto out_free_skb;
902
903 p = nlmsg_data(nlh);
904 if (c->event == XFRM_MSG_DELSA) {
905 struct nlattr *attr;
906
907 id = nlmsg_data(nlh);
908 memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
909 id->spi = x->id.spi;
910 id->family = x->props.family;
911 id->proto = x->id.proto;
912
913 attr = nla_reserve(skb, XFRMA_SA, sizeof(*p));
914 err = -EMSGSIZE;
915 if (attr == NULL)
916 goto out_free_skb;
917
918 p = nla_data(attr);
919 }
920 err = copy_to_user_state_extra(x, p, skb);
921 if (err)
922 goto out_free_skb;
923
924 nlmsg_end(skb, nlh);
925
926 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_SA);
927
928 out_free_skb:
929 kfree_skb(skb);
930 return err;
931 }
932
933 static inline size_t xfrm_acquire_msgsize(const struct xfrm_state *x,
934 const struct xfrm_policy *xp)
935 {
936 return NLMSG_ALIGN(sizeof(struct xfrm_user_acquire_legacy))
937 + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
938 + nla_total_size(sizeof(struct xfrm_mark))
939 + nla_total_size(xfrm_user_sec_ctx_size(x->security))
940 + userpolicy_type_attrsize();
941 }
942
943 static int build_acquire(struct sk_buff *skb,
944 struct xfrm_state *x,
945 const struct xfrm_tmpl *xt,
946 const struct xfrm_policy *xp)
947 {
948 __u32 seq = xfrm_get_acqseq();
949 struct xfrm_user_acquire_legacy *ua;
950 struct nlmsghdr *nlh;
951 int err;
952
953 nlh = nlmsg_put(skb, 0, 0, XFRM_MSG_ACQUIRE_LEGACY, sizeof(*ua), 0);
954 if (nlh == NULL)
955 return -EMSGSIZE;
956
957 ua = nlmsg_data(nlh);
958 memcpy(&ua->id, &x->id, sizeof(ua->id));
959 memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr));
960 memcpy(&ua->sel, &x->sel, sizeof(ua->sel));
961 copy_to_user_policy(xp, &ua->policy, XFRM_POLICY_OUT);
962 ua->aalgos = xt->aalgos;
963 ua->ealgos = xt->ealgos;
964 ua->calgos = xt->calgos;
965 ua->seq = x->km.seq = seq;
966
967 err = xfrm_copy_to_user_tmpl(xp, skb);
968 if (!err)
969 err = copy_to_user_state_sec_ctx(x, skb);
970 if (!err)
971 err = copy_to_user_policy_type(xp->type, skb);
972 if (!err)
973 err = xfrm_mark_put(skb, &xp->mark);
974 if (err) {
975 nlmsg_cancel(skb, nlh);
976 return err;
977 }
978
979 nlmsg_end(skb, nlh);
980 return 0;
981 }
982
> 983 int xfrm_send_acquire_legacy(struct xfrm_state *x,
984 const struct xfrm_tmpl *xt,
985 const struct xfrm_policy *xp)
986 {
987 struct net *net = xs_net(x);
988 struct sk_buff *skb;
989
990 skb = nlmsg_new(xfrm_acquire_msgsize(x, xp), GFP_ATOMIC);
991 if (skb == NULL)
992 return -ENOMEM;
993
994 if (build_acquire(skb, x, xt, xp) < 0)
995 BUG();
996
997 return xfrm_nlmsg_multicast(net, skb, 0, XFRMNLGRP_ACQUIRE);
998 }
999
1000 static inline size_t xfrm_polexpire_msgsize(const struct xfrm_policy *xp)
1001 {
1002 return NLMSG_ALIGN(sizeof(struct xfrm_user_polexpire_legacy))
1003 + nla_total_size(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr)
1004 + nla_total_size(xfrm_user_sec_ctx_size(xp->security))
1005 + nla_total_size(sizeof(struct xfrm_mark))
1006 + userpolicy_type_attrsize();
1007 }
1008
1009 static int build_polexpire(struct sk_buff *skb,
1010 const struct xfrm_policy *xp,
1011 int dir,
1012 const struct km_event *c)
1013 {
1014 struct xfrm_user_polexpire_legacy *upe;
1015 int hard = c->data.hard;
1016 struct nlmsghdr *nlh;
1017 int err;
1018
1019 nlh = nlmsg_put(skb, c->portid, 0, XFRM_MSG_POLEXPIRE_LEGACY,
1020 sizeof(*upe), 0);
1021 if (nlh == NULL)
1022 return -EMSGSIZE;
1023
1024 upe = nlmsg_data(nlh);
1025 copy_to_user_policy(xp, &upe->pol, dir);
1026 err = xfrm_copy_to_user_tmpl(xp, skb);
1027 if (!err)
1028 err = copy_to_user_sec_ctx(xp, skb);
1029 if (!err)
1030 err = copy_to_user_policy_type(xp->type, skb);
1031 if (!err)
1032 err = xfrm_mark_put(skb, &xp->mark);
1033 if (err) {
1034 nlmsg_cancel(skb, nlh);
1035 return err;
1036 }
1037 upe->hard = !!hard;
1038
1039 nlmsg_end(skb, nlh);
1040 return 0;
1041 }
1042
> 1043 int xfrm_exp_policy_notify_legacy(const struct xfrm_policy *xp,
1044 int dir,
1045 const struct km_event *c)
1046 {
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 45848 bytes --]
^ permalink raw reply
* [PATCH net-next 2/2] vxlan: do not age static remote mac entries
From: Roopa Prabhu @ 2017-01-21 7:43 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984599-16712-1-git-send-email-roopa@cumulusnetworks.com>
From: Balakrishnan Raman <ramanb@cumulusnetworks.com>
Mac aging is applicable only for dynamically learnt remote mac
entries. Check for user configured static remote mac entries
and skip aging.
Signed-off-by: Balakrishnan Raman <ramanb@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
drivers/net/vxlan.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 269e515..2c5bb0a 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2268,7 +2268,7 @@ static void vxlan_cleanup(unsigned long arg)
= container_of(p, struct vxlan_fdb, hlist);
unsigned long timeout;
- if (f->state & NUD_PERMANENT)
+ if (f->state & (NUD_PERMANENT | NUD_NOARP))
continue;
timeout = f->used + vxlan->cfg.age_interval * HZ;
--
1.9.1
^ permalink raw reply related
* [PATCH net-next 0/2] vxlan: misc fdb fixes
From: Roopa Prabhu @ 2017-01-21 7:43 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
From: Roopa Prabhu <roopa@cumulusnetworks.com>
Balakrishnan Raman (1):
vxlan: do not age static remote mac entries
Roopa Prabhu (1):
vxlan: don't flush static fdb entries on admin down
drivers/net/vxlan.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH net-next 1/2] vxlan: don't flush static fdb entries on admin down
From: Roopa Prabhu @ 2017-01-21 7:43 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984599-16712-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
This patch skips flushing static fdb entries in
ndo_stop, but flushes all fdb entries during vxlan
device delete. This is consistent with the bridge
driver fdb
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
drivers/net/vxlan.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 19b1653..269e515 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2354,7 +2354,7 @@ static int vxlan_open(struct net_device *dev)
}
/* Purge the forwarding table */
-static void vxlan_flush(struct vxlan_dev *vxlan)
+static void vxlan_flush(struct vxlan_dev *vxlan, int do_all)
{
unsigned int h;
@@ -2364,6 +2364,8 @@ static void vxlan_flush(struct vxlan_dev *vxlan)
hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) {
struct vxlan_fdb *f
= container_of(p, struct vxlan_fdb, hlist);
+ if (!do_all && (f->state & (NUD_PERMANENT | NUD_NOARP)))
+ continue;
/* the all_zeros_mac entry is deleted at vxlan_uninit */
if (!is_zero_ether_addr(f->eth_addr))
vxlan_fdb_destroy(vxlan, f);
@@ -2385,7 +2387,7 @@ static int vxlan_stop(struct net_device *dev)
del_timer_sync(&vxlan->age_timer);
- vxlan_flush(vxlan);
+ vxlan_flush(vxlan, 0);
vxlan_sock_release(vxlan);
return ret;
@@ -3058,6 +3060,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+ vxlan_flush(vxlan, 1);
+
spin_lock(&vn->sock_lock);
if (!hlist_unhashed(&vxlan->hlist))
hlist_del_rcu(&vxlan->hlist);
--
1.9.1
^ permalink raw reply related
* Re: [PATCH cumulus-4.1.y 1/5] vxlan: flush fdb entries on oper down
From: Roopa Prabhu @ 2017-01-21 7:41 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984410-3304-1-git-send-email-roopa@cumulusnetworks.com>
On 1/20/17, 11:40 PM, Roopa Prabhu wrote:
> From: Balakrishnan Raman <ramanb@cumulusnetworks.com>
>
> Flush fdb entries of a vxlan device when its state
> changes to oper down. vxlan_stop handles flush on
> admin down.
>
> Signed-off-by: Balakrishnan Raman <ramanb@cumulusnetworks.com>
> Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
> ---
>
pls ignore this series. Accidently hit send in the wrong folder :(
^ permalink raw reply
* [PATCH cumulus-4.1.y 2/5] vxlan: don't replace fdb entry if nothing changed
From: Roopa Prabhu @ 2017-01-21 7:40 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984410-3304-1-git-send-email-roopa@cumulusnetworks.com>
From: Balakrishnan Raman <ramanb@cumulusnetworks.com>
This will avoid unnecessary notifications to userspace.
Signed-off-by: Balakrishnan Raman <ramanb@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
drivers/net/vxlan.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 15b1c23..72b99ff 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -467,12 +467,19 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f,
if (!rd)
return 0;
- dst_cache_reset(&rd->dst_cache);
- rd->remote_ip = *ip;
- rd->remote_port = port;
- rd->remote_vni = vni;
- rd->remote_ifindex = ifindex;
- return 1;
+ if (!vxlan_addr_equal(&rd->remote_ip, ip) ||
+ rd->remote_port != port ||
+ rd->remote_vni != vni ||
+ rd->remote_ifindex != ifindex) {
+ dst_cache_reset(&rd->dst_cache);
+ rd->remote_ip = *ip;
+ rd->remote_port = port;
+ rd->remote_vni = vni;
+ rd->remote_ifindex = ifindex;
+ return 1;
+ }
+
+ return 0;
}
/* Add/update destinations for multicast */
--
1.9.1
^ permalink raw reply related
* [PATCH cumulus-4.1.y 1/5] vxlan: flush fdb entries on oper down
From: Roopa Prabhu @ 2017-01-21 7:40 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
From: Balakrishnan Raman <ramanb@cumulusnetworks.com>
Flush fdb entries of a vxlan device when its state
changes to oper down. vxlan_stop handles flush on
admin down.
Signed-off-by: Balakrishnan Raman <ramanb@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
drivers/net/vxlan.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 19b1653..15b1c23 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -3276,6 +3276,12 @@ static int vxlan_netdevice_event(struct notifier_block *unused,
vxlan_handle_lowerdev_unregister(vn, dev);
else if (event == NETDEV_UDP_TUNNEL_PUSH_INFO)
vxlan_push_rx_ports(dev);
+ else if (event == NETDEV_CHANGE) {
+ if (dev->netdev_ops == &vxlan_netdev_ops) {
+ if (netif_running(dev) && !netif_oper_up(dev))
+ vxlan_flush(netdev_priv(dev));
+ }
+ }
return NOTIFY_DONE;
}
--
1.9.1
^ permalink raw reply related
* [PATCH cumulus-4.1.y 3/5] vxlan: enforce precedence for static over dynamic fdb entry
From: Roopa Prabhu @ 2017-01-21 7:40 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984410-3304-1-git-send-email-roopa@cumulusnetworks.com>
From: Wilson Kok <wkok@cumulusnetworks.com>
This patch enforces fdb state correctly when deciding
to add or update an existing fdb. It makes sure static fdb
entries are not replaced by dynamic fdb entries.
Signed-off-by: Wilson Kok <wkok@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
drivers/net/vxlan.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 72b99ff..7300586 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -628,6 +628,10 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
return -EEXIST;
}
if (f->state != state) {
+ if ((f->state & NUD_PERMANENT) &&
+ !(state & NUD_PERMANENT))
+ return -EINVAL;
+
f->state = state;
f->updated = jiffies;
notify = 1;
--
1.9.1
^ permalink raw reply related
* [PATCH cumulus-4.1.y 5/5] vxlan: do not age static remote mac entries
From: Roopa Prabhu @ 2017-01-21 7:40 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984410-3304-1-git-send-email-roopa@cumulusnetworks.com>
From: Balakrishnan Raman <ramanb@cumulusnetworks.com>
Mac aging is applicable only for dynamically learnt remote mac
entries. Check for user configured static remote mac entries
and skip aging.
Signed-off-by: Balakrishnan Raman <ramanb@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
drivers/net/vxlan.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 3314090..312240c 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2279,7 +2279,7 @@ static void vxlan_cleanup(unsigned long arg)
= container_of(p, struct vxlan_fdb, hlist);
unsigned long timeout;
- if (f->state & NUD_PERMANENT)
+ if (f->state & (NUD_PERMANENT | NUD_NOARP))
continue;
timeout = f->used + vxlan->cfg.age_interval * HZ;
--
1.9.1
^ permalink raw reply related
* [PATCH cumulus-4.1.y 4/5] vxlan: don't flush static fdb entries on admin down
From: Roopa Prabhu @ 2017-01-21 7:40 UTC (permalink / raw)
To: davem; +Cc: netdev, ramanb, stephen, jbenc, pshelar
In-Reply-To: <1484984410-3304-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
This patch skips flushing static fdb entries in
ndo_stop, but flushes all fdb entries during vxlan
device delete. This is consistent with the bridge
driver fdb
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
drivers/net/vxlan.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 7300586..3314090 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2365,7 +2365,7 @@ static int vxlan_open(struct net_device *dev)
}
/* Purge the forwarding table */
-static void vxlan_flush(struct vxlan_dev *vxlan)
+static void vxlan_flush(struct vxlan_dev *vxlan, int do_all)
{
unsigned int h;
@@ -2375,6 +2375,8 @@ static void vxlan_flush(struct vxlan_dev *vxlan)
hlist_for_each_safe(p, n, &vxlan->fdb_head[h]) {
struct vxlan_fdb *f
= container_of(p, struct vxlan_fdb, hlist);
+ if (!do_all && (f->state & (NUD_PERMANENT | NUD_NOARP)))
+ continue;
/* the all_zeros_mac entry is deleted at vxlan_uninit */
if (!is_zero_ether_addr(f->eth_addr))
vxlan_fdb_destroy(vxlan, f);
@@ -2396,7 +2398,7 @@ static int vxlan_stop(struct net_device *dev)
del_timer_sync(&vxlan->age_timer);
- vxlan_flush(vxlan);
+ vxlan_flush(vxlan, 0);
vxlan_sock_release(vxlan);
return ret;
@@ -3069,6 +3071,8 @@ static void vxlan_dellink(struct net_device *dev, struct list_head *head)
struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
+ vxlan_flush(vxlan, 1);
+
spin_lock(&vn->sock_lock);
if (!hlist_unhashed(&vxlan->hlist))
hlist_del_rcu(&vxlan->hlist);
--
1.9.1
^ permalink raw reply related
* [PATCH v2] net: xilinx: constify net_device_ops structure
From: Bhumika Goyal @ 2017-01-21 6:58 UTC (permalink / raw)
To: julia.lawall, michal.simek, soren.brinkmann, netdev,
linux-arm-kernel, linux-kernel
Cc: Bhumika Goyal
Declare net_device_ops structure as const as it is only stored in
the netdev_ops field of a net_device structure. This field is of type
const, so net_device_ops structures having same properties can be made
const too.
Done using Coccinelle:
@r1 disable optional_qualifier@
identifier i;
position p;
@@
static struct net_device_ops i@p={...};
@ok1@
identifier r1.i;
position p;
struct net_device ndev;
@@
ndev.netdev_ops=&i@p
@bad@
position p!={r1.p,ok1.p};
identifier r1.i;
@@
i@p
@depends on !bad disable optional_qualifier@
identifier r1.i;
@@
+const
struct net_device_ops i;
File size before:
text data bss dec hex filename
6201 744 0 6945 1b21 ethernet/xilinx/xilinx_emaclite.o
File size after:
text data bss dec hex filename
6745 192 0 6937 1b19 ethernet/xilinx/xilinx_emaclite.o
Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
---
Changes in v2:
* Corrected the commit message.
drivers/net/ethernet/xilinx/xilinx_emaclite.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 93dc10b..546f569 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -1065,7 +1065,7 @@ static bool get_bool(struct platform_device *ofdev, const char *s)
}
}
-static struct net_device_ops xemaclite_netdev_ops;
+static const struct net_device_ops xemaclite_netdev_ops;
/**
* xemaclite_of_probe - Probe method for the Emaclite device.
@@ -1219,7 +1219,7 @@ static int xemaclite_of_remove(struct platform_device *of_dev)
}
#endif
-static struct net_device_ops xemaclite_netdev_ops = {
+static const struct net_device_ops xemaclite_netdev_ops = {
.ndo_open = xemaclite_open,
.ndo_stop = xemaclite_close,
.ndo_start_xmit = xemaclite_send,
--
1.9.1
^ permalink raw reply related
* [PATCH v2] net: moxa: constify net_device_ops structures
From: Bhumika Goyal @ 2017-01-21 6:57 UTC (permalink / raw)
To: julia.lawall, dan.carpenter, davem, netdev, linux-kernel; +Cc: Bhumika Goyal
Declare net_device_ops structure as const as it is only stored in
the netdev_ops field of a net_device structure. This field is of type
const, so net_device_ops structures having same properties can be made
const too.
Done using Coccinelle:
@r1 disable optional_qualifier@
identifier i;
position p;
@@
static struct net_device_ops i@p={...};
@ok1@
identifier r1.i;
position p;
struct net_device ndev;
@@
ndev.netdev_ops=&i@p
@bad@
position p!={r1.p,ok1.p};
identifier r1.i;
@@
i@p
@depends on !bad disable optional_qualifier@
identifier r1.i;
@@
+const
struct net_device_ops i;
File size before:
text data bss dec hex filename
4821 744 0 5565 15bd ethernet/moxa/moxart_ether.o
File size after:
text data bss dec hex filename
5373 192 0 5565 15bd ethernet/moxa/moxart_ether.o
Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
---
Changes in v2:
* Corrected the commit message.
drivers/net/ethernet/moxa/moxart_ether.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index 9774b50..6a6525f 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -436,7 +436,7 @@ static void moxart_mac_set_rx_mode(struct net_device *ndev)
spin_unlock_irq(&priv->txlock);
}
-static struct net_device_ops moxart_netdev_ops = {
+static const struct net_device_ops moxart_netdev_ops = {
.ndo_open = moxart_mac_open,
.ndo_stop = moxart_mac_stop,
.ndo_start_xmit = moxart_mac_start_xmit,
--
1.9.1
^ permalink raw reply related
* [PATCH] net: moxa: constify net_device_ops structures
From: Bhumika Goyal @ 2017-01-21 6:14 UTC (permalink / raw)
To: julia.lawall, dan.carpenter, davem, netdev, linux-kernel; +Cc: Bhumika Goyal
Declare net_device_ops structures as const as they are only stored in
the netdev_ops field of a net_device structure. This field is of type
const, so net_device_ops structures having same properties can be made
const too.
Done using Coccinelle:
@r1 disable optional_qualifier@
identifier i;
position p;
@@
static struct net_device_ops i@p={...};
@ok1@
identifier r1.i;
position p;
struct net_device ndev;
@@
ndev.netdev_ops=&i@p
@bad@
position p!={r1.p,ok1.p};
identifier r1.i;
@@
i@p
@depends on !bad disable optional_qualifier@
identifier r1.i;
@@
+const
struct net_device_ops i;
File size before:
text data bss dec hex filename
4821 744 0 5565 15bd ethernet/moxa/moxart_ether.o
File size after:
text data bss dec hex filename
5373 192 0 5565 15bd ethernet/moxa/moxart_ether.o
Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
---
drivers/net/ethernet/moxa/moxart_ether.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index 9774b50..6a6525f 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -436,7 +436,7 @@ static void moxart_mac_set_rx_mode(struct net_device *ndev)
spin_unlock_irq(&priv->txlock);
}
-static struct net_device_ops moxart_netdev_ops = {
+static const struct net_device_ops moxart_netdev_ops = {
.ndo_open = moxart_mac_open,
.ndo_stop = moxart_mac_stop,
.ndo_start_xmit = moxart_mac_start_xmit,
--
1.9.1
^ permalink raw reply related
* [PATCH] net: xilinx: constify net_device_ops structures
From: Bhumika Goyal @ 2017-01-21 6:08 UTC (permalink / raw)
To: julia.lawall, michal.simek, soren.brinkmann, netdev,
linux-arm-kernel, linux-kernel
Cc: Bhumika Goyal
Declare net_device_ops structures as const as they are only stored in
the netdev_ops field of a net_device structure. This field is of type
const, so net_device_ops structures having same properties can be made
const too.
Done using Coccinelle:
@r1 disable optional_qualifier@
identifier i;
position p;
@@
static struct net_device_ops i@p={...};
@ok1@
identifier r1.i;
position p;
struct net_device ndev;
@@
ndev.netdev_ops=&i@p
@bad@
position p!={r1.p,ok1.p};
identifier r1.i;
@@
i@p
@depends on !bad disable optional_qualifier@
identifier r1.i;
@@
+const
struct net_device_ops i;
File size before:
text data bss dec hex filename
6201 744 0 6945 1b21 ethernet/xilinx/xilinx_emaclite.o
File size after:
text data bss dec hex filename
6745 192 0 6937 1b19 ethernet/xilinx/xilinx_emaclite.o
Signed-off-by: Bhumika Goyal <bhumirks@gmail.com>
---
drivers/net/ethernet/xilinx/xilinx_emaclite.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 93dc10b..546f569 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -1065,7 +1065,7 @@ static bool get_bool(struct platform_device *ofdev, const char *s)
}
}
-static struct net_device_ops xemaclite_netdev_ops;
+static const struct net_device_ops xemaclite_netdev_ops;
/**
* xemaclite_of_probe - Probe method for the Emaclite device.
@@ -1219,7 +1219,7 @@ static int xemaclite_of_remove(struct platform_device *of_dev)
}
#endif
-static struct net_device_ops xemaclite_netdev_ops = {
+static const struct net_device_ops xemaclite_netdev_ops = {
.ndo_open = xemaclite_open,
.ndo_stop = xemaclite_close,
.ndo_start_xmit = xemaclite_send,
--
1.9.1
^ permalink raw reply related
* [RFC PATCH net-next 4/5] bridge: vlan lwt and dst_metadata netlink support
From: Roopa Prabhu @ 2017-01-21 5:46 UTC (permalink / raw)
To: netdev; +Cc: davem, stephen, nikolay, tgraf, hannes, jbenc, pshelar, dsa, hadi
In-Reply-To: <1484977616-1541-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
This patch adds support to attach per vlan tunnel info dst
metadata. This enables bridge driver to map vlan to tunnel_info
at ingress and egress
The initial use case is vlan to vni bridging, but the api is generic
to extend to any tunnel_info in the future:
- Uapi to configure/unconfigure/dump per vlan tunnel data
- netlink functions to configure vlan and tunnel_info mapping
- Introduces bridge port flag BR_LWT_VLAN to enable attach/detach
dst_metadata to bridged packets on ports.
Use case:
example use for this is a vxlan bridging gateway or vtep
which maps vlans to vn-segments (or vnis). User can configure
per-vlan tunnel information which the bridge driver can use
to bridge vlan into the corresponding tunnel.
CC: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
CC'ing Nikolay for some more eyes as he has been trying to keep the
bridge driver fast path lite.
include/linux/if_bridge.h | 1 +
net/bridge/br_input.c | 1 +
net/bridge/br_netlink.c | 410 ++++++++++++++++++++++++++++++++++++++-------
net/bridge/br_private.h | 18 ++
net/bridge/br_vlan.c | 138 ++++++++++++++-
5 files changed, 507 insertions(+), 61 deletions(-)
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index c6587c0..36ff611 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -46,6 +46,7 @@ struct br_ip_list {
#define BR_LEARNING_SYNC BIT(9)
#define BR_PROXYARP_WIFI BIT(10)
#define BR_MCAST_FLOOD BIT(11)
+#define BR_LWT_VLAN BIT(12)
#define BR_DEFAULT_AGEING_TIME (300 * HZ)
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 855b72f..83f356f 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -20,6 +20,7 @@
#include <net/arp.h>
#include <linux/export.h>
#include <linux/rculist.h>
+#include <net/dst_metadata.h>
#include "br_private.h"
/* Hook for brouter */
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 71c7453..df997ad 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -17,17 +17,30 @@
#include <net/net_namespace.h>
#include <net/sock.h>
#include <uapi/linux/if_bridge.h>
+#include <net/dst_metadata.h>
#include "br_private.h"
#include "br_private_stp.h"
-static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg,
- u32 filter_mask)
+static size_t br_get_vlan_tinfo_size(void)
{
+ return nla_total_size(0) + /* nest IFLA_BRIDGE_VLAN_TUNNEL_INFO */
+ nla_total_size(sizeof(u32)) + /* IFLA_BRIDGE_VLAN_TUNNEL_ID */
+ nla_total_size(sizeof(u16)) + /* IFLA_BRIDGE_VLAN_TUNNEL_VID */
+ nla_total_size(sizeof(u16)); /* IFLA_BRIDGE_VLAN_TUNNEL_FLAGS */
+}
+
+static int __get_num_vlan_infos(struct net_bridge_port *p,
+ struct net_bridge_vlan_group *vg,
+ u32 filter_mask, int *num_vtinfos)
+{
+ struct net_bridge_vlan *vbegin = NULL, *vend = NULL;
+ struct net_bridge_vlan *vtbegin = NULL, *vtend = NULL;
struct net_bridge_vlan *v;
- u16 vid_range_start = 0, vid_range_end = 0, vid_range_flags = 0;
+ bool get_tinfos = (p && p->flags & BR_LWT_VLAN) ? true: false;
+ bool vcontinue, vtcontinue;
+ int num_vinfos = 0;
u16 flags, pvid;
- int num_vlans = 0;
if (!(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED))
return 0;
@@ -36,6 +49,8 @@ static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg,
/* Count number of vlan infos */
list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
flags = 0;
+ vcontinue = false;
+ vtcontinue = false;
/* only a context, bridge vlan not activated */
if (!br_vlan_should_use(v))
continue;
@@ -45,47 +60,79 @@ static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg,
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)
flags |= BRIDGE_VLAN_INFO_UNTAGGED;
- if (vid_range_start == 0) {
- goto initvars;
- } else if ((v->vid - vid_range_end) == 1 &&
- flags == vid_range_flags) {
- vid_range_end = v->vid;
+ if (!vbegin) {
+ vbegin = v;
+ vend = v;
+ vcontinue = true;
+ } else if ((v->vid - vend->vid) == 1 &&
+ flags == vbegin->flags) {
+ vend = v;
+ vcontinue = true;
+ }
+
+ if (!vcontinue) {
+ if ((vend->vid - vbegin->vid) > 0)
+ num_vinfos += 2;
+ else
+ num_vinfos += 1;
+ }
+
+ if (!get_tinfos && !v->tinfo.tunnel_id)
continue;
- } else {
- if ((vid_range_end - vid_range_start) > 0)
- num_vlans += 2;
+
+ if (!vtbegin) {
+ vtbegin = v;
+ vtend = v;
+ vtcontinue = true;
+ } else if ((v->vid - vtend->vid) == 1 &&
+ vlan_tunnel_id_isrange(vtend, v)) {
+ vtend = v;
+ vtcontinue = true;
+ }
+
+ if (!vtcontinue) {
+ if ((vtend->vid - vtbegin->vid) > 0)
+ num_vtinfos += 2;
else
- num_vlans += 1;
+ num_vtinfos += 1;
+ vbegin = NULL;
+ vend = NULL;
}
-initvars:
- vid_range_start = v->vid;
- vid_range_end = v->vid;
- vid_range_flags = flags;
}
- if (vid_range_start != 0) {
- if ((vid_range_end - vid_range_start) > 0)
- num_vlans += 2;
+ if (vbegin) {
+ if ((vend->vid - vbegin->vid) > 0)
+ num_vinfos += 2;
else
- num_vlans += 1;
+ num_vinfos += 1;
}
- return num_vlans;
+ if (get_tinfos && vtbegin && vtbegin->tinfo.tunnel_id) {
+ if ((vtend->vid - vtbegin->vid) > 0)
+ *num_vtinfos += 2;
+ else
+ *num_vtinfos += 1;
+ }
+
+ return num_vinfos;
}
-static int br_get_num_vlan_infos(struct net_bridge_vlan_group *vg,
- u32 filter_mask)
+static int br_get_num_vlan_infos(struct net_bridge_port *p,
+ struct net_bridge_vlan_group *vg,
+ int *num_tinfos, u32 filter_mask)
{
int num_vlans;
if (!vg)
return 0;
- if (filter_mask & RTEXT_FILTER_BRVLAN)
+ if (filter_mask & RTEXT_FILTER_BRVLAN) {
+ *num_tinfos = vg->num_vlans;
return vg->num_vlans;
+ }
rcu_read_lock();
- num_vlans = __get_num_vlan_infos(vg, filter_mask);
+ num_vlans = __get_num_vlan_infos(p, vg, filter_mask, num_tinfos);
rcu_read_unlock();
return num_vlans;
@@ -95,9 +142,10 @@ static size_t br_get_link_af_size_filtered(const struct net_device *dev,
u32 filter_mask)
{
struct net_bridge_vlan_group *vg = NULL;
- struct net_bridge_port *p;
+ struct net_bridge_port *p = NULL;
struct net_bridge *br;
- int num_vlan_infos;
+ int num_vlan_infos, num_vlan_tinfos = 0;
+ size_t retsize = 0;
rcu_read_lock();
if (br_port_exists(dev)) {
@@ -107,11 +155,15 @@ static size_t br_get_link_af_size_filtered(const struct net_device *dev,
br = netdev_priv(dev);
vg = br_vlan_group_rcu(br);
}
- num_vlan_infos = br_get_num_vlan_infos(vg, filter_mask);
+ num_vlan_infos = br_get_num_vlan_infos(p, vg, &num_vlan_tinfos,
+ filter_mask);
rcu_read_unlock();
/* Each VLAN is returned in bridge_vlan_info along with flags */
- return num_vlan_infos * nla_total_size(sizeof(struct bridge_vlan_info));
+ retsize = num_vlan_infos * nla_total_size(sizeof(struct bridge_vlan_info)) +
+ num_vlan_tinfos * br_get_vlan_tinfo_size();
+
+ return retsize;
}
static inline size_t br_port_info_size(void)
@@ -191,7 +243,8 @@ static int br_port_fill_attrs(struct sk_buff *skb,
nla_put_u16(skb, IFLA_BRPORT_NO, p->port_no) ||
nla_put_u8(skb, IFLA_BRPORT_TOPOLOGY_CHANGE_ACK,
p->topology_change_ack) ||
- nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending))
+ nla_put_u8(skb, IFLA_BRPORT_CONFIG_PENDING, p->config_pending) ||
+ nla_put_u8(skb, IFLA_BRPORT_LWT_VLAN, !!(p->flags & BR_LWT_VLAN)))
return -EMSGSIZE;
timerval = br_timer_value(&p->message_age_timer);
@@ -216,6 +269,34 @@ static int br_port_fill_attrs(struct sk_buff *skb,
return 0;
}
+static int br_fill_vlan_tinfo(struct sk_buff *skb, u16 vid,
+ __be64 tunnel_id, u16 flags)
+{
+ __be32 tid = tunnel_id_to_key32(tunnel_id);
+ struct nlattr *tmap;
+
+ tmap = nla_nest_start(skb, IFLA_BRIDGE_VLAN_TUNNEL_INFO);
+ if (!tmap)
+ return -EMSGSIZE;
+ if (nla_put_u32(skb, IFLA_BRIDGE_VLAN_TUNNEL_ID,
+ be32_to_cpu(tid)))
+ goto nla_put_failure;
+ if (nla_put_u16(skb, IFLA_BRIDGE_VLAN_TUNNEL_VID,
+ vid))
+ goto nla_put_failure;
+ if (nla_put_u16(skb, IFLA_BRIDGE_VLAN_TUNNEL_FLAGS,
+ flags))
+ goto nla_put_failure;
+ nla_nest_end(skb, tmap);
+
+ return 0;
+
+nla_put_failure:
+ nla_nest_cancel(skb, tmap);
+
+ return -EMSGSIZE;
+}
+
static int br_fill_ifvlaninfo_range(struct sk_buff *skb, u16 vid_start,
u16 vid_end, u16 flags)
{
@@ -249,20 +330,24 @@ static int br_fill_ifvlaninfo_range(struct sk_buff *skb, u16 vid_start,
}
static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb,
+ struct net_bridge_port *p,
struct net_bridge_vlan_group *vg)
{
+ struct net_bridge_vlan *vbegin = NULL, *vend = NULL;
+ struct net_bridge_vlan *vtbegin = NULL, *vtend = NULL;
+ bool fill_tinfos = (p && p->flags & BR_LWT_VLAN) ? true: false;
struct net_bridge_vlan *v;
- u16 vid_range_start = 0, vid_range_end = 0, vid_range_flags = 0;
+ bool vcontinue, vtcontinue;
u16 flags, pvid;
- int err = 0;
+ int err;
- /* Pack IFLA_BRIDGE_VLAN_INFO's for every vlan
- * and mark vlan info with begin and end flags
- * if vlaninfo represents a range
- */
pvid = br_get_pvid(vg);
+ /* Count number of vlan infos */
list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
flags = 0;
+ vcontinue = false;
+ vtcontinue = false;
+ /* only a context, bridge vlan not activated */
if (!br_vlan_should_use(v))
continue;
if (v->vid == pvid)
@@ -271,44 +356,103 @@ static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb,
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)
flags |= BRIDGE_VLAN_INFO_UNTAGGED;
- if (vid_range_start == 0) {
- goto initvars;
- } else if ((v->vid - vid_range_end) == 1 &&
- flags == vid_range_flags) {
- vid_range_end = v->vid;
- continue;
- } else {
- err = br_fill_ifvlaninfo_range(skb, vid_range_start,
- vid_range_end,
- vid_range_flags);
+ if (!vbegin) {
+ vbegin = v;
+ vend = v;
+ vcontinue = true;
+ } else if ((v->vid - vend->vid) == 1 &&
+ flags == vbegin->flags) {
+ vend = v;
+ vcontinue = true;
+ }
+
+ if (!vcontinue) {
+ err = br_fill_ifvlaninfo_range(skb,
+ vbegin->vid,
+ vend->vid,
+ vbegin->flags);
if (err)
return err;
+ vbegin = vend = NULL;
+ }
+
+ if (!fill_tinfos || !v->tinfo.tunnel_id)
+ continue;
+
+ if (!vtbegin) {
+ vtbegin = v;
+ vtend = v;
+ vtcontinue = true;
+ } else if ((v->vid - vtend->vid) == 1 &&
+ vlan_tunnel_id_isrange(vtend, v)) {
+ vtend = v;
+ vtcontinue = true;
}
-initvars:
- vid_range_start = v->vid;
- vid_range_end = v->vid;
- vid_range_flags = flags;
+ if (!vtcontinue && vtbegin->tinfo.tunnel_id) {
+ if ((vtend->vid - vtbegin->vid) > 0) {
+ err = br_fill_vlan_tinfo(skb, vbegin->vid,
+ vbegin->tinfo.tunnel_id,
+ BRIDGE_VLAN_INFO_RANGE_BEGIN);
+ if (err)
+ return err;
+ err = br_fill_vlan_tinfo(skb, vend->vid,
+ vend->tinfo.tunnel_id,
+ BRIDGE_VLAN_INFO_RANGE_END);
+ if (err)
+ return err;
+ } else {
+ err = br_fill_vlan_tinfo(skb, vbegin->vid,
+ vbegin->tinfo.tunnel_id,
+ 0);
+ if (err)
+ return err;
+ }
+ vbegin = NULL;
+ vend = NULL;
+ }
}
- if (vid_range_start != 0) {
- /* Call it once more to send any left over vlans */
- err = br_fill_ifvlaninfo_range(skb, vid_range_start,
- vid_range_end,
- vid_range_flags);
+ if (vbegin) {
+ err = br_fill_ifvlaninfo_range(skb, vbegin->vid,
+ vend->vid,
+ vbegin->flags);
if (err)
return err;
}
+ if (fill_tinfos && vtbegin && vtbegin->tinfo.tunnel_id) {
+ if ((vtend->vid - vtbegin->vid) > 0) {
+ err = br_fill_vlan_tinfo(skb, vbegin->vid,
+ vbegin->tinfo.tunnel_id,
+ BRIDGE_VLAN_INFO_RANGE_BEGIN);
+ if (err)
+ return err;
+ err = br_fill_vlan_tinfo(skb, vend->vid,
+ vend->tinfo.tunnel_id,
+ BRIDGE_VLAN_INFO_RANGE_END);
+ if (err)
+ return err;
+ } else {
+ err = br_fill_vlan_tinfo(skb, vbegin->vid,
+ vbegin->tinfo.tunnel_id, 0);
+ if (err)
+ return err;
+ }
+ }
+
return 0;
}
static int br_fill_ifvlaninfo(struct sk_buff *skb,
+ struct net_bridge_port *p,
struct net_bridge_vlan_group *vg)
{
struct bridge_vlan_info vinfo;
struct net_bridge_vlan *v;
+ bool fill_tinfos = (p && p->flags & BR_LWT_VLAN) ? true : false;
u16 pvid;
+ int err;
pvid = br_get_pvid(vg);
list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
@@ -326,6 +470,14 @@ static int br_fill_ifvlaninfo(struct sk_buff *skb,
if (nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
sizeof(vinfo), &vinfo))
goto nla_put_failure;
+
+ if (!fill_tinfos || !v->tinfo.tunnel_id)
+ continue;
+
+ err = br_fill_vlan_tinfo(skb, v->vid,
+ v->tinfo.tunnel_id, 0);
+ if (err)
+ return err;
}
return 0;
@@ -411,9 +563,9 @@ static int br_fill_ifinfo(struct sk_buff *skb,
goto nla_put_failure;
}
if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)
- err = br_fill_ifvlaninfo_compressed(skb, vg);
+ err = br_fill_ifvlaninfo_compressed(skb, port, vg);
else
- err = br_fill_ifvlaninfo(skb, vg);
+ err = br_fill_ifvlaninfo(skb, port, vg);
rcu_read_unlock();
if (err)
goto nla_put_failure;
@@ -514,6 +666,127 @@ static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p,
return err;
}
+static const struct nla_policy vlan_tunnel_policy[IFLA_BRIDGE_VLAN_TUNNEL_MAX + 1] = {
+ [IFLA_BRIDGE_VLAN_TUNNEL_ID]= { .type = NLA_U32 },
+ [IFLA_BRIDGE_VLAN_TUNNEL_VID] = { .type = NLA_U16 },
+ [IFLA_BRIDGE_VLAN_TUNNEL_FLAGS] = { .type = NLA_U16 },
+};
+
+static int br_add_vlan_tunnel_info(struct net_bridge *br,
+ struct net_bridge_port *p, int cmd,
+ u16 vid, u32 tun_id)
+{
+ int err;
+
+ switch (cmd) {
+ case RTM_SETLINK:
+ if (p) {
+ /* if the MASTER flag is set this will act on the global
+ * per-VLAN entry as well
+ */
+ err = nbp_vlan_tunnel_info_add(p, vid, tun_id);
+ if (err)
+ break;
+ } else {
+ return -EINVAL;
+ }
+
+ break;
+
+ case RTM_DELLINK:
+ if (p)
+ nbp_vlan_tunnel_info_delete(p, vid);
+ else
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+struct vtunnel_info {
+ u32 tunid;
+ u16 vid;
+ u16 flags;
+};
+
+static int br_parse_vlan_tunnel_info(struct nlattr *attr,
+ struct vtunnel_info *tinfo)
+{
+ struct nlattr *tb[IFLA_BRIDGE_VLAN_TUNNEL_MAX + 1];
+ u32 tun_id;
+ u16 vid, flags;
+ int err;
+
+ err = nla_parse_nested(tb, IFLA_BRIDGE_VLAN_TUNNEL_MAX,
+ attr, vlan_tunnel_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[IFLA_BRIDGE_VLAN_TUNNEL_ID])
+ tun_id = nla_get_u32(tb[IFLA_BRIDGE_VLAN_TUNNEL_ID]);
+ else
+ return -EINVAL;
+
+ if (tb[IFLA_BRIDGE_VLAN_TUNNEL_VID]) {
+ vid = nla_get_u16(tb[IFLA_BRIDGE_VLAN_TUNNEL_VID]);
+ if (vid >= VLAN_VID_MASK)
+ return -ERANGE;
+ } else {
+ return -EINVAL;
+ }
+
+ if (tb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS])
+ flags = nla_get_u16(tb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS]);
+
+ tinfo->tunid = tun_id;
+ tinfo->vid = vid;
+ tinfo->flags = flags;
+
+ return 0;
+}
+
+static int br_process_vlan_tunnel_info(struct net_bridge *br,
+ struct net_bridge_port *p, int cmd,
+ struct vtunnel_info *tinfo_curr,
+ struct vtunnel_info *tinfo_last)
+{
+ int t, v;
+ int err;
+
+ if (tinfo_curr->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
+ if (tinfo_last->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN)
+ return -EINVAL;
+ memcpy(tinfo_last, tinfo_curr, sizeof(struct vtunnel_info));
+ } else if (tinfo_curr->flags & BRIDGE_VLAN_INFO_RANGE_END) {
+ if (!(tinfo_last->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN))
+ return -EINVAL;
+ if ((tinfo_curr->vid - tinfo_last->vid) !=
+ (tinfo_curr->tunid - tinfo_last->tunid))
+ return -EINVAL;
+ /* XXX: tun id and vlan id attrs must be same
+ */
+ t = tinfo_last->tunid;
+ for (v = tinfo_last->vid; v <= tinfo_curr->vid; v++) {
+ err = br_add_vlan_tunnel_info(br, p, cmd,
+ v, t);
+ if (err)
+ return err;
+ t++;
+ }
+ memset(tinfo_last, 0, sizeof(struct vtunnel_info));
+ memset(tinfo_curr, 0, sizeof(struct vtunnel_info));
+ } else {
+ err = br_add_vlan_tunnel_info(br, p, cmd,
+ tinfo_curr->vid,
+ tinfo_curr->tunid);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
static int br_afspec(struct net_bridge *br,
struct net_bridge_port *p,
struct nlattr *af_spec,
@@ -522,10 +795,30 @@ static int br_afspec(struct net_bridge *br,
struct bridge_vlan_info *vinfo_start = NULL;
struct bridge_vlan_info *vinfo = NULL;
struct nlattr *attr;
+ struct vtunnel_info tinfo_last = {
+ .tunid = 0,
+ .vid = 0,
+ .flags = 0};
+ struct vtunnel_info tinfo_curr = {
+ .tunid = 0,
+ .vid = 0,
+ .flags = 0};
int err = 0;
int rem;
nla_for_each_nested(attr, af_spec, rem) {
+ if (nla_type(attr) == IFLA_BRIDGE_VLAN_TUNNEL_INFO) {
+ err = br_parse_vlan_tunnel_info(attr, &tinfo_curr);
+ if (err)
+ return err;
+ err = br_process_vlan_tunnel_info(br, p, cmd,
+ &tinfo_curr,
+ &tinfo_last);
+ if (err)
+ return err;
+ continue;
+ }
+
if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
continue;
if (nla_len(attr) != sizeof(struct bridge_vlan_info))
@@ -638,6 +931,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
br_set_port_flag(p, tb, IFLA_BRPORT_MCAST_FLOOD, BR_MCAST_FLOOD);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP, BR_PROXYARP);
br_set_port_flag(p, tb, IFLA_BRPORT_PROXYARP_WIFI, BR_PROXYARP_WIFI);
+ br_set_port_flag(p, tb, IFLA_BRPORT_LWT_VLAN, BR_LWT_VLAN);
if (tb[IFLA_BRPORT_COST]) {
err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 8ce621e..f68e360 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -91,6 +91,11 @@ struct br_vlan_stats {
struct u64_stats_sync syncp;
};
+struct br_tunnel_info {
+ __be64 tunnel_id;
+ struct metadata_dst *tunnel_dst;
+};
+
/**
* struct net_bridge_vlan - per-vlan entry
*
@@ -113,6 +118,7 @@ struct br_vlan_stats {
*/
struct net_bridge_vlan {
struct rhash_head vnode;
+ struct rhash_head tnode;
u16 vid;
u16 flags;
struct br_vlan_stats __percpu *stats;
@@ -124,6 +130,9 @@ struct net_bridge_vlan {
atomic_t refcnt;
struct net_bridge_vlan *brvlan;
};
+
+ struct br_tunnel_info tinfo;
+
struct list_head vlist;
struct rcu_head rcu;
@@ -145,6 +154,7 @@ struct net_bridge_vlan {
*/
struct net_bridge_vlan_group {
struct rhashtable vlan_hash;
+ struct rhashtable tunnel_hash;
struct list_head vlan_list;
u16 num_vlans;
u16 pvid;
@@ -786,6 +796,14 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask);
void br_vlan_get_stats(const struct net_bridge_vlan *v,
struct br_vlan_stats *stats);
+int __vlan_tunnel_info_add(struct net_bridge_vlan_group *vg,
+ struct net_bridge_vlan *vlan, u32 tun_id);
+int __vlan_tunnel_info_del(struct net_bridge_vlan_group *vg,
+ struct net_bridge_vlan *vlan);
+int nbp_vlan_tunnel_info_delete(struct net_bridge_port *port, u16 vid);
+int nbp_vlan_tunnel_info_add(struct net_bridge_port *port, u16 vid, u32 tun_id);
+bool vlan_tunnel_id_isrange(struct net_bridge_vlan *v_end,
+ struct net_bridge_vlan *v);
static inline struct net_bridge_vlan_group *br_vlan_group(
const struct net_bridge *br)
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index b6de4f4..2040f08 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -3,6 +3,7 @@
#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include <net/switchdev.h>
+#include <net/dst_metadata.h>
#include "br_private.h"
@@ -31,6 +32,31 @@ static struct net_bridge_vlan *br_vlan_lookup(struct rhashtable *tbl, u16 vid)
return rhashtable_lookup_fast(tbl, &vid, br_vlan_rht_params);
}
+static inline int br_vlan_tunid_cmp(struct rhashtable_compare_arg *arg,
+ const void *ptr)
+{
+ const struct net_bridge_vlan *vle = ptr;
+ __be64 tunid = *(__be64 *)arg->key;
+
+ return vle->tinfo.tunnel_id != tunid;
+}
+
+static const struct rhashtable_params br_vlan_tunnel_rht_params = {
+ .head_offset = offsetof(struct net_bridge_vlan, tnode),
+ .key_offset = offsetof(struct net_bridge_vlan, tinfo.tunnel_id),
+ .key_len = sizeof(__be64),
+ .nelem_hint = 3,
+ .locks_mul = 1,
+ .obj_cmpfn = br_vlan_tunid_cmp,
+ .automatic_shrinking = true,
+};
+
+static struct net_bridge_vlan *br_vlan_tunnel_lookup(struct rhashtable *tbl,
+ u64 tunnel_id)
+{
+ return rhashtable_lookup_fast(tbl, &tunnel_id, br_vlan_tunnel_rht_params);
+}
+
static void __vlan_add_pvid(struct net_bridge_vlan_group *vg, u16 vid)
{
if (vg->pvid == vid)
@@ -325,6 +351,7 @@ static void __vlan_group_free(struct net_bridge_vlan_group *vg)
{
WARN_ON(!list_empty(&vg->vlan_list));
rhashtable_destroy(&vg->vlan_hash);
+ rhashtable_destroy(&vg->tunnel_hash);
kfree(vg);
}
@@ -613,6 +640,8 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
br_fdb_find_delete_local(br, NULL, br->dev->dev_addr, vid);
br_fdb_delete_by_port(br, NULL, vid, 0);
+ __vlan_tunnel_info_del(vg, v);
+
return __vlan_del(v);
}
@@ -918,6 +947,9 @@ int br_vlan_init(struct net_bridge *br)
ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params);
if (ret)
goto err_rhtbl;
+ ret = rhashtable_init(&vg->tunnel_hash, &br_vlan_tunnel_rht_params);
+ if (ret)
+ goto err_rhtbl2;
INIT_LIST_HEAD(&vg->vlan_list);
br->vlan_proto = htons(ETH_P_8021Q);
br->default_pvid = 1;
@@ -932,6 +964,8 @@ int br_vlan_init(struct net_bridge *br)
return ret;
err_vlan_add:
+ rhashtable_destroy(&vg->tunnel_hash);
+err_rhtbl2:
rhashtable_destroy(&vg->vlan_hash);
err_rhtbl:
kfree(vg);
@@ -960,7 +994,10 @@ int nbp_vlan_init(struct net_bridge_port *p)
ret = rhashtable_init(&vg->vlan_hash, &br_vlan_rht_params);
if (ret)
- goto err_rhtbl;
+ goto err_rhtbl1;
+ ret = rhashtable_init(&vg->tunnel_hash, &br_vlan_tunnel_rht_params);
+ if (ret)
+ goto err_rhtbl2;
INIT_LIST_HEAD(&vg->vlan_list);
rcu_assign_pointer(p->vlgrp, vg);
if (p->br->default_pvid) {
@@ -976,9 +1013,11 @@ int nbp_vlan_init(struct net_bridge_port *p)
err_vlan_add:
RCU_INIT_POINTER(p->vlgrp, NULL);
synchronize_rcu();
- rhashtable_destroy(&vg->vlan_hash);
+ rhashtable_destroy(&vg->tunnel_hash);
err_vlan_enabled:
-err_rhtbl:
+err_rhtbl2:
+ rhashtable_destroy(&vg->vlan_hash);
+err_rhtbl1:
kfree(vg);
goto out;
@@ -1081,3 +1120,96 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v,
stats->tx_packets += txpackets;
}
}
+
+bool vlan_tunnel_id_isrange(struct net_bridge_vlan *v_end,
+ struct net_bridge_vlan *v)
+{
+ /* XXX: check other tunnel attributes */
+ return (be32_to_cpu(tunnel_id_to_key32(v_end->tinfo.tunnel_id)) -
+ be32_to_cpu(tunnel_id_to_key32(v->tinfo.tunnel_id)) == 1);
+}
+
+int __vlan_tunnel_info_add(struct net_bridge_vlan_group *vg,
+ struct net_bridge_vlan *vlan, u32 tun_id)
+{
+ struct metadata_dst *metadata = NULL;
+ __be64 key = key32_to_tunnel_id(cpu_to_be32(tun_id));
+ int err;
+
+ if (vlan->tinfo.tunnel_dst)
+ return -EEXIST;
+
+ metadata = __ip_tun_set_dst(0, 0, 0, 0, 0, TUNNEL_KEY,
+ key, 0);
+ if (!metadata)
+ return -EINVAL;
+
+ metadata->u.tun_info.mode |= IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_BRIDGE;
+ vlan->tinfo.tunnel_dst = metadata;
+ vlan->tinfo.tunnel_id = key;
+
+ err = rhashtable_lookup_insert_fast(&vg->tunnel_hash, &vlan->tnode,
+ br_vlan_tunnel_rht_params);
+ if (err)
+ goto out;
+
+ return 0;
+out:
+ dst_release(&vlan->tinfo.tunnel_dst->dst);
+
+ return err;
+}
+
+int __vlan_tunnel_info_del(struct net_bridge_vlan_group *vg,
+ struct net_bridge_vlan *vlan)
+{
+ if (vlan->tinfo.tunnel_dst) {
+ vlan->tinfo.tunnel_id = 0;
+ dst_release(&vlan->tinfo.tunnel_dst->dst);
+
+ rhashtable_remove_fast(&vg->tunnel_hash, &vlan->vnode,
+ br_vlan_tunnel_rht_params);
+ }
+
+ return 0;
+}
+
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
+int nbp_vlan_tunnel_info_add(struct net_bridge_port *port, u16 vid, u32 tun_id)
+{
+ struct net_bridge_vlan_group *vg;
+ struct net_bridge_vlan *vlan;
+
+ ASSERT_RTNL();
+
+ vg = nbp_vlan_group(port);
+ vlan = br_vlan_find(vg, vid);
+ if (!vlan)
+ return -EINVAL;
+
+ __vlan_tunnel_info_add(vg, vlan, tun_id);
+
+ return 0;
+}
+
+/* Must be protected by RTNL.
+ * Must be called with vid in range from 1 to 4094 inclusive.
+ */
+int nbp_vlan_tunnel_info_delete(struct net_bridge_port *port, u16 vid)
+{
+ struct net_bridge_vlan_group *vg;
+ struct net_bridge_vlan *v;
+
+ ASSERT_RTNL();
+
+ vg = nbp_vlan_group(port);
+ v = br_vlan_find(vg, vid);
+ if (!v)
+ return -ENOENT;
+
+ __vlan_tunnel_info_del(vg, v);
+
+ return 0;
+}
--
1.7.10.4
^ permalink raw reply related
* [RFC PATCH net-next 5/5] bridge: vlan lwt dst_metadata hooks in ingress and egress paths
From: Roopa Prabhu @ 2017-01-21 5:46 UTC (permalink / raw)
To: netdev; +Cc: davem, stephen, nikolay, tgraf, hannes, jbenc, pshelar, dsa, hadi
In-Reply-To: <1484977616-1541-1-git-send-email-roopa@cumulusnetworks.com>
From: Roopa Prabhu <roopa@cumulusnetworks.com>
- ingress hook:
- if port is a lwt tunnel port, use tunnel info in
attached dst_metadata to map it to a local vlan
- egress hook:
- if port is a lwt tunnel port, use tunnel info attached to
vlan to set dst_metadata on the skb
CC: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
CC'ing Nikolay for some more eyes as he has been trying to keep the
bridge driver fast path lite.
net/bridge/br_input.c | 4 ++++
net/bridge/br_private.h | 4 ++++
net/bridge/br_vlan.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+)
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 83f356f..96602a1 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -262,6 +262,10 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
return RX_HANDLER_CONSUMED;
p = br_port_get_rcu(skb->dev);
+ if (p->flags & BR_LWT_VLAN) {
+ if (br_handle_ingress_vlan_tunnel(skb, p, nbp_vlan_group_rcu(p)))
+ goto drop;
+ }
if (unlikely(is_link_local_ether_addr(dest))) {
u16 fwd_mask = p->br->group_fwd_mask_required;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index f68e360..68a23c5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -804,6 +804,10 @@ int __vlan_tunnel_info_del(struct net_bridge_vlan_group *vg,
int nbp_vlan_tunnel_info_add(struct net_bridge_port *port, u16 vid, u32 tun_id);
bool vlan_tunnel_id_isrange(struct net_bridge_vlan *v_end,
struct net_bridge_vlan *v);
+int br_handle_ingress_vlan_tunnel(struct sk_buff *skb, struct net_bridge_port *p,
+ struct net_bridge_vlan_group *vg);
+int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
+ struct net_bridge_vlan *vlan);
static inline struct net_bridge_vlan_group *br_vlan_group(
const struct net_bridge *br)
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 2040f08..6cf2344 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -405,6 +405,11 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
if (v->flags & BRIDGE_VLAN_INFO_UNTAGGED)
skb->vlan_tci = 0;
+
+ if (br_handle_egress_vlan_tunnel(skb, v)) {
+ kfree_skb(skb);
+ return NULL;
+ }
out:
return skb;
}
@@ -1213,3 +1218,53 @@ int nbp_vlan_tunnel_info_delete(struct net_bridge_port *port, u16 vid)
return 0;
}
+
+int br_handle_ingress_vlan_tunnel(struct sk_buff *skb,
+ struct net_bridge_port *p,
+ struct net_bridge_vlan_group *vg)
+{
+ struct ip_tunnel_info *tinfo = skb_tunnel_info(skb);
+ struct net_bridge_vlan *vlan;
+
+ if (!vg || !tinfo)
+ return 0;
+
+ /* if already tagged, ignore */
+ if (skb_vlan_tagged(skb))
+ return 0;
+
+ /* lookup vid, given tunnel id */
+ vlan = br_vlan_tunnel_lookup(&vg->tunnel_hash, tinfo->key.tun_id);
+ if (!vlan)
+ return 0;
+
+ skb_dst_drop(skb);
+
+ __vlan_hwaccel_put_tag(skb, p->br->vlan_proto, vlan->vid);
+
+ return 0;
+}
+
+int br_handle_egress_vlan_tunnel(struct sk_buff *skb,
+ struct net_bridge_vlan *vlan)
+{
+ __be32 tun_id;
+ int err;
+
+ if (!vlan || !vlan->tinfo.tunnel_id)
+ return 0;
+
+ if (unlikely(!skb_vlan_tag_present(skb)))
+ return 0;
+
+ skb_dst_drop(skb);
+ tun_id = tunnel_id_to_key32(vlan->tinfo.tunnel_id);
+
+ err = skb_vlan_pop(skb);
+ if (err)
+ return err;
+
+ skb_dst_set(skb, dst_clone(&vlan->tinfo.tunnel_dst->dst));
+
+ return 0;
+}
--
1.7.10.4
^ 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