diff options
author | Fernando Fernandez Mancera <ffmancera@riseup.net> | 2022-04-04 14:10:00 +0200 |
---|---|---|
committer | Fernando Fernandez Mancera <ffmancera@riseup.net> | 2022-04-04 18:19:01 +0200 |
commit | 0bad1de0b0adfcdf774160954e3ca0a8c03556a7 (patch) | |
tree | 1ca3723f200488a3f10f8c4060f9f834f96b0858 | |
parent | 721f0e75de0c4b615ffb2eddda53817f5d201665 (diff) |
ovs, dpdk: fix creating ovs-interface when the ovs-bridge is netdevff/ovs_netdev_ip
When the ovs-bridge datapath is netdev, OpenvSwitch will not create a
ovs-interface but a tun interface. The ovs-interface device must check
all the link-change signals and check if the link type is tun and the
interface name is the same than the device name. If so, the
ovs-interface device will get the ifindex of the tun device. This allow
NetworkManager to manage the interface properly, modifying MTU,
configuring IPv4/IPv6 and others.
Example:
```
55: ovsbridge-port0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 9000 qdisc fq_codel state UNKNOWN group default qlen 1000
link/ether fa:fb:07:98:e0:c6 brd ff:ff:ff:ff:ff:ff
inet 192.168.123.100/24 brd 192.168.123.255 scope global noprefixroute ovsbridge-port0
valid_lft forever preferred_lft forever
inet6 fe80::9805:55c4:4c5f:da1c/64 scope link noprefixroute
valid_lft forever preferred_lft forever
```
https://bugzilla.redhat.com/show_bug.cgi?id=2001792
-rw-r--r-- | src/core/devices/ovs/nm-device-ovs-interface.c | 82 |
1 files changed, 80 insertions, 2 deletions
diff --git a/src/core/devices/ovs/nm-device-ovs-interface.c b/src/core/devices/ovs/nm-device-ovs-interface.c index 74707d2482..73fa58fab7 100644 --- a/src/core/devices/ovs/nm-device-ovs-interface.c +++ b/src/core/devices/ovs/nm-device-ovs-interface.c @@ -13,6 +13,7 @@ #include "devices/nm-device-private.h" #include "nm-active-connection.h" #include "nm-setting-connection.h" +#include "nm-setting-ovs-bridge.h" #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-port.h" @@ -24,6 +25,7 @@ typedef struct { NMOvsdb *ovsdb; bool waiting_for_interface : 1; + GSource *link_check; } NMDeviceOvsInterfacePrivate; struct _NMDeviceOvsInterface { @@ -35,6 +37,11 @@ struct _NMDeviceOvsInterfaceClass { NMDeviceClass parent; }; +typedef struct { + NMDevice *device; + int ifindex; +} NMDeviceOvsInterfaceCheck; + G_DEFINE_TYPE(NMDeviceOvsInterface, nm_device_ovs_interface, NM_TYPE_DEVICE) #define NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self) \ @@ -199,17 +206,83 @@ ready_for_ip_config(NMDevice *device) return nm_device_get_ip_ifindex(device) > 0; } +static gboolean +_set_ip_ifindex_tun(gpointer user_data) +{ + NMDeviceOvsInterfaceCheck *cb_data = user_data; + NMDevice *device = cb_data->device; + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + + priv->waiting_for_interface = FALSE; + nm_device_set_ip_ifindex(device, cb_data->ifindex); + + nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_PENDING, NULL); + nm_device_devip_set_state(device, AF_INET6, NM_DEVICE_IP_STATE_PENDING, NULL); + nm_device_activate_schedule_stage3_ip_config(device, FALSE); + + g_free(cb_data); + + return G_SOURCE_REMOVE; +} + +static void +_netdev_tun_link_cb(NMPlatform *platform, + int obj_type_i, + int ifindex, + NMPlatformLink *pllink, + int change_type_i, + NMDevice *device) +{ + const NMPlatformSignalChangeType change_type = change_type_i; + NMDeviceOvsInterfaceCheck *cb_data = NULL; + + if (change_type == NM_PLATFORM_SIGNAL_ADDED) { + if (pllink->type == NM_LINK_TYPE_TUN + && nm_streq0(pllink->name, nm_device_get_iface(device))) { + g_signal_handlers_disconnect_by_func(platform, _netdev_tun_link_cb, device); + cb_data = g_slice_new0(NMDeviceOvsInterfaceCheck); + cb_data->device = device; + cb_data->ifindex = ifindex; + + nm_g_idle_add(_set_ip_ifindex_tun, cb_data); + } + } +} + static void act_stage3_ip_config(NMDevice *device, int addr_family) { - NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); - NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); + NMActiveConnection *controller_act = NULL; + NMSettingOvsBridge *s_ovs_bridge = NULL; + NMDeviceOvsInterface *self = NM_DEVICE_OVS_INTERFACE(device); + NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); if (!_is_internal_interface(device)) { nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, NULL); return; } + /* When the ovs-bridge controller is using netdev datapath, the interface + * link created is a tun device instead of a ovs-interface. NetworkManager must + * detect the creation of the tun link and attach the ifindex to the + * ovs-interface device. */ + controller_act = NM_ACTIVE_CONNECTION(nm_device_get_act_request(device)); + if (controller_act && nm_device_get_ip_ifindex(device) <= 0) { + controller_act = + nm_active_connection_get_master(nm_active_connection_get_master(controller_act)); + + if (controller_act) + s_ovs_bridge = nm_connection_get_setting_ovs_bridge( + nm_active_connection_get_applied_connection(controller_act)); + if (s_ovs_bridge + && nm_streq0(nm_setting_ovs_bridge_get_datapath_type(s_ovs_bridge), "netdev")) + g_signal_connect(nm_device_get_platform(device), + NM_PLATFORM_SIGNAL_LINK_CHANGED, + G_CALLBACK(_netdev_tun_link_cb), + self); + } + /* FIXME(l3cfg): we should create the IP ifindex before stage3 start. * * For now it's here because when the ovs-interface enters stage3, then it's added to the @@ -245,6 +318,8 @@ deactivate(NMDevice *device) NMDeviceOvsInterfacePrivate *priv = NM_DEVICE_OVS_INTERFACE_GET_PRIVATE(self); priv->waiting_for_interface = FALSE; + if (priv->link_check) + nm_clear_g_source_inst(&priv->link_check); } typedef struct { @@ -360,6 +435,9 @@ deactivate_async(NMDevice *device, return; } + if (priv->link_check) + nm_clear_g_source_inst(&priv->link_check); + if (priv->waiting_for_interface) { /* At this point we have issued an INSERT and a DELETE * command for the interface to ovsdb. We don't know if |