24 Commits

Author SHA1 Message Date
a960d64a87 Add the ability to skip address sync on unnumbered interfaces 2024-03-05 22:59:55 +01:00
8fc5631ef6 Run clang-format on all files. 2023-05-30 21:28:35 +02:00
ccea08b95d Ensure the string is 0-terminated 2023-02-05 11:32:48 +00:00
815a6e0dce Run VPP's checkstyle to reformat the code 2023-01-11 16:21:40 +00:00
e53d4376ab cleanup: Clean logging, consistent capitalization, nouns, and macro names 2023-01-11 16:18:18 +00:00
cdf07cce34 Merge review feedback from mgsmith on upstream gerrit 33709 ps8..10 2021-11-29 20:19:34 +00:00
45cb9b4afc Cleanup interface sync
- move tap_set_carrier() upstream to lcp_itf_set_link_state()
- refuse to set admin-up on sub-int if parent is down
- no need to switch namespaces, lcp_itf_set_link_state() already does
- in change_mtu and change_admin_state, if the interface is a sub,
  we only have to sync that one interface. Otherwise, walk the parent
  interface and all sub-ints with lcp_itf_pair_sync_state_hw() and
  make note of this in the (DBG) log
2021-09-08 20:53:02 +00:00
ba4d9d1a3c Add lcp_itf_pair_sync_state_hw() and only walk relevant int+subints, not all interfaces 2021-09-08 19:50:50 +00:00
6d2ce1cd83 Consolidate MTU and Link changes into one function. 2021-08-24 17:50:44 +02:00
2d00de080b Protect VPP -> Linux state propagation behind flag
Introduce lcp_main.lcp_sync, which determines if state changes made
to interfaces in VPP do or don't propagate into Linux.

- Add a startup.conf directive 'lcp-sync' to enable at startup time.
- Add CLI.short_help = "lcp lcp-sync [on|enable|off|disable]",
- Show the current value in "show lcp".

Gate changes in mtu, state and address on lcp_lcp_sync().

When the operator issues 'lcp lcp-sync on', it is prudent to do a
one-off sync of all interface attributes from VPP into Linux.
For this, add a lcp_itf_pair_sync_state_all() function.
2021-08-15 16:07:53 +02:00
d23aab2d95 Add CLI for lcp-auto-subint
In preparation of another feature 'netlink-auto-subint', rename
lcp_main's field to "lcp_auto_subint".

Add CLI .short_help = "lcp lcp-auto-subint [on|enable|off|disable]"

Show status of the field on "lcp show" output.
2021-08-15 14:45:04 +02:00
934446dcd9 Add automatic LCP creation
Update the pair_config() parser to follow suite.

When the configuration 'lcp-auto-subint' is set, and the interface at
hand is a subinterface, in lcp_itf_interface_add_del():

- if it's a deletion and we're a sub-int, and we have a LIP: delete it.
- if it's a creation and we're a sub-int, and our parent has a LIP, create one.

Fix a few logging consistency issues (pair_del), and in
pair_delete_by_index() ensure that the right namespace is selected.

Due to this quirk with lip->lip_namespace not wanting to be a vec_dup()
string, rewrite them all to be strdup/free instead.
2021-08-14 17:20:31 +02:00
b3d8e75706 Start LCP auto-creation
This first preparation moves lcp_itf_phy_add() to lcpng_if_sync.c
and renames it lcp_itf_interface_add_del().

It does all the pre-flight checks to validate that a new device, given
by sw_if_index, can have a LIP created:
- must be a sub-int
- must have a sw_sup_if_index, which itself has a LIP

However, I realize that I cannot create an interface from within an
interface add callback, so I'll have to schedule the child LIP to be
created by a process, after the callback returns.

I'll do that in the next commit.
2021-08-14 14:28:16 +02:00
20e282655b fixstyle 2021-08-14 11:27:06 +02:00
10f10d534c Ensure the plugin works well with namespaces
I've made a few cosmetic adjustments:
- introduce debug, info, notice, warn and err loggers
- remove redundant logging, and set correct (conservative) log levels
- turn the sync-state error into a warning

And a little debt paydown:
- refactor sync-state into its own function, to be called instead of
  all the spot fixes elsewhere. It's going to be the case that
  sync-state is "the reconsiliation function".
- Fix a bug in lip->lip_namespace copy: vec_dup() there doesn't seem
  to work for me, use strdup() instead and make a mental note to
  reviist.

The plugin now works with 'lcpng default netns dataplane' in its
startup.conf; and with 'lcp default netns dataplane' as its first
command. A few of these fixes should go upstream, too, which I'll
do next.
2021-08-14 09:40:43 +02:00
aab11196cf Sanitize some overly verbose logging ERR->{DBG,INFO} 2021-08-13 21:08:03 +02:00
72f55fd901 Netlink namespaces!
I have been very careless in using the correct network namespace when
manipulating LCP host devices. Around any/every netlink write operation,
we must first clib_setns() into the correct namespace. So, wrap every
call of vnet_netlink_*() in all places.

For consistency, use the convention 'curr_ns_fd' (for the one we are
coming from) and 'vif_ns_fd' (to signal the one that the netlink VIF
is in).

Be careful as well to enter and exit everywhere without losing file
descriptors.
2021-08-13 20:58:28 +02:00
79a395b3c9 Clamp sub-int MTU to parent's MTU
In VPP, a sub-interface can have a larger MTU than its parent.
In Linux, this cannot happen, so the following is problematic:

```
DBGvpp# create sub TenGigabitEthernet3/0/0 10
DBGvpp# set int mtu packet 1500 TenGigabitEthernet3/0/0
DBGvpp# set int mtu packet 9000 TenGigabitEthernet3/0/0.10
694: e0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UNKNOWN mode DEFAULT group default qlen 1000
695: e0.10@e0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
```

The best way to ensure this works is to clamp the sub-int to a maximum MTU
of that of its parent, and override the user request to change the VPP
sub-int to anything higher than that, perhaps logging an error explaining
why. This means two things:

1.  Any change in VPP of a child MTU to larger than its parent, should be
    reverted.
1   Any change in VPP of a parent MTU should ensure all children are clamped
    to at most that.
2021-08-13 19:59:55 +02:00
f7e1bb951d Sync IPv4 and IPv6 addresses from VPP to LCP
There are three ways in which IP addresses will want to be copied
from VPP into the companion Linux devices:

1) set interface ip address ... adds an IPv4 or IPv6 address
  - this is handled by lcp_itf_ip[46]_add_del_interface_addr() which
    is a callback installed in lcp_itf_pair_init()
2) set interface ip address del ... removes them
  - also handled by lcp_itf_ip[46]_add_del_interface_addr() but
    curiously there is no upstream vnet_netlink_del_ip[46]_addr() so
    I wrote them inline here - I will try to get them upstreamed, as
    they appear to be obvious companions in vnet/device/netlink.h
3) Upon LIP creation, it could be that there are L3 addresses already
   on the VPP interface. If so, set them with lcp_itf_set_interface_addr()

This means that now, at any time a new LIP is created, its state from
VPP is fully copied over (MTU, Link state, IPv4/IPv6 addresses)!

At runtime, new addresses can be set/removed as well.
2021-08-13 16:50:32 +02:00
39bfa1615f Add sync of VPP mtu changes into Linux interfaces
This is a straight foward copy of the VPP L3 (packet) MTU into the Linux
host interface, for any change on an interface/sub-int for which a LIP is
defined.

As with Linux itself, no care is taken to ensure that the parent interface
(e0) has a higher MTU than the child interface (e0.10).

DBGvpp# create sub TenGigabitEthernet3/0/0 10
DBGvpp# lcp create TenGigabitEthernet3/0/0 host-if e0
DBGvpp# lcp create TenGigabitEthernet3/0/0.10 host-if e0.10
602: e0: <BROADCAST,MULTICAST> mtu 9000 qdisc mq state DOWN mode DEFAULT group default qlen 1000
603: e0.10@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 9000 qdisc noop state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set interface mtu packet 9216 TenGigabitEthernet3/0/0
602: e0: <BROADCAST,MULTICAST> mtu 9216 qdisc mq state DOWN mode DEFAULT group default qlen 1000
603: e0.10@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 9000 qdisc noop state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set interface mtu packet 9050 TenGigabitEthernet3/0/0
602: e0: <BROADCAST,MULTICAST> mtu 9050 qdisc mq state DOWN mode DEFAULT group default qlen 1000
603: e0.10@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 9000 qdisc noop state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set interface mtu packet 9050 TenGigabitEthernet3/0/0.10
602: e0: <BROADCAST,MULTICAST> mtu 9050 qdisc mq state DOWN mode DEFAULT group default qlen 1000
603: e0.10@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 9050 qdisc noop state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set interface mtu packet 1500 TenGigabitEthernet3/0/0.10
602: e0: <BROADCAST,MULTICAST> mtu 9050 qdisc mq state DOWN mode DEFAULT group default qlen 1000
603: e0.10@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set interface mtu packet 1500 TenGigabitEthernet3/0/0
602: e0: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000
603: e0.10@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
2021-08-13 15:02:31 +02:00
d8c988273e fixstyle, now with upstream .clang-* files 2021-08-13 14:37:12 +02:00
cc61e7694d fixstyle 2021-08-13 14:36:25 +02:00
a3dc56c014 Force a sync of interfaces when VPP phy changes state
When Linux changes link on a master interface, all of its children also change.
This is not true in VPP, where bringing down a phy while its sub-ints are up
will not change link on the sub-ints.

We are forced to undo that change by walking the sub-interfaces of a phy and
syncing their state back into linux.

For simplicity, just walk all interfaces, as others will be a no-op.

The approach may have to be revisited once netlink messages are
consumed, to ensure there is not an oscillation where netlink sets a
link, which forces all links to be reset, generating more netlink
messages, etc. Care should be taken when netlink consumption comes into
play!

DBGvpp# create sub TenGigabitEthernet3/0/0 1
DBGvpp# lcp create TenGigabitEthernet3/0/0 host-if e0
DBGvpp# lcp create TenGigabitEthernet3/0/0.1 host-if e0.1
593: e0: <BROADCAST,MULTICAST> mtu 9000 qdisc mq state DOWN mode DEFAULT group default qlen 1000
594: e0.1@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 9000 qdisc noop state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set int state TenGigabitEthernet3/0/0  up
593: e0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UNKNOWN mode DEFAULT group default qlen 1000
594: e0.1@e0: <BROADCAST,MULTICAST> mtu 9000 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set int state TenGigabitEthernet3/0/0.1 up
593: e0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UNKNOWN mode DEFAULT group default qlen 1000
594: e0.1@e0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc noqueue state UP mode DEFAULT group default qlen 1000

DBGvpp# set int state TenGigabitEthernet3/0/0 down
593: e0: <BROADCAST,MULTICAST> mtu 9000 qdisc mq state DOWN mode DEFAULT group default qlen 1000
594: e0.1@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 9000 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set int state TenGigabitEthernet3/0/0 up
DBGvpp# set int state TenGigabitEthernet3/0/0.1 down
593: e0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP mode DEFAULT group default qlen 1000
594: e0.1@e0: <BROADCAST,MULTICAST> mtu 9000 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000

DBGvpp# set int state TenGigabitEthernet3/0/0 down
593: e0: <BROADCAST,MULTICAST> mtu 9000 qdisc mq state DOWN mode DEFAULT group default qlen 1000
594: e0.1@e0: <BROADCAST,MULTICAST,M-DOWN> mtu 9000 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
2021-08-13 14:33:03 +02:00
7c15c84f6c Sync interface state from VPP to LCP
This is the first in a series of functions that aims to copy forward
interface changes in the VPP dataplane into the linux interfaces.

Capture link state changes (set interface state ...) and apply them
to Linux.

There's an important dissonance here:
- When Linux sets a parent interface up, all children also go up.

ip link set enp66s0f1 down
ip link add link enp66s0f1 name foo type vlan id 1234
ip link set foo down
ip link | grep enp66s0f1
9: enp66s0f1: <BROADCAST,MULTICAST> mtu 9000 qdisc mq state DOWN mode DEFAULT group default qlen 1000
61: foo@enp66s0f1: <BROADCAST,MULTICAST,M-DOWN> mtu 9000 qdisc noop state DOWN mode DEFAULT group default qlen 1000

ip link set enp66s0f1 up
ip link | grep s0f1
9: enp66s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP mode DEFAULT group default qlen 1000
61: foo@enp66s0f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc noqueue state UP mode DEFAULT group default qlen 1000

While in VPP this is not so, there each individual interface and
sub-interface stands for itself. I think the proper fix here is to walk
all sub-interfaces when a phy changes, and force a sync of those from
VPP to LCP as well. I'll do that in a followup commit so it's easier to
roll back.
2021-08-13 13:27:20 +02:00