@@ -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;
+}
+
@@ -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);
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 <ARukomoinikova@k2.cloud> --- controller/neighbor-exchange-netlink.c | 124 ++++++++++++++++++++++++- controller/neighbor-exchange-netlink.h | 11 +++ 2 files changed, 133 insertions(+), 2 deletions(-)