Extend neighbor-exchange-netlink with helpers to create VXLAN, bridge,
loopback and VRF devices, to enslave an interface to a master, to set
an interface MAC address and to delete an interface.  They will be used
to set up the EVPN datapath.

Signed-off-by: Alexandra Rukomoinikova <[email protected]>
---
 controller/neighbor-exchange-netlink.c | 124 ++++++++++++++++++++++++-
 controller/neighbor-exchange-netlink.h |  11 +++
 2 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/controller/neighbor-exchange-netlink.c 
b/controller/neighbor-exchange-netlink.c
index c6b21e7a2..591b2c2fc 100644
--- a/controller/neighbor-exchange-netlink.c
+++ b/controller/neighbor-exchange-netlink.c
@@ -14,8 +14,10 @@
  */
 
 #include <config.h>
+#include <errno.h>
 #include <stdbool.h>
 #include <linux/if_ether.h>
+#include <linux/if_link.h>
 #include <linux/rtnetlink.h>
 
 #include "hmapx.h"
@@ -23,6 +25,7 @@
 #include "lib/netlink-socket.h"
 #include "lib/packets.h"
 #include "openvswitch/vlog.h"
+#include "netlink-utils.h"
 
 #include "neighbor-exchange-netlink.h"
 #include "neighbor.h"
@@ -35,8 +38,6 @@
 
 VLOG_DEFINE_THIS_MODULE(neighbor_exchange_netlink);
 
-#define NETNL_REQ_BUFFER_SIZE 128
-
 /* NTF_EXT_LEARNED was introduced in Linux v3.19, define it if
  * not available. */
 #ifndef NTF_EXT_LEARNED
@@ -541,3 +542,122 @@ ne_table_parse(struct ofpbuf *buf, void *change)
     return ne_table_parse__(buf, NLMSG_HDRLEN + sizeof *nd,
                             nlmsg, nd, change);
 }
+
+int32_t
+ne_nl_ifindex_get(const char *ifname)
+{
+    return nl_ifindex_get(ifname);
+}
+
+int
+ne_nl_create_bridge(const char *ifname)
+{
+    return nl_create_device(ifname, "bridge");
+}
+
+int
+ne_nl_create_lo(const char *ifname)
+{
+    return nl_create_device(ifname, "dummy");
+}
+
+int
+ne_nl_create_vxlan(const char *ifname, uint32_t vni,
+                   const struct in6_addr *local_ip, uint16_t dst_port,
+                   int32_t link_ifindex)
+{
+    int err = 0;
+    struct ifinfomsg *ifinfo;
+    struct ofpbuf request;
+    ofpbuf_init(&request, 0);
+
+    nl_msg_put_nlmsghdr(&request, 0, RTM_NEWLINK,
+                        NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL);
+    ifinfo = ofpbuf_put_zeros(&request, sizeof *ifinfo);
+    nl_msg_put_string(&request, IFLA_IFNAME, ifname);
+
+    ifinfo->ifi_change = ifinfo->ifi_flags = IFF_UP;
+    size_t linkinfo_off = nl_msg_start_nested(&request, IFLA_LINKINFO);
+    nl_msg_put_string(&request, IFLA_INFO_KIND, "vxlan");
+    size_t infodata_off = nl_msg_start_nested(&request, IFLA_INFO_DATA);
+
+    nl_msg_put_u32(&request, IFLA_VXLAN_ID, vni);
+    nl_msg_put_u32(&request, IFLA_VXLAN_LINK, link_ifindex);
+    nl_msg_put_u8(&request, IFLA_VXLAN_LEARNING, 0);
+    nl_msg_put_be16(&request, IFLA_VXLAN_PORT, htons(dst_port));
+
+    if (IN6_IS_ADDR_V4MAPPED(local_ip)) {
+        ovs_be32 ipv4 = in6_addr_get_mapped_ipv4(local_ip);
+        nl_msg_put_be32(&request, IFLA_VXLAN_LOCAL, ipv4);
+    } else {
+        nl_msg_put_in6_addr(&request, IFLA_VXLAN_LOCAL6, local_ip);
+    }
+
+    nl_msg_end_nested(&request, infodata_off);
+    nl_msg_end_nested(&request, linkinfo_off);
+
+    err = nl_transact(NETLINK_ROUTE, &request, NULL);
+    ofpbuf_uninit(&request);
+    return err;
+}
+
+int
+ne_nl_set_master(const char *slave, const char *master)
+{
+    int err = 0;
+    int32_t master_idx = nl_ifindex_get(master);
+    if (!master_idx) {
+        return ENODEV;
+    }
+
+    struct ofpbuf request;
+    ofpbuf_init(&request, 0);
+
+    nl_msg_put_nlmsghdr(&request, 0, RTM_NEWLINK,
+                        NLM_F_REQUEST | NLM_F_ACK);
+    ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg));
+    nl_msg_put_string(&request, IFLA_IFNAME, slave);
+    nl_msg_put_u32(&request, IFLA_MASTER, master_idx);
+
+    err = nl_transact(NETLINK_ROUTE, &request, NULL);
+    ofpbuf_uninit(&request);
+    return err;
+}
+
+int
+ne_nl_set_iface_mac_addr(const char *ifname, const struct eth_addr *mac)
+{
+    int err = 0;
+    struct ofpbuf request;
+    ofpbuf_init(&request, 0);
+
+    nl_msg_put_nlmsghdr(&request, 0, RTM_NEWLINK,
+                        NLM_F_REQUEST | NLM_F_ACK);
+    ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg));
+    nl_msg_put_string(&request, IFLA_IFNAME, ifname);
+    nl_msg_put_unspec(&request, IFLA_ADDRESS, mac, sizeof *mac);
+
+    err = nl_transact(NETLINK_ROUTE, &request, NULL);
+    ofpbuf_uninit(&request);
+    return err;
+}
+
+int
+ne_nl_delete_iface(const char *ifname)
+{
+    return nl_delete_device(ifname);
+}
+
+int
+ne_nl_create_vrf(const char *ifname, uint32_t table_id)
+{
+    if (TABLE_ID_VALID(table_id)) {
+        return nl_create_vrf(ifname, table_id);
+    }
+
+    VLOG_WARN_RL(&rl, "attempt to create VRF using invalid table id %"PRIu32,
+                 table_id);
+
+    return EINVAL;
+}
+
diff --git a/controller/neighbor-exchange-netlink.h 
b/controller/neighbor-exchange-netlink.h
index 659fe72d8..37badb226 100644
--- a/controller/neighbor-exchange-netlink.h
+++ b/controller/neighbor-exchange-netlink.h
@@ -50,6 +50,17 @@ struct ne_table_msg {
     struct ne_nl_received_neigh nd; /* Data parsed from this message. */
 };
 
+int32_t ne_nl_ifindex_get(const char *ifname);
+int ne_nl_create_vxlan(const char *ifname, uint32_t vni,
+                       const struct in6_addr *local_ip, uint16_t dst_port,
+                       int32_t link_ifindex);
+int ne_nl_create_bridge(const char *ifname);
+int ne_nl_create_lo(const char *ifname);
+int ne_nl_create_vrf(const char *ifname, uint32_t table_id);
+int ne_nl_set_master(const char *slave, const char *master);
+int ne_nl_set_iface_mac_addr(const char *ifname, const struct eth_addr *mac);
+int ne_nl_delete_iface(const char *ifname);
+
 int ne_nl_sync_neigh(uint8_t family, int32_t if_index,
                      const struct hmap *neighbors,
                      struct vector *learned_neighbors);
-- 
2.48.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to