Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next v2 1/4] net: switchdev: Prepare for deferred functions modifying objects
From: Florian Fainelli @ 2017-01-10 17:57 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, davem, vivien.didelot, andrew, marcelo.leitner
In-Reply-To: <20170110100901.GB1827@nanopsycho>

On 01/10/2017 02:09 AM, Jiri Pirko wrote:
> Mon, Jan 09, 2017 at 09:45:20PM CET, f.fainelli@gmail.com wrote:
>> In preparation for adding support for deferred dump operations, allow
>> specifying a deferred function whose signature allows read/write
>> objects.
>>
>> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
>> ---
>> net/switchdev/switchdev.c | 21 ++++++++++++++++-----
>> 1 file changed, 16 insertions(+), 5 deletions(-)
>>
>> diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
>> index 017801f9dbaa..3d70ad02c617 100644
>> --- a/net/switchdev/switchdev.c
>> +++ b/net/switchdev/switchdev.c
>> @@ -100,11 +100,14 @@ static DEFINE_SPINLOCK(deferred_lock);
>>
>> typedef void switchdev_deferred_func_t(struct net_device *dev,
>> 				       const void *data);
>> +typedef void switchdev_deferred_func_rw_t(struct net_device *dev,
>> +					  void *data);
>>
>> struct switchdev_deferred_item {
>> 	struct list_head list;
>> 	struct net_device *dev;
>> 	switchdev_deferred_func_t *func;
>> +	switchdev_deferred_func_rw_t *func_rw;
> 
> I'm missing why you need to have 2 funcs here. Why you just can't re-use
> func?

I wanted to let the existing callers be passed down a const void *data,
and not update them with void *data, since there is value in keeping
that annotated. This may be considered overkill, I don't know.
-- 
Florian

^ permalink raw reply

* Re: net/atm: warning in alloc_tx/__might_sleep
From: Cong Wang @ 2017-01-10 17:55 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: Andrey Konovalov, David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, netdev, LKML, Al Viro,
	Dmitry Vyukov, Kostya Serebryany, syzkaller
In-Reply-To: <CANn89iLxQPAt0e5Yc0yYFFQtoQwuRsdAwH9m1d4oqWQ3W=DZTQ@mail.gmail.com>

On Tue, Jan 10, 2017 at 9:40 AM, Eric Dumazet <edumazet@google.com> wrote:
> On Tue, Jan 10, 2017 at 9:35 AM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
>> On Mon, Jan 9, 2017 at 9:20 AM, Andrey Konovalov <andreyknvl@google.com> wrote:
>>
>> The fix should be straight-forward. Mind to try the attached patch?
>
>
> You forgot to remove schedule() ?
>
>   schedule();
> + wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);

Ah, of course, never even compile it... :-/

^ permalink raw reply

* Re: [PATCH net-next] net: ipv6: put autoconf routes into per-interface tables
From: Lorenzo Colitti @ 2017-01-10 17:47 UTC (permalink / raw)
  To: Andrey Jr. Melnikov; +Cc: netdev@vger.kernel.org
In-Reply-To: <un3fkd-lod.ln1@banana.localnet>

On Tue, Jan 10, 2017 at 10:21 PM, Andrey Jr. Melnikov
<temnota.am@gmail.com> wrote:
>
> > >>> I have no firsthand experience of this myself, but if the problems
> > >>> that Andrey reports above in this thread are real, then those would
> > >>> indicate that the code is not well-supported. Being unable to accept
> > >>> DAD is a pretty serious issue. Andrey, what version of the kernel did
> > >>> you see this on?
>
> Good catch. I'm running 4.8 without this patch. Current 4.10-rc works. Sorry
> for noise.

Ack. As I said before, I haven't seen this myself. Shouldn't have made
assertions without firsthand evidence.

That said, I think this patch is useful even though autoconf on VRFs
works the same way. One reason is the example I provided above: it
works even for interfaces that don't exist yet, whereas a VRF has to
be created ahead of time, which means that the interface cannot
immediately come up and receive an RA or its configuration will be
incorrect.

I also think that from a configuration perspective it's not
necessarily useful to have one VRF for every interface, but that sort
of depends on your point of view. Perhaps it's fine on a client system
to have both vrf-wlan0 and wlan0, and vrf-eth0 and eth0. That might be
confusing to users but maybe users don't really care?

More in general I think that using a VRFs is buying into a bigger set
of assumptions/restrictions than this patch does. For example, if I'm
reading ipv6_dev_get_saddr correctly, once you put an interface in a
VRF you can't really use the weak host model any more, because the
stack won't pick a source address from outside the VRF if the route
lookup returned a route in the VRF. Turning on the functionality in
patch is a more minimal change that only affects autoconf.

^ permalink raw reply

* [PATCH net v2] mlx4: Return EOPNOTSUPP instead of ENOTSUPP
From: Martin KaFai Lau @ 2017-01-10 17:41 UTC (permalink / raw)
  To: netdev; +Cc: Saeed Mahameed, Tariq Toukan, Kernel Team

In commit b45f0674b997 ("mlx4: xdp: Allow raising MTU up to one page minus eth and vlan hdrs"),
it changed EOPNOTSUPP to ENOTSUPP by mistake.  This patch fixes it.

Fixes: b45f0674b997 ("mlx4: xdp: Allow raising MTU up to one page minus eth and vlan hdrs")
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
---
 drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index edbe200ac2fa..4910d9af1933 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2277,7 +2277,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
 
 	if (priv->tx_ring_num[TX_XDP] &&
 	    !mlx4_en_check_xdp_mtu(dev, new_mtu))
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	dev->mtu = new_mtu;
 
-- 
2.5.1

^ permalink raw reply related

* Re: net/atm: warning in alloc_tx/__might_sleep
From: Eric Dumazet @ 2017-01-10 17:40 UTC (permalink / raw)
  To: Cong Wang
  Cc: Andrey Konovalov, David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, netdev, LKML, Al Viro,
	Dmitry Vyukov, Kostya Serebryany, syzkaller
In-Reply-To: <CAM_iQpWaHX_orHbFjKcjBZL67b6LUAmOfvS1SQP13VPZDo-69w@mail.gmail.com>

On Tue, Jan 10, 2017 at 9:35 AM, Cong Wang <xiyou.wangcong@gmail.com> wrote:
> On Mon, Jan 9, 2017 at 9:20 AM, Andrey Konovalov <andreyknvl@google.com> wrote:
>
> The fix should be straight-forward. Mind to try the attached patch?


You forgot to remove schedule() ?

  schedule();
+ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);

^ permalink raw reply

* Re: [PATCH net] mlx4: Return EOPNOTSUPP instead of ENOTSUPP
From: Martin KaFai Lau @ 2017-01-10 17:39 UTC (permalink / raw)
  To: Sergei Shtylyov; +Cc: netdev, Saeed Mahameed, Tariq Toukan, Kernel Team
In-Reply-To: <2e26d5f0-fed8-a2b9-392a-87da29c38758@cogentembedded.com>

On Tue, Jan 10, 2017 at 03:43:39PM +0300, Sergei Shtylyov wrote:
> Hello!
>
> On 01/10/2017 01:13 AM, Martin KaFai Lau wrote:
>
> >In commit b45f0674b997 ("mlx4: xdp: Allow raising MTU up to one page minus eth and vlan hdrs"),
> >it changed ENOTSUPP to EOPNOTSUPP by mistake.  This patch fixes it.
>
>    You mean vice versa (looking at your patch)?
Indeed. Will send v2 to correct this.

>
> >Fixes: b45f0674b997 ("mlx4: xdp: Allow raising MTU up to one page minus eth and vlan hdrs")
> >Signed-off-by: Martin KaFai Lau <kafai@fb.com>
> >---
> > drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> >diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> >index edbe200ac2fa..4910d9af1933 100644
> >--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> >+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
> >@@ -2277,7 +2277,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
> >
> > 	if (priv->tx_ring_num[TX_XDP] &&
> > 	    !mlx4_en_check_xdp_mtu(dev, new_mtu))
> >-		return -ENOTSUPP;
> >+		return -EOPNOTSUPP;
> >
> > 	dev->mtu = new_mtu;
> >
>
> MBR, Sergei
>

^ permalink raw reply

* Re: [PATCH] net: add the AF_QIPCRTR entries to family name tables
From: Suman Anna @ 2017-01-10 17:39 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, linux-kernel, Bjorn Andersson
In-Reply-To: <20170110034856.49721-1-s-anna@ti.com>

On 01/09/2017 09:48 PM, Suman Anna wrote:
> Commit bdabad3e363d ("net: Add Qualcomm IPC router") introduced a
> new address family. Update the family name tables accordingly so
> that the lockdep initialization can use the proper names for this
> family.
> 
> Cc: Courtney Cavin <courtney.cavin@sonymobile.com>

Courtney's email bounced, so this line can be removed.

regards
Suman

> Cc: Bjorn Andersson <bjorn.andersson@linaro.org>
> Signed-off-by: Suman Anna <s-anna@ti.com>
> ---
>  net/core/sock.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/net/core/sock.c b/net/core/sock.c
> index f560e0826009..4eca27dc5c94 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -222,7 +222,7 @@ static const char *const af_family_key_strings[AF_MAX+1] = {
>    "sk_lock-AF_RXRPC" , "sk_lock-AF_ISDN"     , "sk_lock-AF_PHONET"   ,
>    "sk_lock-AF_IEEE802154", "sk_lock-AF_CAIF" , "sk_lock-AF_ALG"      ,
>    "sk_lock-AF_NFC"   , "sk_lock-AF_VSOCK"    , "sk_lock-AF_KCM"      ,
> -  "sk_lock-AF_MAX"
> +  "sk_lock-AF_QIPCRTR", "sk_lock-AF_MAX"
>  };
>  static const char *const af_family_slock_key_strings[AF_MAX+1] = {
>    "slock-AF_UNSPEC", "slock-AF_UNIX"     , "slock-AF_INET"     ,
> @@ -239,7 +239,7 @@ static const char *const af_family_slock_key_strings[AF_MAX+1] = {
>    "slock-AF_RXRPC" , "slock-AF_ISDN"     , "slock-AF_PHONET"   ,
>    "slock-AF_IEEE802154", "slock-AF_CAIF" , "slock-AF_ALG"      ,
>    "slock-AF_NFC"   , "slock-AF_VSOCK"    ,"slock-AF_KCM"       ,
> -  "slock-AF_MAX"
> +  "slock-AF_QIPCRTR", "slock-AF_MAX"
>  };
>  static const char *const af_family_clock_key_strings[AF_MAX+1] = {
>    "clock-AF_UNSPEC", "clock-AF_UNIX"     , "clock-AF_INET"     ,
> @@ -256,7 +256,7 @@ static const char *const af_family_clock_key_strings[AF_MAX+1] = {
>    "clock-AF_RXRPC" , "clock-AF_ISDN"     , "clock-AF_PHONET"   ,
>    "clock-AF_IEEE802154", "clock-AF_CAIF" , "clock-AF_ALG"      ,
>    "clock-AF_NFC"   , "clock-AF_VSOCK"    , "clock-AF_KCM"      ,
> -  "clock-AF_MAX"
> +  "clock-AF_QIPCRTR", "clock-AF_MAX"
>  };
>  
>  /*
> 

^ permalink raw reply

* Re: net/atm: warning in alloc_tx/__might_sleep
From: Cong Wang @ 2017-01-10 17:35 UTC (permalink / raw)
  To: Andrey Konovalov
  Cc: David S. Miller, Alexey Kuznetsov, James Morris,
	Hideaki YOSHIFUJI, Patrick McHardy, netdev, LKML, Al Viro,
	Dmitry Vyukov, Kostya Serebryany, Eric Dumazet, syzkaller
In-Reply-To: <CAAeHK+yZ16SKcmJbv2ARafGgAuX2wwQNE0HGdiFy1WgqPjxLMg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 2099 bytes --]

On Mon, Jan 9, 2017 at 9:20 AM, Andrey Konovalov <andreyknvl@google.com> wrote:
> Hi!
>
> I've got the following error report while running the syzkaller fuzzer.
>
> On commit a121103c922847ba5010819a3f250f1f7fc84ab8 (4.10-rc3).
>
> A reproducer is attached.
>
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 4114 at kernel/sched/core.c:7737 __might_sleep+0x149/0x1a0
> do not call blocking ops when !TASK_RUNNING; state=1 set at
> [<ffffffff813fcb22>] prepare_to_wait+0x182/0x530
> Modules linked in:
> CPU: 0 PID: 4114 Comm: a.out Not tainted 4.10.0-rc3+ #59
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
> Call Trace:
>  __dump_stack lib/dump_stack.c:15
>  dump_stack+0x292/0x398 lib/dump_stack.c:51
>  __warn+0x19f/0x1e0 kernel/panic.c:547
>  warn_slowpath_fmt+0xc5/0x110 kernel/panic.c:562
>  __might_sleep+0x149/0x1a0 kernel/sched/core.c:7732
>  slab_pre_alloc_hook mm/slab.h:408
>  slab_alloc_node mm/slub.c:2634
>  kmem_cache_alloc_node+0x14a/0x280 mm/slub.c:2744
>  __alloc_skb+0x10f/0x800 net/core/skbuff.c:219
>  alloc_skb ./include/linux/skbuff.h:926
>  alloc_tx net/atm/common.c:75
>  vcc_sendmsg+0x5e8/0x1010 net/atm/common.c:609
>  sock_sendmsg_nosec net/socket.c:635
>  sock_sendmsg+0xca/0x110 net/socket.c:645
>  ___sys_sendmsg+0x9d2/0xae0 net/socket.c:1985
>  __sys_sendmsg+0x138/0x320 net/socket.c:2019
>  SYSC_sendmsg net/socket.c:2030
>  SyS_sendmsg+0x2d/0x50 net/socket.c:2026
>  entry_SYSCALL_64_fastpath+0x1f/0xc2 arch/x86/entry/entry_64.S:203
> RIP: 0033:0x7fcbacfddb79
> RSP: 002b:00007ffed8b5a7b8 EFLAGS: 00000206 ORIG_RAX: 000000000000002e
> RAX: ffffffffffffffda RBX: 00007ffed8b5a950 RCX: 00007fcbacfddb79
> RDX: 000000000000c000 RSI: 0000000020002000 RDI: 0000000000000003
> RBP: 0000000000400af0 R08: 0000000000000000 R09: 0000000000000000
> R10: 0000000000000000 R11: 0000000000000206 R12: 0000000000000000
> R13: 00007ffed8b5a950 R14: 0000000000000000 R15: 0000000000000000
> ---[ end trace 9edf2da84d8112da ]---
> atm:sigd_send: bad message type 0

The fix should be straight-forward. Mind to try the attached patch?

[-- Attachment #2: atm.diff --]
[-- Type: text/plain, Size: 1418 bytes --]

diff --git a/net/atm/common.c b/net/atm/common.c
index a3ca922..b7d9661 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -571,8 +571,8 @@ int vcc_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
 
 int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
 {
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 	struct sock *sk = sock->sk;
-	DEFINE_WAIT(wait);
 	struct atm_vcc *vcc;
 	struct sk_buff *skb;
 	int eff, error;
@@ -604,7 +604,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
 	}
 
 	eff = (size+3) & ~3; /* align to word boundary */
-	prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+	add_wait_queue(sk_sleep(sk), &wait);
 	error = 0;
 	while (!(skb = alloc_tx(vcc, eff))) {
 		if (m->msg_flags & MSG_DONTWAIT) {
@@ -612,6 +612,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
 			break;
 		}
 		schedule();
+		wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
 		if (signal_pending(current)) {
 			error = -ERESTARTSYS;
 			break;
@@ -623,9 +624,8 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
 			send_sig(SIGPIPE, current, 0);
 			break;
 		}
-		prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
 	}
-	finish_wait(sk_sleep(sk), &wait);
+	remove_wait_queue(sk_sleep(sk), &wait);
 	if (error)
 		goto out;
 	skb->dev = NULL; /* for paths shared with net_device interfaces */

^ permalink raw reply related

* Re: Setting link down hangs the kernel
From: Mason @ 2017-01-10 17:29 UTC (permalink / raw)
  To: netdev
  Cc: Mans Rullgard, Thibaud Cornic, Thomas Gambier, Florian Fainelli,
	Andrew Lunn
In-Reply-To: <b478607d-cb69-0efc-5a8c-9b7a54b88d68@free.fr>

On 10/01/2017 16:28, Mason wrote:

> On 10/01/2017 15:36, Mason wrote:
> 
>> I'm using kernel v4.9 on a [new] dev board.
>> I built a small kernel + rootfs with buildroot 2016.11.1
>> eth0 is driven by drivers/net/ethernet/aurora/nb8800.c
>>
>> After booting, I just run udhcpc (busybox version)
>> Then I set the link down, and the kernel hangs.
>
> So far, I've been unable to reproduce this issue on an older
> smp8758 dev board.

And another symptom (which exists only on the new board) :

After the first "link down", udhcpc no longer works.

Also, the OS prints "link down" only when udhcpc requests "link up".

I guess I have lots of "fun" things to investigate tomorrow...
Any pointers to where I should look first?

I think some kind of "deferred worker thread" is spawned when the PHY
state machine changes state? Could there be some kind of race there?
Or is it more likely something is broken in the HW?


Welcome to Buildroot
buildroot login: root
# udhcpc && ip addr
udhcpc: started, v1.25.1
udhcpc: sending discover
udhcpc: sending discover
[   28.427174] nb8800 26000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
udhcpc: sending discover
udhcpc: sending select for 172.27.64.46
udhcpc: lease of 172.27.64.46 obtained, lease time 604800
deleting routers
adding dns 172.27.0.17
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 00:16:e8:78:2c:b3 brd ff:ff:ff:ff:ff:ff
    inet 172.27.64.46/18 brd 172.27.127.255 scope global eth0
       valid_lft forever preferred_lft forever
# ip link set dev eth0 down && sleep 10 && udhcpc -T 1 -A 3
udhcpc: started, v1.25.1
udhcpc: sending discover
[   55.040450] nb8800 26000.ethernet eth0: Link is Down
udhcpc: sending discover
udhcpc: sending discover
[   57.067154] nb8800 26000.ethernet eth0: Link is Up - 1Gbps/Full - flow control rx/tx
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
udhcpc: sending discover
^C


Regards.

^ permalink raw reply

* [PATCH] vxlan: Set flow*_dport when doing route lookups
From: Martynas Pumputis @ 2017-01-10 17:29 UTC (permalink / raw)
  To: davem; +Cc: netdev, Martynas Pumputis

Otherwise, no xfrm policy with dport being set can be matched.

Signed-off-by: Martynas Pumputis <martynas@weave.works>
---
 drivers/net/vxlan.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index bb70dd5..fcfe786 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1798,7 +1798,7 @@ static int vxlan_build_skb(struct sk_buff *skb, struct dst_entry *dst,
 static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct net_device *dev,
 				      struct vxlan_sock *sock4,
 				      struct sk_buff *skb, int oif, u8 tos,
-				      __be32 daddr, __be32 *saddr,
+				      __be32 daddr, __be32 *saddr, __be16 dport,
 				      struct dst_cache *dst_cache,
 				      const struct ip_tunnel_info *info)
 {
@@ -1824,6 +1824,7 @@ static struct rtable *vxlan_get_route(struct vxlan_dev *vxlan, struct net_device
 	fl4.flowi4_proto = IPPROTO_UDP;
 	fl4.daddr = daddr;
 	fl4.saddr = *saddr;
+	fl4.fl4_dport = dport;
 
 	rt = ip_route_output_key(vxlan->net, &fl4);
 	if (likely(!IS_ERR(rt))) {
@@ -1851,6 +1852,7 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
 					  __be32 label,
 					  const struct in6_addr *daddr,
 					  struct in6_addr *saddr,
+					  __be16 dport,
 					  struct dst_cache *dst_cache,
 					  const struct ip_tunnel_info *info)
 {
@@ -1877,6 +1879,7 @@ static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
 	fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tos), label);
 	fl6.flowi6_mark = skb->mark;
 	fl6.flowi6_proto = IPPROTO_UDP;
+	fl6.fl6_dport = dport;
 
 	err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
 					 sock6->sock->sk,
@@ -2068,6 +2071,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 				     rdst ? rdst->remote_ifindex : 0, tos,
 				     dst->sin.sin_addr.s_addr,
 				     &src->sin.sin_addr.s_addr,
+				     dst_port,
 				     dst_cache, info);
 		if (IS_ERR(rt)) {
 			err = PTR_ERR(rt);
@@ -2104,6 +2108,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 					rdst ? rdst->remote_ifindex : 0, tos,
 					label, &dst->sin6.sin6_addr,
 					&src->sin6.sin6_addr,
+					dst_port,
 					dst_cache, info);
 		if (IS_ERR(ndst)) {
 			err = PTR_ERR(ndst);
@@ -2430,7 +2435,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 
 		rt = vxlan_get_route(vxlan, dev, sock4, skb, 0, info->key.tos,
 				     info->key.u.ipv4.dst,
-				     &info->key.u.ipv4.src, NULL, info);
+				     &info->key.u.ipv4.src, dport, NULL, info);
 		if (IS_ERR(rt))
 			return PTR_ERR(rt);
 		ip_rt_put(rt);
@@ -2441,7 +2446,7 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
 
 		ndst = vxlan6_get_route(vxlan, dev, sock6, skb, 0, info->key.tos,
 					info->key.label, &info->key.u.ipv6.dst,
-					&info->key.u.ipv6.src, NULL, info);
+					&info->key.u.ipv6.src, dport, NULL, info);
 		if (IS_ERR(ndst))
 			return PTR_ERR(ndst);
 		dst_release(ndst);
-- 
2.10.2

^ permalink raw reply related

* Re: [PATCH iproute2 3/3] iproute: add support for SR-IPv6 lwtunnel encapsulation
From: Tom Herbert @ 2017-01-10 17:26 UTC (permalink / raw)
  To: David Lebrun; +Cc: Linux Kernel Network Developers
In-Reply-To: <1484066486-22152-4-git-send-email-david.lebrun@uclouvain.be>

On Tue, Jan 10, 2017 at 8:41 AM, David Lebrun <david.lebrun@uclouvain.be> wrote:
> This patch adds support for SEG6 encapsulation type
> ("ip route add ... encap seg6 ...").
>
> Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
> ---
>  ip/iproute.c          |   6 +-
>  ip/iproute_lwtunnel.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 164 insertions(+), 2 deletions(-)
>
> diff --git a/ip/iproute.c b/ip/iproute.c
> index e433de8..a102e33 100644
> --- a/ip/iproute.c
> +++ b/ip/iproute.c
> @@ -98,8 +98,10 @@ static void usage(void)
>         fprintf(stderr, "TIME := NUMBER[s|ms]\n");
>         fprintf(stderr, "BOOL := [1|0]\n");
>         fprintf(stderr, "FEATURES := ecn\n");
> -       fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 ]\n");
> -       fprintf(stderr, "ENCAPHDR := [ MPLSLABEL ]\n");
> +       fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 | seg6 ]\n");
> +       fprintf(stderr, "ENCAPHDR := [ MPLSLABEL | SEG6HDR ]\n");
> +       fprintf(stderr, "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n");
> +       fprintf(stderr, "SEGMODE := [ encap | inline ]\n");
>         exit(-1);
>  }
>
> diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
> index 1a92cec..3ee6dcc 100644
> --- a/ip/iproute_lwtunnel.c
> +++ b/ip/iproute_lwtunnel.c
> @@ -26,6 +26,10 @@
>  #include "iproute_lwtunnel.h"
>  #include "bpf_util.h"
>
> +#include <linux/seg6.h>
> +#include <linux/seg6_iptunnel.h>
> +#include <linux/seg6_hmac.h>
> +
>  static const char *format_encap_type(int type)
>  {
>         switch (type) {
> @@ -39,6 +43,8 @@ static const char *format_encap_type(int type)
>                 return "ila";
>         case LWTUNNEL_ENCAP_BPF:
>                 return "bpf";
> +       case LWTUNNEL_ENCAP_SEG6:
> +               return "seg6";
>         default:
>                 return "unknown";
>         }
> @@ -69,12 +75,51 @@ static int read_encap_type(const char *name)
>                 return LWTUNNEL_ENCAP_ILA;
>         else if (strcmp(name, "bpf") == 0)
>                 return LWTUNNEL_ENCAP_BPF;
> +       else if (strcmp(name, "seg6") == 0)
> +               return LWTUNNEL_ENCAP_SEG6;
>         else if (strcmp(name, "help") == 0)
>                 encap_type_usage();
>
>         return LWTUNNEL_ENCAP_NONE;
>  }
>
> +static void print_encap_seg6(FILE *fp, struct rtattr *encap)
> +{
> +       struct rtattr *tb[SEG6_IPTUNNEL_MAX+1];
> +       struct seg6_iptunnel_encap *tuninfo;
> +       struct ipv6_sr_hdr *srh;
> +       int i;
> +
> +       parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap);
> +
> +       if (!tb[SEG6_IPTUNNEL_SRH])
> +       return;
> +
> +       tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
> +       fprintf(fp, "mode %s ",
> +               (tuninfo->mode == SEG6_IPTUN_MODE_ENCAP) ? "encap" : "inline");
> +
> +       srh = tuninfo->srh;
> +
> +       fprintf(fp, "segs %d [ ", srh->first_segment + 1);
> +
> +       for (i = srh->first_segment; i >= 0; i--)
> +               fprintf(fp, "%s ",
> +                       rt_addr_n2a(AF_INET6, 16, &srh->segments[i]));
> +
> +       fprintf(fp, "] ");
> +
> +       if (sr_has_cleanup(srh))
> +
> +       if (sr_has_hmac(srh)) {
> +               unsigned int offset = ((srh->hdrlen + 1) << 3) - 40;
> +               struct sr6_tlv_hmac *tlv;
> +
> +               tlv = (struct sr6_tlv_hmac *)((char *)srh + offset);
> +               fprintf(fp, "hmac 0x%X ", ntohl(tlv->hmackeyid));
> +       }
> +}
> +
>  static void print_encap_mpls(FILE *fp, struct rtattr *encap)
>  {
>         struct rtattr *tb[MPLS_IPTUNNEL_MAX+1];
> @@ -238,9 +283,121 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
>         case LWTUNNEL_ENCAP_BPF:
>                 print_encap_bpf(fp, encap);
>                 break;
> +       case LWTUNNEL_ENCAP_SEG6:
> +               print_encap_seg6(fp, encap);
> +               break;
>         }
>  }
>
> +static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
> +                           char ***argvp)
> +{
> +       int mode_ok = 0, segs_ok = 0, cleanup_ok = 0, hmac_ok = 0;
> +       struct seg6_iptunnel_encap *tuninfo;
> +       struct ipv6_sr_hdr *srh;
> +       char **argv = *argvp;
> +       char segbuf[1024];
> +       int argc = *argcp;
> +       __u8 cleanup = 0;
> +       int encap = -1;
> +       __u32 hmac = 0;
> +       int nsegs = 0;
> +       int srhlen;
> +       char *s;
> +       int i;
> +
> +       while (argc > 0) {
> +               if (strcmp(*argv, "mode") == 0) {
> +                       NEXT_ARG();
> +                       if (mode_ok++)
> +                               duparg2("mode", *argv);
> +                       if (strcmp(*argv, "encap") == 0)
> +                               encap = 1;
> +                       else if (strcmp(*argv, "inline") == 0)
> +                               encap = 0;
> +                       else
> +                               invarg("\"mode\" value is invalid\n", *argv);
> +               } else if (strcmp(*argv, "segs") == 0) {
> +                       NEXT_ARG();
> +                       if (segs_ok++)
> +                               duparg2("segs", *argv);
> +                       if (encap == -1)
> +                               invarg("\"segs\" provided before \"mode\"\n",
> +                                      *argv);
> +
> +                       strncpy(segbuf, *argv, 1024);
> +                       segbuf[1023] = 0;
> +               } else if (strcmp(*argv, "cleanup") == 0) {
> +                       if (cleanup_ok++)
> +                               duparg2("cleanup", *argv);
> +                       cleanup = 1;
> +               } else if (strcmp(*argv, "hmac") == 0) {
> +                       NEXT_ARG();
> +                       if (hmac_ok++)
> +                               duparg2("hmac", *argv);
> +                       get_u32(&hmac, *argv, 0);
> +               } else {
> +                       break;
> +               }
> +               argc--; argv++;
> +       }
> +
> +       s = segbuf;
> +       for (i = 0; *s; *s++ == ',' ? i++ : *s);
> +       nsegs = i + 1;
> +
> +       if (!encap)
> +               nsegs++;
> +
> +       srhlen = 8 + 16*nsegs;
> +
> +       if (hmac)
> +               srhlen += 40;
> +
> +       tuninfo = malloc(sizeof(*tuninfo) + srhlen);
> +       memset(tuninfo, 0, sizeof(*tuninfo) + srhlen);
> +
> +       if (encap)
> +               tuninfo->mode = SEG6_IPTUN_MODE_ENCAP;
> +       else
> +               tuninfo->mode = SEG6_IPTUN_MODE_INLINE;
> +
> +       srh = tuninfo->srh;
> +       srh->hdrlen = (srhlen >> 3) - 1;
> +       srh->type = 4;
> +       srh->segments_left = nsegs - 1;
> +       srh->first_segment = nsegs - 1;
> +
> +       if (cleanup)
> +               srh->flag_1 |= SR6_FLAG1_CLEANUP;
> +       if (hmac)
> +               srh->flag_1 |= SR6_FLAG1_HMAC;
> +
> +       i = srh->first_segment;
> +       for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) {
> +               inet_get_addr(s, NULL, &srh->segments[i]);
> +               i--;
> +       }
> +
> +       if (hmac) {
> +               struct sr6_tlv_hmac *tlv;
> +
> +               tlv = (struct sr6_tlv_hmac *)((char *)srh + srhlen - 40);
> +               tlv->tlvhdr.type = SR6_TLV_HMAC;
> +               tlv->tlvhdr.len = 38;
> +               tlv->hmackeyid = htonl(hmac);
> +       }
> +
> +       rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo,
> +                     sizeof(*tuninfo) + srhlen);
> +       free(tuninfo);
> +
> +       *argcp = argc + 1;
> +       *argvp = argv - 1;
> +
> +       return 0;
> +}
> +
>  static int parse_encap_mpls(struct rtattr *rta, size_t len,
>                             int *argcp, char ***argvp)
>  {
> @@ -573,6 +730,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
>                 if (parse_encap_bpf(rta, len, &argc, &argv) < 0)
>                         exit(-1);
>                 break;
> +       case LWTUNNEL_ENCAP_SEG6:
> +               parse_encap_seg6(rta, len, &argc, &argv);
> +               break;
>         default:
>                 fprintf(stderr, "Error: unsupported encap type\n");
>                 break;
> --
> 2.7.3
>

 Acked-by: Tom Herbert <tom@herbertland.com>

Is there a place do document all the SR functionality?

^ permalink raw reply

* Re: [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures
From: Tom Herbert @ 2017-01-10 17:25 UTC (permalink / raw)
  To: David Lebrun; +Cc: Linux Kernel Network Developers
In-Reply-To: <1484066486-22152-3-git-send-email-david.lebrun@uclouvain.be>

On Tue, Jan 10, 2017 at 8:41 AM, David Lebrun <david.lebrun@uclouvain.be> wrote:
> This patch add commands to support the tunnel source properties
> ("ip sr tunsrc") and the HMAC key -> secret, algorithm binding
> ("ip sr hmac").
>
> Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
> ---
>  ip/Makefile    |   2 +-
>  ip/ip.c        |   3 +-
>  ip/ip_common.h |   1 +
>  ip/ipseg6.c    | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 242 insertions(+), 2 deletions(-)
>  create mode 100644 ip/ipseg6.c
>
> diff --git a/ip/Makefile b/ip/Makefile
> index 1928489..678a795 100644
> --- a/ip/Makefile
> +++ b/ip/Makefile
> @@ -8,7 +8,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
>      link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
>      iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
>      iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \
> -    ipvrf.o
> +    ipvrf.o ipseg6.o
>
>  RTMONOBJ=rtmon.o
>
> diff --git a/ip/ip.c b/ip/ip.c
> index 07050b0..7c14a8e 100644
> --- a/ip/ip.c
> +++ b/ip/ip.c
> @@ -52,7 +52,7 @@ static void usage(void)
>  "where  OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n"
>  "                   tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n"
>  "                   netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n"
> -"                   vrf }\n"
> +"                   vrf | sr }\n"
>  "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
>  "                    -h[uman-readable] | -iec |\n"
>  "                    -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n"
> @@ -101,6 +101,7 @@ static const struct cmd {
>         { "netns",      do_netns },
>         { "netconf",    do_ipnetconf },
>         { "vrf",        do_ipvrf},
> +       { "sr",         do_seg6 },
>         { "help",       do_help },
>         { 0 }
>  };
> diff --git a/ip/ip_common.h b/ip/ip_common.h
> index ab6a834..13108c6 100644
> --- a/ip/ip_common.h
> +++ b/ip/ip_common.h
> @@ -59,6 +59,7 @@ int do_ipnetconf(int argc, char **argv);
>  int do_iptoken(int argc, char **argv);
>  int do_ipvrf(int argc, char **argv);
>  void vrf_reset(void);
> +int do_seg6(int argc, char **argv);
>
>  int iplink_get(unsigned int flags, char *name, __u32 filt_mask);
>
> diff --git a/ip/ipseg6.c b/ip/ipseg6.c
> new file mode 100644
> index 0000000..0d4130e
> --- /dev/null
> +++ b/ip/ipseg6.c
> @@ -0,0 +1,238 @@
> +/*
> + * seg6.c "ip sr/seg6"
> + *
> + *       This program is free software; you can redistribute it and/or
> + *       modify it under the terms of the GNU General Public License
> + *       version 2 as published by the Free Software Foundation;
> + *
> + * Author: David Lebrun <david.lebrun@uclouvain.be>
> + */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <sys/types.h>
> +#include <sys/socket.h>
> +#include <arpa/inet.h>
> +#include <sys/ioctl.h>
> +#include <linux/if.h>
> +
> +#include <linux/genetlink.h>
> +#include <linux/seg6_genl.h>
> +#include <linux/seg6_hmac.h>
> +
> +#include "utils.h"
> +#include "ip_common.h"
> +#include "libgenl.h"
> +
> +#define HMAC_KEY_PROMPT "Enter secret for HMAC key ID (blank to delete): "
> +
> +static void usage(void)
> +{
> +       fprintf(stderr, "Usage: ip sr { COMMAND | help }\n");
> +       fprintf(stderr, "          ip sr hmac show\n");
> +       fprintf(stderr, "          ip sr hmac set KEYID ALGO\n");
> +       fprintf(stderr, "          ip sr tunsrc show\n");
> +       fprintf(stderr, "          ip sr tunsrc set ADDRESS\n");
> +       fprintf(stderr, "where  ALGO := { sha1 | sha256 }\n");
> +       exit(-1);
> +}
> +
> +static struct rtnl_handle grth = { .fd = -1 };
> +static int genl_family = -1;
> +
> +#define SEG6_REQUEST(_req, _bufsiz, _cmd, _flags) \
> +       GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
> +                               SEG6_GENL_VERSION, _cmd, _flags)
> +
> +static struct {
> +       int cmd;
> +       struct in6_addr addr;
> +       __u32 keyid;
> +       char *pass;
> +       __u8 alg_id;
> +} opts;
> +
> +static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
> +                      void *arg)
> +{
> +       struct rtattr *attrs[SEG6_ATTR_MAX + 1];
> +       struct genlmsghdr *ghdr;
> +       FILE *fp = (FILE *)arg;
> +       int len = n->nlmsg_len;
> +
> +       if (n->nlmsg_type != genl_family)
> +               return -1;
> +
> +       len -= NLMSG_LENGTH(GENL_HDRLEN);
> +       if (len < 0)
> +               return -1;
> +
> +       ghdr = NLMSG_DATA(n);
> +
> +       parse_rtattr(attrs, SEG6_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
> +
> +       switch (ghdr->cmd) {
> +       case SEG6_CMD_DUMPHMAC:
> +       {
> +               char secret[64];
> +               char *algstr;
> +               __u8 slen = rta_getattr_u8(attrs[SEG6_ATTR_SECRETLEN]);
> +               __u8 alg_id = rta_getattr_u8(attrs[SEG6_ATTR_ALGID]);
> +
> +               memset(secret, 0, 64);
> +
> +               if (slen > 63) {
> +                       fprintf(stderr, "HMAC secret length %d > 63, "
> +                                       "truncated\n", slen);
> +                       slen = 63;
> +               }
> +               memcpy(secret, RTA_DATA(attrs[SEG6_ATTR_SECRET]), slen);
> +
> +               switch (alg_id) {
> +               case SEG6_HMAC_ALGO_SHA1:
> +                       algstr = "sha1";
> +                       break;
> +               case SEG6_HMAC_ALGO_SHA256:
> +                       algstr = "sha256";
> +                       break;
> +               default:
> +                       algstr = "<unknown>";
> +               }
> +
> +               fprintf(fp, "hmac %u ",
> +                       rta_getattr_u32(attrs[SEG6_ATTR_HMACKEYID]));
> +               fprintf(fp, "algo %s ", algstr);
> +               fprintf(fp, "secret \"%s\" ", secret);
> +
> +               fprintf(fp, "\n");
> +               break;
> +       }
> +       case SEG6_CMD_GET_TUNSRC:
> +       {
> +               fprintf(fp, "tunsrc addr %s\n",
> +                       rt_addr_n2a(AF_INET6, 16,
> +                                   RTA_DATA(attrs[SEG6_ATTR_DST])));
> +               break;
> +       }
> +       }
> +
> +       return 0;
> +}
> +
> +static int seg6_do_cmd(void)
> +{
> +       SEG6_REQUEST(req, 1024, opts.cmd, NLM_F_REQUEST);
> +       int repl = 0, dump = 0;
> +
> +       if (genl_family < 0) {
> +               if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) {
> +                       fprintf(stderr, "Cannot open generic netlink socket\n");
> +                       exit(1);
> +               }
> +               genl_family = genl_resolve_family(&grth, SEG6_GENL_NAME);
> +               if (genl_family < 0)
> +                       exit(1);
> +               req.n.nlmsg_type = genl_family;
> +       }
> +
> +       switch (opts.cmd) {
> +       case SEG6_CMD_SETHMAC:
> +       {
> +               addattr32(&req.n, sizeof(req), SEG6_ATTR_HMACKEYID, opts.keyid);
> +               addattr8(&req.n, sizeof(req), SEG6_ATTR_SECRETLEN,
> +                        strlen(opts.pass));
> +               addattr8(&req.n, sizeof(req), SEG6_ATTR_ALGID, opts.alg_id);
> +               if (strlen(opts.pass))
> +                       addattr_l(&req.n, sizeof(req), SEG6_ATTR_SECRET,
> +                                 opts.pass, strlen(opts.pass));
> +               break;
> +       }
> +       case SEG6_CMD_SET_TUNSRC:
> +               addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, &opts.addr,
> +                         sizeof(struct in6_addr));
> +               break;
> +       case SEG6_CMD_DUMPHMAC:
> +               dump = 1;
> +               break;
> +       case SEG6_CMD_GET_TUNSRC:
> +               repl = 1;
> +               break;
> +       }
> +
> +       if (!repl && !dump) {
> +               if (rtnl_talk(&grth, &req.n, NULL, 0) < 0)
> +                       return -1;
> +       } else if (repl) {
> +               if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0)
> +                       return -2;
> +               if (process_msg(NULL, &req.n, stdout) < 0) {
> +                       fprintf(stderr, "Error parsing reply\n");
> +                       exit(1);
> +               }
> +       } else {
> +               req.n.nlmsg_flags |= NLM_F_DUMP;
> +               req.n.nlmsg_seq = grth.dump = ++grth.seq;
> +               if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
> +                       perror("Failed to send dump request");
> +                       exit(1);
> +               }
> +
> +               if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) {
> +                       fprintf(stderr, "Dump terminated\n");
> +                       exit(1);
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +int do_seg6(int argc, char **argv)
> +{
> +       if (argc < 1 || matches(*argv, "help") == 0)
> +               usage();
> +
> +       memset(&opts, 0, sizeof(opts));
> +
> +       if (matches(*argv, "hmac") == 0) {
> +               NEXT_ARG();
> +               if (matches(*argv, "show") == 0) {
> +                       opts.cmd = SEG6_CMD_DUMPHMAC;
> +               } else if (matches(*argv, "set") == 0) {
> +                       NEXT_ARG();
> +                       if (get_u32(&opts.keyid, *argv, 0) || opts.keyid == 0)
> +                               invarg("hmac KEYID value is invalid", *argv);
> +                       NEXT_ARG();
> +                       if (strcmp(*argv, "sha1") == 0) {
> +                               opts.alg_id = SEG6_HMAC_ALGO_SHA1;
> +                       } else if (strcmp(*argv, "sha256") == 0) {
> +                               opts.alg_id = SEG6_HMAC_ALGO_SHA256;
> +                       } else {
> +                               invarg("hmac ALGO value is invalid", *argv);
> +                       }
> +                       opts.cmd = SEG6_CMD_SETHMAC;
> +                       opts.pass = getpass(HMAC_KEY_PROMPT);
> +               } else {
> +                       invarg("unknown", *argv);
> +               }
> +       } else if (matches(*argv, "tunsrc") == 0) {
> +               NEXT_ARG();
> +               if (matches(*argv, "show") == 0) {
> +                       opts.cmd = SEG6_CMD_GET_TUNSRC;
> +               } else if (matches(*argv, "set") == 0) {
> +                       NEXT_ARG();
> +                       opts.cmd = SEG6_CMD_SET_TUNSRC;
> +                       if (!inet_get_addr(*argv, NULL, &opts.addr))
> +                               invarg("tunsrc ADDRESS value is invalid",
> +                                      *argv);
> +               } else {
> +                       invarg("unknown", *argv);
> +               }
> +       } else {
> +               invarg("unknown", *argv);
> +       }
> +
> +       return seg6_do_cmd();
> +}
> --
> 2.7.3
>

 Acked-by: Tom Herbert <tom@herbertland.com>

^ permalink raw reply

* Re: [PATCH iproute2 1/3] sr: add header files for SR-IPv6
From: Tom Herbert @ 2017-01-10 17:25 UTC (permalink / raw)
  To: David Lebrun; +Cc: Linux Kernel Network Developers
In-Reply-To: <1484066486-22152-2-git-send-email-david.lebrun@uclouvain.be>

 Acked-by: Tom Herbert <tom@herbertland.com>



On Tue, Jan 10, 2017 at 8:41 AM, David Lebrun <david.lebrun@uclouvain.be> wrote:
> This patch add the necessary header files to interface with the SR-IPv6 kernel
> implementation.
>
> Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
> ---
>  include/linux/seg6.h          | 54 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/seg6_genl.h     | 32 +++++++++++++++++++++++++
>  include/linux/seg6_hmac.h     | 21 +++++++++++++++++
>  include/linux/seg6_iptunnel.h | 38 ++++++++++++++++++++++++++++++
>  4 files changed, 145 insertions(+)
>  create mode 100644 include/linux/seg6.h
>  create mode 100644 include/linux/seg6_genl.h
>  create mode 100644 include/linux/seg6_hmac.h
>  create mode 100644 include/linux/seg6_iptunnel.h
>
> diff --git a/include/linux/seg6.h b/include/linux/seg6.h
> new file mode 100644
> index 0000000..8f651bf
> --- /dev/null
> +++ b/include/linux/seg6.h
> @@ -0,0 +1,54 @@
> +/*
> + *  SR-IPv6 implementation
> + *
> + *  Author:
> + *  David Lebrun <david.lebrun@uclouvain.be>
> + *
> + *
> + *  This program is free software; you can redistribute it and/or
> + *      modify it under the terms of the GNU General Public License
> + *      as published by the Free Software Foundation; either version
> + *      2 of the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SEG6_H
> +#define _SEG6_H
> +
> +/*
> + * SRH
> + */
> +struct ipv6_sr_hdr {
> +       __u8    nexthdr;
> +       __u8    hdrlen;
> +       __u8    type;
> +       __u8    segments_left;
> +       __u8    first_segment;
> +       __u8    flag_1;
> +       __u8    flag_2;
> +       __u8    reserved;
> +
> +       struct in6_addr segments[0];
> +};
> +
> +#define SR6_FLAG1_CLEANUP      (1 << 7)
> +#define SR6_FLAG1_PROTECTED    (1 << 6)
> +#define SR6_FLAG1_OAM          (1 << 5)
> +#define SR6_FLAG1_ALERT                (1 << 4)
> +#define SR6_FLAG1_HMAC         (1 << 3)
> +
> +#define SR6_TLV_INGRESS                1
> +#define SR6_TLV_EGRESS         2
> +#define SR6_TLV_OPAQUE         3
> +#define SR6_TLV_PADDING                4
> +#define SR6_TLV_HMAC           5
> +
> +#define sr_has_cleanup(srh) ((srh)->flag_1 & SR6_FLAG1_CLEANUP)
> +#define sr_has_hmac(srh) ((srh)->flag_1 & SR6_FLAG1_HMAC)
> +
> +struct sr6_tlv {
> +       __u8 type;
> +       __u8 len;
> +       __u8 data[0];
> +};
> +
> +#endif
> diff --git a/include/linux/seg6_genl.h b/include/linux/seg6_genl.h
> new file mode 100644
> index 0000000..36fcbc8
> --- /dev/null
> +++ b/include/linux/seg6_genl.h
> @@ -0,0 +1,32 @@
> +#ifndef _SEG6_GENL_H
> +#define _SEG6_GENL_H
> +
> +#define SEG6_GENL_NAME         "SEG6"
> +#define SEG6_GENL_VERSION      0x1
> +
> +enum {
> +       SEG6_ATTR_UNSPEC,
> +       SEG6_ATTR_DST,
> +       SEG6_ATTR_DSTLEN,
> +       SEG6_ATTR_HMACKEYID,
> +       SEG6_ATTR_SECRET,
> +       SEG6_ATTR_SECRETLEN,
> +       SEG6_ATTR_ALGID,
> +       SEG6_ATTR_HMACINFO,
> +       __SEG6_ATTR_MAX,
> +};
> +
> +#define SEG6_ATTR_MAX (__SEG6_ATTR_MAX - 1)
> +
> +enum {
> +       SEG6_CMD_UNSPEC,
> +       SEG6_CMD_SETHMAC,
> +       SEG6_CMD_DUMPHMAC,
> +       SEG6_CMD_SET_TUNSRC,
> +       SEG6_CMD_GET_TUNSRC,
> +       __SEG6_CMD_MAX,
> +};
> +
> +#define SEG6_CMD_MAX (__SEG6_CMD_MAX - 1)
> +
> +#endif
> diff --git a/include/linux/seg6_hmac.h b/include/linux/seg6_hmac.h
> new file mode 100644
> index 0000000..71803d2
> --- /dev/null
> +++ b/include/linux/seg6_hmac.h
> @@ -0,0 +1,21 @@
> +#ifndef _SEG6_HMAC_H
> +#define _SEG6_HMAC_H
> +
> +#include <linux/seg6.h>
> +
> +#define SEG6_HMAC_SECRET_LEN   64
> +#define SEG6_HMAC_FIELD_LEN    32
> +
> +struct sr6_tlv_hmac {
> +       struct sr6_tlv tlvhdr;
> +       __u16 reserved;
> +       __be32 hmackeyid;
> +       __u8 hmac[SEG6_HMAC_FIELD_LEN];
> +};
> +
> +enum {
> +       SEG6_HMAC_ALGO_SHA1 = 1,
> +       SEG6_HMAC_ALGO_SHA256 = 2,
> +};
> +
> +#endif
> diff --git a/include/linux/seg6_iptunnel.h b/include/linux/seg6_iptunnel.h
> new file mode 100644
> index 0000000..0d72a58
> --- /dev/null
> +++ b/include/linux/seg6_iptunnel.h
> @@ -0,0 +1,38 @@
> +/*
> + *  SR-IPv6 implementation
> + *
> + *  Author:
> + *  David Lebrun <david.lebrun@uclouvain.be>
> + *
> + *
> + *  This program is free software; you can redistribute it and/or
> + *      modify it under the terms of the GNU General Public License
> + *      as published by the Free Software Foundation; either version
> + *      2 of the License, or (at your option) any later version.
> + */
> +
> +#ifndef _SEG6_IPTUNNEL_H
> +#define _SEG6_IPTUNNEL_H
> +
> +#include <linux/seg6.h>
> +
> +enum {
> +       SEG6_IPTUNNEL_UNSPEC,
> +       SEG6_IPTUNNEL_SRH,
> +       __SEG6_IPTUNNEL_MAX,
> +};
> +#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1)
> +
> +struct seg6_iptunnel_encap {
> +       int mode;
> +       struct ipv6_sr_hdr srh[0];
> +};
> +
> +#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3))
> +
> +enum {
> +       SEG6_IPTUN_MODE_INLINE,
> +       SEG6_IPTUN_MODE_ENCAP,
> +};
> +
> +#endif
> --
> 2.7.3
>

^ permalink raw reply

* Re: [PATCH net-next] bridge: multicast to unicast
From: Felix Fietkau @ 2017-01-10 17:23 UTC (permalink / raw)
  To: Dave Taht, Johannes Berg
  Cc: netdev@vger.kernel.org, bridge, linux-wireless,
	linux-kernel@vger.kernel.org, M. Braun, David S . Miller
In-Reply-To: <CAA93jw6+P8um7TxDCYgJ=SJfFzpskboR7njgudMb3NR4JZ34BA@mail.gmail.com>

On 2017-01-10 18:17, Dave Taht wrote:
> In the case of wifi I have 3 issues with this line of thought.
> 
> multicast in wifi has generally supposed to be unreliable. This makes
> it reliable. reliability comes at a cost -
> 
> multicast is typically set at a fixed low rate today. unicast is
> retried at different rates until it succeeds - for every station
> listening. If one station is already at the lowest rate, the total
> cost of the transmit increases, rather than decreases.
> 
> unicast gets block acks until it succeeds. Again, more delay.
> 
> I think there is something like 31 soft-retries in the ath9k driver....
If I remember correctly, hardware retries are counted here as well.

> what happens to diffserv markings here? for unicast CS1 goes into the
> BE queue, CS6, the VO queue. Do we go from one flat queue for all of
> multicast to punching it through one of the hardware queues based on
> the diffserv mark now with this patch?
> 
> I would like it if there was a way to preserve the unreliability
> (which multiple mesh protocols depend on), send stuff with QoSNoack,
> etc - or dynamically choose (based on the rates of the stations)
> between conventional multicast and unicast.
> 
> Or - better, IMHO, keep sending multicast as is but pick the best of
> the rates available to all the listening stations for it.
The advantage of the multicast-to-unicast conversion goes beyond simply
selecting a better rate - aggregation matters a lot as well, and that is
simply incompatible with normal multicast.

Some multicast streams use lots of small-ish packets, the airtime impact
of those is vastly reduced, even if the transmission has to be
duplicated for a few stations.

- Felix

^ permalink raw reply

* Re: [PATCH net-next] bridge: multicast to unicast
From: Dave Taht @ 2017-01-10 17:17 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Linus Lüssing, Stephen Hemminger, M. Braun, Felix Fietkau,
	netdev@vger.kernel.org, David S . Miller, bridge,
	linux-kernel@vger.kernel.org, linux-wireless
In-Reply-To: <1484045763.1014.0.camel@sipsolutions.net>

In the case of wifi I have 3 issues with this line of thought.

multicast in wifi has generally supposed to be unreliable. This makes
it reliable. reliability comes at a cost -

multicast is typically set at a fixed low rate today. unicast is
retried at different rates until it succeeds - for every station
listening. If one station is already at the lowest rate, the total
cost of the transmit increases, rather than decreases.

unicast gets block acks until it succeeds. Again, more delay.

I think there is something like 31 soft-retries in the ath9k driver....

what happens to diffserv markings here? for unicast CS1 goes into the
BE queue, CS6, the VO queue. Do we go from one flat queue for all of
multicast to punching it through one of the hardware queues based on
the diffserv mark now with this patch?

I would like it if there was a way to preserve the unreliability
(which multiple mesh protocols depend on), send stuff with QoSNoack,
etc - or dynamically choose (based on the rates of the stations)
between conventional multicast and unicast.

Or - better, IMHO, keep sending multicast as is but pick the best of
the rates available to all the listening stations for it.

Has anyone actually looked at the effects of this with, say, 5-10
stations at middlin to poor quality (longer distance)? using something
to measure the real effect of the multicast conversion? (uftp, mdns?)

^ permalink raw reply

* Re: using rcu_read_lock() after calling dst_neigh_lookup
From: David Miller @ 2017-01-10 17:02 UTC (permalink / raw)
  To: hadarh; +Cc: netdev, ogerlitz, idosch
In-Reply-To: <ead29087-05cc-c586-3b7e-d37c2e6f753c@mellanox.com>

From: Hadar Hen Zion <hadarh@mellanox.com>
Date: Tue, 10 Jan 2017 16:22:51 +0200

> While the documentation in neighbour.c says:
> 
>  "Neighbour entries are protected:
>    - with reference count.
>    - with rwlock neigh->lock
>    Reference count prevents destruction.
>    neigh->lock mainly serializes ll address data and its validity state."
> 
> So what is the right way to protect the neigh entry parameters? I
> couldn't find why rcu_read_lock() is helping here (dst_neigh_lookup
> already takes a reference on the neigh).

Documentation is, unfortunately, out of date.

When there is a mis-match, usually the behavior of the code in the
tree trumps whatever the documentation says.

^ permalink raw reply

* (unknown)
From: kevin.smith @ 2017-01-10 16:54 UTC (permalink / raw)
  To: netdev

unsubscribe

^ permalink raw reply

* Re: [PATCH 1/2] synopsys: remove dwc_eth_qos driver
From: David Miller @ 2017-01-10 16:58 UTC (permalink / raw)
  To: lars.persson; +Cc: Joao.Pinto, niklass, peppe.cavallaro, netdev
In-Reply-To: <C4CB449E-0540-4521-8A73-9B9EEC2DB7BF@axis.com>

From: Lars Persson <lars.persson@axis.com>
Date: Tue, 10 Jan 2017 12:12:42 +0000

> In the MAINTAINERS file remove the entry for SYNOPSYS DESIGNWARE ETHERNET QOS 4.10a driver.
> 
> Please also replace this Kconfig reference with CONFIG_DWMAC_DWC_QOS_ETH:
> arch/arm/configs/multi_v7_defconfig:CONFIG_SYNOPSYS_DWC_ETH_QOS=y
> 
> It might need a separate patch through the ARM maintainers’ tree.

Please do not quote a huge patch just to make a small comment like this.

Only quote a small, contextually relevant, part of the email you are
replying to.

Thanks.

^ permalink raw reply

* Re: [PATCH] net: netcp: correct netcp_get_stats function signature
From: David Miller @ 2017-01-10 16:52 UTC (permalink / raw)
  To: j-keerthy
  Cc: w-kwok2, m-karicheri2, netdev, linux-kernel, stephen, m-scherban
In-Reply-To: <1484047585-16733-1-git-send-email-j-keerthy@ti.com>

From: Keerthy <j-keerthy@ti.com>
Date: Tue, 10 Jan 2017 16:56:25 +0530

> @@ -1909,7 +1909,7 @@ static int netcp_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
>  	return 0;
>  }
>  
> -static struct rtnl_link_stats64 *
> +void
>  netcp_get_stats(struct net_device *ndev, struct rtnl_link_stats64 *stats)

Please do not remove the static qualifier.

^ permalink raw reply

* Re: [PATCH net 0/2] r8152: fix autosuspend issue
From: David Miller @ 2017-01-10 16:50 UTC (permalink / raw)
  To: hayeswang; +Cc: netdev, nic_swsd, linux-kernel, linux-usb
In-Reply-To: <1394712342-15778-229-Taiwan-albertk@realtek.com>

From: Hayes Wang <hayeswang@realtek.com>
Date: Tue, 10 Jan 2017 17:04:05 +0800

> Avoid rx is split into two parts when runtime suspend occurs.

Series applied and queued up for -stable.

^ permalink raw reply

* Re: [Open-FCoE] [PATCH RFC net-next 1/5] qed: Add support for hardware offloaded FCoE.
From: Arun Easi @ 2017-01-10 16:49 UTC (permalink / raw)
  To: Hannes Reinecke
  Cc: Dupuis, Chad, Martin K. Petersen, fcoe-devel, netdev,
	QLogic-Storage-Upstream, linux-scsi, Yuval Mintz
In-Reply-To: <371bc2ac-c630-0e95-29aa-3fa16fe0c764@suse.de>

Hi Hannes,

Thank you for the review. Please see my comment inline..

On Wed, 28 Dec 2016, 12:41am, Hannes Reinecke wrote:

> On 12/23/2016 08:17 PM, Dupuis, Chad wrote:
> > From: Arun Easi <arun.easi@qlogic.com>
> > 
> > This adds the backbone required for the various HW initalizations
> > which are necessary for the FCoE driver (qedf) for QLogic FastLinQ
> > 4xxxx line of adapters - FW notification, resource initializations, etc.
> > 
> > Signed-off-by: Arun Easi <arun.easi@cavium.com>
> > Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
> > ---

--8<-- snipped --

> > diff --git a/include/linux/qed/qed_fcoe_if.h b/include/linux/qed/qed_fcoe_if.h
> > new file mode 100644
> > index 0000000..bd6bcb8
> > --- /dev/null
> > +++ b/include/linux/qed/qed_fcoe_if.h
> > @@ -0,0 +1,145 @@
> > +#ifndef _QED_FCOE_IF_H
> > +#define _QED_FCOE_IF_H
> > +#include <linux/types.h>
> > +#include <linux/qed/qed_if.h>
> > +struct qed_fcoe_stats {
> > +	u64 fcoe_rx_byte_cnt;
> > +	u64 fcoe_rx_data_pkt_cnt;
> > +	u64 fcoe_rx_xfer_pkt_cnt;
> > +	u64 fcoe_rx_other_pkt_cnt;
> > +	u32 fcoe_silent_drop_pkt_cmdq_full_cnt;
> > +	u32 fcoe_silent_drop_pkt_rq_full_cnt;
> > +	u32 fcoe_silent_drop_pkt_crc_error_cnt;
> > +	u32 fcoe_silent_drop_pkt_task_invalid_cnt;
> > +	u32 fcoe_silent_drop_total_pkt_cnt;
> > +
> > +	u64 fcoe_tx_byte_cnt;
> > +	u64 fcoe_tx_data_pkt_cnt;
> > +	u64 fcoe_tx_xfer_pkt_cnt;
> > +	u64 fcoe_tx_other_pkt_cnt;
> > +};
> > +
> > +struct qed_dev_fcoe_info {
> > +	struct qed_dev_info common;
> > +
> > +	void __iomem *primary_dbq_rq_addr;
> > +	void __iomem *secondary_bdq_rq_addr;
> > +};
> > +
> > +struct qed_fcoe_params_offload {
> > +	dma_addr_t sq_pbl_addr;
> > +	dma_addr_t sq_curr_page_addr;
> > +	dma_addr_t sq_next_page_addr;
> > +
> > +	u8 src_mac[ETH_ALEN];
> > +	u8 dst_mac[ETH_ALEN];
> > +
> > +	u16 tx_max_fc_pay_len;
> > +	u16 e_d_tov_timer_val;
> > +	u16 rec_tov_timer_val;
> > +	u16 rx_max_fc_pay_len;
> > +	u16 vlan_tag;
> > +
> > +	struct fc_addr_nw s_id;
> > +	u8 max_conc_seqs_c3;
> > +	struct fc_addr_nw d_id;
> > +	u8 flags;
> > +	u8 def_q_idx;
> > +};
> > +
> > +#define MAX_TID_BLOCKS_FCOE (512)
> > +struct qed_fcoe_tid {
> > +	u32 size;		/* In bytes per task */
> > +	u32 num_tids_per_block;
> > +	u8 *blocks[MAX_TID_BLOCKS_FCOE];
> > +};
> > +
> > +struct qed_fcoe_cb_ops {
> > +	struct qed_common_cb_ops common;
> > +	 u32 (*get_login_failures)(void *cookie);
> > +};
> > +
> > +void qed_fcoe_set_pf_params(struct qed_dev *cdev,
> > +			    struct qed_fcoe_pf_params *params);
> > +
> > +/**
> > + * struct qed_fcoe_ops - qed FCoE operations.
> > + * @common:		common operations pointer
> > + * @fill_dev_info:	fills FCoE specific information
> > + *			@param cdev
> > + *			@param info
> > + *			@return 0 on sucesss, otherwise error value.
> > + * @register_ops:	register FCoE operations
> > + *			@param cdev
> > + *			@param ops - specified using qed_iscsi_cb_ops
> > + *			@param cookie - driver private
> > + * @ll2:		light L2 operations pointer
> > + * @start:		fcoe in FW
> > + *			@param cdev
> > + *			@param tasks - qed will fill information about tasks
> > + *			return 0 on success, otherwise error value.
> > + * @stop:		stops fcoe in FW
> > + *			@param cdev
> > + *			return 0 on success, otherwise error value.
> > + * @acquire_conn:	acquire a new fcoe connection
> > + *			@param cdev
> > + *			@param handle - qed will fill handle that should be
> > + *				used henceforth as identifier of the
> > + *				connection.
> > + *			@param p_doorbell - qed will fill the address of the
> > + *				doorbell.
> > + *			return 0 on sucesss, otherwise error value.
> > + * @release_conn:	release a previously acquired fcoe connection
> > + *			@param cdev
> > + *			@param handle - the connection handle.
> > + *			return 0 on success, otherwise error value.
> > + * @offload_conn:	configures an offloaded connection
> > + *			@param cdev
> > + *			@param handle - the connection handle.
> > + *			@param conn_info - the configuration to use for the
> > + *				offload.
> > + *			return 0 on success, otherwise error value.
> > + * @destroy_conn:	stops an offloaded connection
> > + *			@param cdev
> > + *			@param handle - the connection handle.
> > + *			@param terminate_params
> > + *			return 0 on success, otherwise error value.
> > + * @get_stats:		gets FCoE related statistics
> > + *			@param cdev
> > + *			@param stats - pointer to struck that would be filled
> > + *				we stats
> > + *			return 0 on success, error otherwise.
> > + */
> > +struct qed_fcoe_ops {
> > +	const struct qed_common_ops *common;
> > +
> > +	int (*fill_dev_info)(struct qed_dev *cdev,
> > +			     struct qed_dev_fcoe_info *info);
> > +
> > +	void (*register_ops)(struct qed_dev *cdev,
> > +			     struct qed_fcoe_cb_ops *ops, void *cookie);
> > +
> > +	const struct qed_ll2_ops *ll2;
> > +
> > +	int (*start)(struct qed_dev *cdev, struct qed_fcoe_tid *tasks);
> > +
> > +	int (*stop)(struct qed_dev *cdev);
> > +
> > +	int (*acquire_conn)(struct qed_dev *cdev,
> > +			    u32 *handle,
> > +			    u32 *fw_cid, void __iomem **p_doorbell);
> > +
> > +	int (*release_conn)(struct qed_dev *cdev, u32 handle);
> > +
> > +	int (*offload_conn)(struct qed_dev *cdev,
> > +			    u32 handle,
> > +			    struct qed_fcoe_params_offload *conn_info);
> > +	int (*destroy_conn)(struct qed_dev *cdev,
> > +			    u32 handle, dma_addr_t terminate_params);
> > +
> > +	int (*get_stats)(struct qed_dev *cdev, struct qed_fcoe_stats *stats);
> > +};
> > +
> I prefer to have to comments directly above the function prototypes;
> that is easier to read and requires editing in one place only; this way
> there's a higher likelyhood of both getting out of sync.
> 
> But that may be personal preference only.
> 

I too prefer the same, but when I posted the iSCSI qed part sometime ago, 
which had comment style like you said, I got a comment to follow 
kernel-doc style. So, for the FCoE series, I moved to kernel-doc style 
from the get go.

Regards,
-Arun

> > +const struct qed_fcoe_ops *qed_get_fcoe_ops(void);
> > +void qed_put_fcoe_ops(void);
> > +#endif

--8<-- snipped --


^ permalink raw reply

* [PATCH iproute2 1/3] sr: add header files for SR-IPv6
From: David Lebrun @ 2017-01-10 16:41 UTC (permalink / raw)
  To: netdev; +Cc: David Lebrun
In-Reply-To: <1484066486-22152-1-git-send-email-david.lebrun@uclouvain.be>

This patch add the necessary header files to interface with the SR-IPv6 kernel
implementation.

Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
 include/linux/seg6.h          | 54 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/seg6_genl.h     | 32 +++++++++++++++++++++++++
 include/linux/seg6_hmac.h     | 21 +++++++++++++++++
 include/linux/seg6_iptunnel.h | 38 ++++++++++++++++++++++++++++++
 4 files changed, 145 insertions(+)
 create mode 100644 include/linux/seg6.h
 create mode 100644 include/linux/seg6_genl.h
 create mode 100644 include/linux/seg6_hmac.h
 create mode 100644 include/linux/seg6_iptunnel.h

diff --git a/include/linux/seg6.h b/include/linux/seg6.h
new file mode 100644
index 0000000..8f651bf
--- /dev/null
+++ b/include/linux/seg6.h
@@ -0,0 +1,54 @@
+/*
+ *  SR-IPv6 implementation
+ *
+ *  Author:
+ *  David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _SEG6_H
+#define _SEG6_H
+
+/*
+ * SRH
+ */
+struct ipv6_sr_hdr {
+	__u8	nexthdr;
+	__u8	hdrlen;
+	__u8	type;
+	__u8	segments_left;
+	__u8	first_segment;
+	__u8	flag_1;
+	__u8	flag_2;
+	__u8	reserved;
+
+	struct in6_addr segments[0];
+};
+
+#define SR6_FLAG1_CLEANUP	(1 << 7)
+#define SR6_FLAG1_PROTECTED	(1 << 6)
+#define SR6_FLAG1_OAM		(1 << 5)
+#define SR6_FLAG1_ALERT		(1 << 4)
+#define SR6_FLAG1_HMAC		(1 << 3)
+
+#define SR6_TLV_INGRESS		1
+#define SR6_TLV_EGRESS		2
+#define SR6_TLV_OPAQUE		3
+#define SR6_TLV_PADDING		4
+#define SR6_TLV_HMAC		5
+
+#define sr_has_cleanup(srh) ((srh)->flag_1 & SR6_FLAG1_CLEANUP)
+#define sr_has_hmac(srh) ((srh)->flag_1 & SR6_FLAG1_HMAC)
+
+struct sr6_tlv {
+	__u8 type;
+	__u8 len;
+	__u8 data[0];
+};
+
+#endif
diff --git a/include/linux/seg6_genl.h b/include/linux/seg6_genl.h
new file mode 100644
index 0000000..36fcbc8
--- /dev/null
+++ b/include/linux/seg6_genl.h
@@ -0,0 +1,32 @@
+#ifndef _SEG6_GENL_H
+#define _SEG6_GENL_H
+
+#define SEG6_GENL_NAME		"SEG6"
+#define SEG6_GENL_VERSION	0x1
+
+enum {
+	SEG6_ATTR_UNSPEC,
+	SEG6_ATTR_DST,
+	SEG6_ATTR_DSTLEN,
+	SEG6_ATTR_HMACKEYID,
+	SEG6_ATTR_SECRET,
+	SEG6_ATTR_SECRETLEN,
+	SEG6_ATTR_ALGID,
+	SEG6_ATTR_HMACINFO,
+	__SEG6_ATTR_MAX,
+};
+
+#define SEG6_ATTR_MAX (__SEG6_ATTR_MAX - 1)
+
+enum {
+	SEG6_CMD_UNSPEC,
+	SEG6_CMD_SETHMAC,
+	SEG6_CMD_DUMPHMAC,
+	SEG6_CMD_SET_TUNSRC,
+	SEG6_CMD_GET_TUNSRC,
+	__SEG6_CMD_MAX,
+};
+
+#define SEG6_CMD_MAX (__SEG6_CMD_MAX - 1)
+
+#endif
diff --git a/include/linux/seg6_hmac.h b/include/linux/seg6_hmac.h
new file mode 100644
index 0000000..71803d2
--- /dev/null
+++ b/include/linux/seg6_hmac.h
@@ -0,0 +1,21 @@
+#ifndef _SEG6_HMAC_H
+#define _SEG6_HMAC_H
+
+#include <linux/seg6.h>
+
+#define SEG6_HMAC_SECRET_LEN	64
+#define SEG6_HMAC_FIELD_LEN	32
+
+struct sr6_tlv_hmac {
+	struct sr6_tlv tlvhdr;
+	__u16 reserved;
+	__be32 hmackeyid;
+	__u8 hmac[SEG6_HMAC_FIELD_LEN];
+};
+
+enum {
+	SEG6_HMAC_ALGO_SHA1 = 1,
+	SEG6_HMAC_ALGO_SHA256 = 2,
+};
+
+#endif
diff --git a/include/linux/seg6_iptunnel.h b/include/linux/seg6_iptunnel.h
new file mode 100644
index 0000000..0d72a58
--- /dev/null
+++ b/include/linux/seg6_iptunnel.h
@@ -0,0 +1,38 @@
+/*
+ *  SR-IPv6 implementation
+ *
+ *  Author:
+ *  David Lebrun <david.lebrun@uclouvain.be>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _SEG6_IPTUNNEL_H
+#define _SEG6_IPTUNNEL_H
+
+#include <linux/seg6.h>
+
+enum {
+	SEG6_IPTUNNEL_UNSPEC,
+	SEG6_IPTUNNEL_SRH,
+	__SEG6_IPTUNNEL_MAX,
+};
+#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1)
+
+struct seg6_iptunnel_encap {
+	int mode;
+	struct ipv6_sr_hdr srh[0];
+};
+
+#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3))
+
+enum {
+	SEG6_IPTUN_MODE_INLINE,
+	SEG6_IPTUN_MODE_ENCAP,
+};
+
+#endif
-- 
2.7.3

^ permalink raw reply related

* [PATCH iproute2 0/3] add support for IPv6 Segment Routing
From: David Lebrun @ 2017-01-10 16:41 UTC (permalink / raw)
  To: netdev; +Cc: David Lebrun

This patch series adds support for the IPv6 Segment Routing implementation in
the Linux kernel. The following features are supported.

* IPv6 SR lightweight tunnels encapsulation ("ip route add ... encap seg6 ...")
* Parsing of routes with a seg6 lwt encap ("ip route show")
* Control of internal SR structures: tunnel source ("ip sr tunsrc") and
  HMAC ("ip sr hmac"). HMAC support enables to map an HMAC Key ID to
  a pair of algorithm + secret.

Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>

David Lebrun (3):
  sr: add header files for SR-IPv6
  ip: add ip sr command to control SR-IPv6 internal structures
  iproute: add support for SR-IPv6 lwtunnel encapsulation

 include/linux/seg6.h          |  54 ++++++++++
 include/linux/seg6_genl.h     |  32 ++++++
 include/linux/seg6_hmac.h     |  21 ++++
 include/linux/seg6_iptunnel.h |  38 +++++++
 ip/Makefile                   |   2 +-
 ip/ip.c                       |   3 +-
 ip/ip_common.h                |   1 +
 ip/iproute.c                  |   6 +-
 ip/iproute_lwtunnel.c         | 160 ++++++++++++++++++++++++++++
 ip/ipseg6.c                   | 238 ++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 551 insertions(+), 4 deletions(-)
 create mode 100644 include/linux/seg6.h
 create mode 100644 include/linux/seg6_genl.h
 create mode 100644 include/linux/seg6_hmac.h
 create mode 100644 include/linux/seg6_iptunnel.h
 create mode 100644 ip/ipseg6.c

-- 
2.7.3

^ permalink raw reply

* [PATCH iproute2 3/3] iproute: add support for SR-IPv6 lwtunnel encapsulation
From: David Lebrun @ 2017-01-10 16:41 UTC (permalink / raw)
  To: netdev; +Cc: David Lebrun
In-Reply-To: <1484066486-22152-1-git-send-email-david.lebrun@uclouvain.be>

This patch adds support for SEG6 encapsulation type
("ip route add ... encap seg6 ...").

Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
 ip/iproute.c          |   6 +-
 ip/iproute_lwtunnel.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+), 2 deletions(-)

diff --git a/ip/iproute.c b/ip/iproute.c
index e433de8..a102e33 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -98,8 +98,10 @@ static void usage(void)
 	fprintf(stderr, "TIME := NUMBER[s|ms]\n");
 	fprintf(stderr, "BOOL := [1|0]\n");
 	fprintf(stderr, "FEATURES := ecn\n");
-	fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 ]\n");
-	fprintf(stderr, "ENCAPHDR := [ MPLSLABEL ]\n");
+	fprintf(stderr, "ENCAPTYPE := [ mpls | ip | ip6 | seg6 ]\n");
+	fprintf(stderr, "ENCAPHDR := [ MPLSLABEL | SEG6HDR ]\n");
+	fprintf(stderr, "SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n");
+	fprintf(stderr, "SEGMODE := [ encap | inline ]\n");
 	exit(-1);
 }
 
diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c
index 1a92cec..3ee6dcc 100644
--- a/ip/iproute_lwtunnel.c
+++ b/ip/iproute_lwtunnel.c
@@ -26,6 +26,10 @@
 #include "iproute_lwtunnel.h"
 #include "bpf_util.h"
 
+#include <linux/seg6.h>
+#include <linux/seg6_iptunnel.h>
+#include <linux/seg6_hmac.h>
+
 static const char *format_encap_type(int type)
 {
 	switch (type) {
@@ -39,6 +43,8 @@ static const char *format_encap_type(int type)
 		return "ila";
 	case LWTUNNEL_ENCAP_BPF:
 		return "bpf";
+	case LWTUNNEL_ENCAP_SEG6:
+		return "seg6";
 	default:
 		return "unknown";
 	}
@@ -69,12 +75,51 @@ static int read_encap_type(const char *name)
 		return LWTUNNEL_ENCAP_ILA;
 	else if (strcmp(name, "bpf") == 0)
 		return LWTUNNEL_ENCAP_BPF;
+	else if (strcmp(name, "seg6") == 0)
+		return LWTUNNEL_ENCAP_SEG6;
 	else if (strcmp(name, "help") == 0)
 		encap_type_usage();
 
 	return LWTUNNEL_ENCAP_NONE;
 }
 
+static void print_encap_seg6(FILE *fp, struct rtattr *encap)
+{
+	struct rtattr *tb[SEG6_IPTUNNEL_MAX+1];
+	struct seg6_iptunnel_encap *tuninfo;
+	struct ipv6_sr_hdr *srh;
+	int i;
+
+	parse_rtattr_nested(tb, SEG6_IPTUNNEL_MAX, encap);
+
+	if (!tb[SEG6_IPTUNNEL_SRH])
+	return;
+
+	tuninfo = RTA_DATA(tb[SEG6_IPTUNNEL_SRH]);
+	fprintf(fp, "mode %s ",
+		(tuninfo->mode == SEG6_IPTUN_MODE_ENCAP) ? "encap" : "inline");
+
+	srh = tuninfo->srh;
+
+	fprintf(fp, "segs %d [ ", srh->first_segment + 1);
+
+	for (i = srh->first_segment; i >= 0; i--)
+		fprintf(fp, "%s ",
+			rt_addr_n2a(AF_INET6, 16, &srh->segments[i]));
+
+	fprintf(fp, "] ");
+
+	if (sr_has_cleanup(srh))
+
+	if (sr_has_hmac(srh)) {
+		unsigned int offset = ((srh->hdrlen + 1) << 3) - 40;
+		struct sr6_tlv_hmac *tlv;
+
+		tlv = (struct sr6_tlv_hmac *)((char *)srh + offset);
+		fprintf(fp, "hmac 0x%X ", ntohl(tlv->hmackeyid));
+	}
+}
+
 static void print_encap_mpls(FILE *fp, struct rtattr *encap)
 {
 	struct rtattr *tb[MPLS_IPTUNNEL_MAX+1];
@@ -238,9 +283,121 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
 	case LWTUNNEL_ENCAP_BPF:
 		print_encap_bpf(fp, encap);
 		break;
+	case LWTUNNEL_ENCAP_SEG6:
+		print_encap_seg6(fp, encap);
+		break;
 	}
 }
 
+static int parse_encap_seg6(struct rtattr *rta, size_t len, int *argcp,
+			    char ***argvp)
+{
+	int mode_ok = 0, segs_ok = 0, cleanup_ok = 0, hmac_ok = 0;
+	struct seg6_iptunnel_encap *tuninfo;
+	struct ipv6_sr_hdr *srh;
+	char **argv = *argvp;
+	char segbuf[1024];
+	int argc = *argcp;
+	__u8 cleanup = 0;
+	int encap = -1;
+	__u32 hmac = 0;
+	int nsegs = 0;
+	int srhlen;
+	char *s;
+	int i;
+
+	while (argc > 0) {
+		if (strcmp(*argv, "mode") == 0) {
+			NEXT_ARG();
+			if (mode_ok++)
+				duparg2("mode", *argv);
+			if (strcmp(*argv, "encap") == 0)
+				encap = 1;
+			else if (strcmp(*argv, "inline") == 0)
+				encap = 0;
+			else
+				invarg("\"mode\" value is invalid\n", *argv);
+		} else if (strcmp(*argv, "segs") == 0) {
+			NEXT_ARG();
+			if (segs_ok++)
+				duparg2("segs", *argv);
+			if (encap == -1)
+				invarg("\"segs\" provided before \"mode\"\n",
+				       *argv);
+
+			strncpy(segbuf, *argv, 1024);
+			segbuf[1023] = 0;
+		} else if (strcmp(*argv, "cleanup") == 0) {
+			if (cleanup_ok++)
+				duparg2("cleanup", *argv);
+			cleanup = 1;
+		} else if (strcmp(*argv, "hmac") == 0) {
+			NEXT_ARG();
+			if (hmac_ok++)
+				duparg2("hmac", *argv);
+			get_u32(&hmac, *argv, 0);
+		} else {
+			break;
+		}
+		argc--; argv++;
+	}
+
+	s = segbuf;
+	for (i = 0; *s; *s++ == ',' ? i++ : *s);
+	nsegs = i + 1;
+
+	if (!encap)
+		nsegs++;
+
+	srhlen = 8 + 16*nsegs;
+
+	if (hmac)
+		srhlen += 40;
+
+	tuninfo = malloc(sizeof(*tuninfo) + srhlen);
+	memset(tuninfo, 0, sizeof(*tuninfo) + srhlen);
+
+	if (encap)
+		tuninfo->mode = SEG6_IPTUN_MODE_ENCAP;
+	else
+		tuninfo->mode = SEG6_IPTUN_MODE_INLINE;
+
+	srh = tuninfo->srh;
+	srh->hdrlen = (srhlen >> 3) - 1;
+	srh->type = 4;
+	srh->segments_left = nsegs - 1;
+	srh->first_segment = nsegs - 1;
+
+	if (cleanup)
+		srh->flag_1 |= SR6_FLAG1_CLEANUP;
+	if (hmac)
+		srh->flag_1 |= SR6_FLAG1_HMAC;
+
+	i = srh->first_segment;
+	for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) {
+		inet_get_addr(s, NULL, &srh->segments[i]);
+		i--;
+	}
+
+	if (hmac) {
+		struct sr6_tlv_hmac *tlv;
+
+		tlv = (struct sr6_tlv_hmac *)((char *)srh + srhlen - 40);
+		tlv->tlvhdr.type = SR6_TLV_HMAC;
+		tlv->tlvhdr.len = 38;
+		tlv->hmackeyid = htonl(hmac);
+	}
+
+	rta_addattr_l(rta, len, SEG6_IPTUNNEL_SRH, tuninfo,
+		      sizeof(*tuninfo) + srhlen);
+	free(tuninfo);
+
+	*argcp = argc + 1;
+	*argvp = argv - 1;
+
+	return 0;
+}
+
 static int parse_encap_mpls(struct rtattr *rta, size_t len,
 			    int *argcp, char ***argvp)
 {
@@ -573,6 +730,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp)
 		if (parse_encap_bpf(rta, len, &argc, &argv) < 0)
 			exit(-1);
 		break;
+	case LWTUNNEL_ENCAP_SEG6:
+		parse_encap_seg6(rta, len, &argc, &argv);
+		break;
 	default:
 		fprintf(stderr, "Error: unsupported encap type\n");
 		break;
-- 
2.7.3

^ permalink raw reply related

* [PATCH iproute2 2/3] ip: add ip sr command to control SR-IPv6 internal structures
From: David Lebrun @ 2017-01-10 16:41 UTC (permalink / raw)
  To: netdev; +Cc: David Lebrun
In-Reply-To: <1484066486-22152-1-git-send-email-david.lebrun@uclouvain.be>

This patch add commands to support the tunnel source properties
("ip sr tunsrc") and the HMAC key -> secret, algorithm binding
("ip sr hmac").

Signed-off-by: David Lebrun <david.lebrun@uclouvain.be>
---
 ip/Makefile    |   2 +-
 ip/ip.c        |   3 +-
 ip/ip_common.h |   1 +
 ip/ipseg6.c    | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 242 insertions(+), 2 deletions(-)
 create mode 100644 ip/ipseg6.c

diff --git a/ip/Makefile b/ip/Makefile
index 1928489..678a795 100644
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -8,7 +8,7 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
     link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \
     iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \
     iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \
-    ipvrf.o
+    ipvrf.o ipseg6.o
 
 RTMONOBJ=rtmon.o
 
diff --git a/ip/ip.c b/ip/ip.c
index 07050b0..7c14a8e 100644
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -52,7 +52,7 @@ static void usage(void)
 "where  OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n"
 "                   tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n"
 "                   netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n"
-"                   vrf }\n"
+"                   vrf | sr }\n"
 "       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
 "                    -h[uman-readable] | -iec |\n"
 "                    -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |\n"
@@ -101,6 +101,7 @@ static const struct cmd {
 	{ "netns",	do_netns },
 	{ "netconf",	do_ipnetconf },
 	{ "vrf",	do_ipvrf},
+	{ "sr",		do_seg6 },
 	{ "help",	do_help },
 	{ 0 }
 };
diff --git a/ip/ip_common.h b/ip/ip_common.h
index ab6a834..13108c6 100644
--- a/ip/ip_common.h
+++ b/ip/ip_common.h
@@ -59,6 +59,7 @@ int do_ipnetconf(int argc, char **argv);
 int do_iptoken(int argc, char **argv);
 int do_ipvrf(int argc, char **argv);
 void vrf_reset(void);
+int do_seg6(int argc, char **argv);
 
 int iplink_get(unsigned int flags, char *name, __u32 filt_mask);
 
diff --git a/ip/ipseg6.c b/ip/ipseg6.c
new file mode 100644
index 0000000..0d4130e
--- /dev/null
+++ b/ip/ipseg6.c
@@ -0,0 +1,238 @@
+/*
+ * seg6.c "ip sr/seg6"
+ *
+ *	  This program is free software; you can redistribute it and/or
+ *	  modify it under the terms of the GNU General Public License
+ *	  version 2 as published by the Free Software Foundation;
+ *
+ * Author: David Lebrun <david.lebrun@uclouvain.be>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <linux/if.h>
+
+#include <linux/genetlink.h>
+#include <linux/seg6_genl.h>
+#include <linux/seg6_hmac.h>
+
+#include "utils.h"
+#include "ip_common.h"
+#include "libgenl.h"
+
+#define HMAC_KEY_PROMPT "Enter secret for HMAC key ID (blank to delete): "
+
+static void usage(void)
+{
+	fprintf(stderr, "Usage: ip sr { COMMAND | help }\n");
+	fprintf(stderr, "	   ip sr hmac show\n");
+	fprintf(stderr, "	   ip sr hmac set KEYID ALGO\n");
+	fprintf(stderr, "	   ip sr tunsrc show\n");
+	fprintf(stderr, "	   ip sr tunsrc set ADDRESS\n");
+	fprintf(stderr, "where  ALGO := { sha1 | sha256 }\n");
+	exit(-1);
+}
+
+static struct rtnl_handle grth = { .fd = -1 };
+static int genl_family = -1;
+
+#define SEG6_REQUEST(_req, _bufsiz, _cmd, _flags) \
+	GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
+				SEG6_GENL_VERSION, _cmd, _flags)
+
+static struct {
+	int cmd;
+	struct in6_addr addr;
+	__u32 keyid;
+	char *pass;
+	__u8 alg_id;
+} opts;
+
+static int process_msg(const struct sockaddr_nl *who, struct nlmsghdr *n,
+		       void *arg)
+{
+	struct rtattr *attrs[SEG6_ATTR_MAX + 1];
+	struct genlmsghdr *ghdr;
+	FILE *fp = (FILE *)arg;
+	int len = n->nlmsg_len;
+
+	if (n->nlmsg_type != genl_family)
+		return -1;
+
+	len -= NLMSG_LENGTH(GENL_HDRLEN);
+	if (len < 0)
+		return -1;
+
+	ghdr = NLMSG_DATA(n);
+
+	parse_rtattr(attrs, SEG6_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
+
+	switch (ghdr->cmd) {
+	case SEG6_CMD_DUMPHMAC:
+	{
+		char secret[64];
+		char *algstr;
+		__u8 slen = rta_getattr_u8(attrs[SEG6_ATTR_SECRETLEN]);
+		__u8 alg_id = rta_getattr_u8(attrs[SEG6_ATTR_ALGID]);
+
+		memset(secret, 0, 64);
+
+		if (slen > 63) {
+			fprintf(stderr, "HMAC secret length %d > 63, "
+					"truncated\n", slen);
+			slen = 63;
+		}
+		memcpy(secret, RTA_DATA(attrs[SEG6_ATTR_SECRET]), slen);
+
+		switch (alg_id) {
+		case SEG6_HMAC_ALGO_SHA1:
+			algstr = "sha1";
+			break;
+		case SEG6_HMAC_ALGO_SHA256:
+			algstr = "sha256";
+			break;
+		default:
+			algstr = "<unknown>";
+		}
+
+		fprintf(fp, "hmac %u ",
+			rta_getattr_u32(attrs[SEG6_ATTR_HMACKEYID]));
+		fprintf(fp, "algo %s ", algstr);
+		fprintf(fp, "secret \"%s\" ", secret);
+
+		fprintf(fp, "\n");
+		break;
+	}
+	case SEG6_CMD_GET_TUNSRC:
+	{
+		fprintf(fp, "tunsrc addr %s\n",
+			rt_addr_n2a(AF_INET6, 16,
+				    RTA_DATA(attrs[SEG6_ATTR_DST])));
+		break;
+	}
+	}
+
+	return 0;
+}
+
+static int seg6_do_cmd(void)
+{
+	SEG6_REQUEST(req, 1024, opts.cmd, NLM_F_REQUEST);
+	int repl = 0, dump = 0;
+
+	if (genl_family < 0) {
+		if (rtnl_open_byproto(&grth, 0, NETLINK_GENERIC) < 0) {
+			fprintf(stderr, "Cannot open generic netlink socket\n");
+			exit(1);
+		}
+		genl_family = genl_resolve_family(&grth, SEG6_GENL_NAME);
+		if (genl_family < 0)
+			exit(1);
+		req.n.nlmsg_type = genl_family;
+	}
+
+	switch (opts.cmd) {
+	case SEG6_CMD_SETHMAC:
+	{
+		addattr32(&req.n, sizeof(req), SEG6_ATTR_HMACKEYID, opts.keyid);
+		addattr8(&req.n, sizeof(req), SEG6_ATTR_SECRETLEN,
+			 strlen(opts.pass));
+		addattr8(&req.n, sizeof(req), SEG6_ATTR_ALGID, opts.alg_id);
+		if (strlen(opts.pass))
+			addattr_l(&req.n, sizeof(req), SEG6_ATTR_SECRET,
+				  opts.pass, strlen(opts.pass));
+		break;
+	}
+	case SEG6_CMD_SET_TUNSRC:
+		addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, &opts.addr,
+			  sizeof(struct in6_addr));
+		break;
+	case SEG6_CMD_DUMPHMAC:
+		dump = 1;
+		break;
+	case SEG6_CMD_GET_TUNSRC:
+		repl = 1;
+		break;
+	}
+
+	if (!repl && !dump) {
+		if (rtnl_talk(&grth, &req.n, NULL, 0) < 0)
+			return -1;
+	} else if (repl) {
+		if (rtnl_talk(&grth, &req.n, &req.n, sizeof(req)) < 0)
+			return -2;
+		if (process_msg(NULL, &req.n, stdout) < 0) {
+			fprintf(stderr, "Error parsing reply\n");
+			exit(1);
+		}
+	} else {
+		req.n.nlmsg_flags |= NLM_F_DUMP;
+		req.n.nlmsg_seq = grth.dump = ++grth.seq;
+		if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
+			perror("Failed to send dump request");
+			exit(1);
+		}
+
+		if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) {
+			fprintf(stderr, "Dump terminated\n");
+			exit(1);
+		}
+	}
+
+	return 0;
+}
+
+int do_seg6(int argc, char **argv)
+{
+	if (argc < 1 || matches(*argv, "help") == 0)
+		usage();
+
+	memset(&opts, 0, sizeof(opts));
+
+	if (matches(*argv, "hmac") == 0) {
+		NEXT_ARG();
+		if (matches(*argv, "show") == 0) {
+			opts.cmd = SEG6_CMD_DUMPHMAC;
+		} else if (matches(*argv, "set") == 0) {
+			NEXT_ARG();
+			if (get_u32(&opts.keyid, *argv, 0) || opts.keyid == 0)
+				invarg("hmac KEYID value is invalid", *argv);
+			NEXT_ARG();
+			if (strcmp(*argv, "sha1") == 0) {
+				opts.alg_id = SEG6_HMAC_ALGO_SHA1;
+			} else if (strcmp(*argv, "sha256") == 0) {
+				opts.alg_id = SEG6_HMAC_ALGO_SHA256;
+			} else {
+				invarg("hmac ALGO value is invalid", *argv);
+			}
+			opts.cmd = SEG6_CMD_SETHMAC;
+			opts.pass = getpass(HMAC_KEY_PROMPT);
+		} else {
+			invarg("unknown", *argv);
+		}
+	} else if (matches(*argv, "tunsrc") == 0) {
+		NEXT_ARG();
+		if (matches(*argv, "show") == 0) {
+			opts.cmd = SEG6_CMD_GET_TUNSRC;
+		} else if (matches(*argv, "set") == 0) {
+			NEXT_ARG();
+			opts.cmd = SEG6_CMD_SET_TUNSRC;
+			if (!inet_get_addr(*argv, NULL, &opts.addr))
+				invarg("tunsrc ADDRESS value is invalid",
+				       *argv);
+		} else {
+			invarg("unknown", *argv);
+		}
+	} else {
+		invarg("unknown", *argv);
+	}
+
+	return seg6_do_cmd();
+}
-- 
2.7.3

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox