pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-uecups/+/42444?usp=email )
Change subject: Use libosmocore netdev API ......................................................................
Use libosmocore netdev API
Depends: libosmocore.git Change-Id I75153eb59e96a6a2505dc5b29432c76e5c21ea24 Change-Id: I8f18ef56a6e7186fed88f965fbb34aa390c3bac1 --- A TODO-RELEASE M daemon/Makefile.am M daemon/gtp_tunnel.c M daemon/internal.h D daemon/netdev.c M daemon/tun_device.c 6 files changed, 68 insertions(+), 182 deletions(-)
Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
diff --git a/TODO-RELEASE b/TODO-RELEASE new file mode 100644 index 0000000..8eda384 --- /dev/null +++ b/TODO-RELEASE @@ -0,0 +1,10 @@ +# When cleaning up this file: bump API version in corresponding Makefile.am and rename corresponding debian/lib*.install +# according to https://osmocom.org/projects/cellular-infrastructure/wiki/Make_a_new_release +# In short: https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.... +# LIBVERSION=c:r:a +# If the library source code has changed at all since the last update, then increment revision: c:r + 1:a. +# If any interfaces have been added, removed, or changed since the last update: c + 1:0:a. +# If any interfaces have been added since the last public release: c:r:a + 1. +# If any interfaces have been removed or changed since the last public release: c:r:0. +#library what description / commit summary line +libosmocore >1.13.1 osmo_netdev_del_addr() diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 1c680a6..89afe7a 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -37,7 +37,6 @@ osmo_uecups_daemon_SOURCES = \ cups_client.c \ utility.c \ - netdev.c \ tun_device.c \ gtp_daemon.c \ gtp_endpoint.c \ diff --git a/daemon/gtp_tunnel.c b/daemon/gtp_tunnel.c index a13b163..4c6b2c5 100644 --- a/daemon/gtp_tunnel.c +++ b/daemon/gtp_tunnel.c @@ -25,6 +25,7 @@ struct gtp_tunnel *gtp_tunnel_alloc(struct gtp_daemon *d, const struct gtp_tunnel_params *cpars) { struct gtp_tunnel *t; + int rc;
t = talloc_zero(d, struct gtp_tunnel); if (!t) @@ -60,9 +61,9 @@ memcpy(&t->user_addr, &cpars->user_addr, sizeof(t->user_addr)); memcpy(&t->remote_udp, &cpars->remote_udp, sizeof(t->remote_udp));
- if (netdev_add_addr(t->tun_dev->nl, t->tun_dev->ifindex, &t->user_addr) < 0) { + if ((rc = osmo_netdev_add_addr(t->tun_dev->netdev, &t->user_addr, 32)) < 0) { LOGT(t, LOGL_ERROR, "Cannot add user addr to tun device: %s\n", - strerror(errno)); + strerror(-rc)); }
/* TODO: hash table? */ @@ -134,12 +135,14 @@ /* UNLOCKED destroy of tunnel; drops references to EP + TUN */ void _gtp_tunnel_destroy(struct gtp_tunnel *t) { + int rc; + LOGT(t, LOGL_NOTICE, "Destroying\n"); /* talloc is not thread safe, all alloc/free must come from main thread */ ASSERT_MAIN_THREAD(t->d);
- if (netdev_del_addr(t->tun_dev->nl, t->tun_dev->ifindex, &t->user_addr) < 0) - LOGT(t, LOGL_ERROR, "Cannot remove user address: %s\n", strerror(errno)); + if ((rc = osmo_netdev_del_addr(t->tun_dev->netdev, &t->user_addr, 32)) < 0) + LOGT(t, LOGL_ERROR, "Cannot remove user address: %s\n", strerror(-rc));
llist_del(&t->list);
diff --git a/daemon/internal.h b/daemon/internal.h index 7a016fa..ae2356b 100644 --- a/daemon/internal.h +++ b/daemon/internal.h @@ -13,6 +13,7 @@ #include <osmocom/core/it_q.h> #include <osmocom/core/utils.h> #include <osmocom/core/socket.h> +#include <osmocom/core/netdev.h>
#include <osmocom/netif/stream.h>
@@ -36,15 +37,6 @@ DUECUPS, };
-/*********************************************************************** - * netdev / netlink - ***********************************************************************/ - -int netdev_add_addr(struct nl_sock *nlsk, int ifindex, const struct osmo_sockaddr *osa); -int netdev_del_addr(struct nl_sock *nlsk, int ifindex, const struct osmo_sockaddr *osa); -int netdev_set_link(struct nl_sock *nlsk, int ifindex, bool up); -int netdev_add_defaultroute(struct nl_sock *nlsk, int ifindex, uint8_t family); -
/*********************************************************************** * GTP Endpoint (UDP socket) @@ -115,8 +107,7 @@ const char *netns_name; int netns_fd;
- /* netlink socket in the namespace of the tun device */ - struct nl_sock *nl; + struct osmo_netdev *netdev;
/* list of local addresses? or simply only have the kernel know thses? */
diff --git a/daemon/netdev.c b/daemon/netdev.c deleted file mode 100644 index 165a6bc..0000000 --- a/daemon/netdev.c +++ /dev/null @@ -1,137 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include <unistd.h> -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/socket.h> - -#include <netinet/ip.h> -#include <netinet/ip6.h> - -#include <linux/if.h> -#include <linux/if_tun.h> -#include <sys/ioctl.h> - -#include <linux/netlink.h> -#include <netlink/socket.h> -#include <netlink/route/link.h> -#include <netlink/route/addr.h> -#include <netlink/route/route.h> -#include <netlink/route/nexthop.h> - -#include <osmocom/core/utils.h> -#include <osmocom/core/socket.h> - -/*********************************************************************** - * netlink helper functions - ***********************************************************************/ - -static int _netdev_addr(struct nl_sock *nlsk, int ifindex, const struct osmo_sockaddr *osa, bool add) -{ - struct nl_addr *local = NULL; - struct rtnl_addr *addr; - int rc; - - switch (osa->u.sa.sa_family) { - case AF_INET: - local = nl_addr_build(AF_INET, &osa->u.sin.sin_addr, 4); - break; - case AF_INET6: - local = nl_addr_build(AF_INET6, &osa->u.sin6.sin6_addr, 16); - break; - } - OSMO_ASSERT(local); - - addr = rtnl_addr_alloc(); - OSMO_ASSERT(addr); - rtnl_addr_set_ifindex(addr, ifindex); - OSMO_ASSERT(rtnl_addr_set_local(addr, local) == 0); - - if (add) - rc = rtnl_addr_add(nlsk, addr, 0); - else - rc = rtnl_addr_delete(nlsk, addr, 0); - - rtnl_addr_put(addr); - - return rc; -} - -int netdev_add_addr(struct nl_sock *nlsk, int ifindex, const struct osmo_sockaddr *osa) -{ - return _netdev_addr(nlsk, ifindex, osa, true); -} - -int netdev_del_addr(struct nl_sock *nlsk, int ifindex, const struct osmo_sockaddr *osa) -{ - return _netdev_addr(nlsk, ifindex, osa, false); -} - -int netdev_set_link(struct nl_sock *nlsk, int ifindex, bool up) -{ - struct rtnl_link *link, *change; - int rc; - - rc = rtnl_link_get_kernel(nlsk, ifindex, NULL, &link); - if (rc < 0) - return rc; - - change = rtnl_link_alloc(); - OSMO_ASSERT(change); - - if (up) - rtnl_link_set_flags(change, IFF_UP); - else - rtnl_link_unset_flags(change, IFF_UP); - - rc = rtnl_link_change(nlsk, link, change, 0); - - rtnl_link_put(change); - rtnl_link_put(link); - - return rc; -} - -int netdev_add_defaultroute(struct nl_sock *nlsk, int ifindex, uint8_t family) -{ - struct rtnl_route *route = rtnl_route_alloc(); - struct rtnl_nexthop *nhop = rtnl_route_nh_alloc(); - struct nl_addr *dst, *gw; - uint8_t buf[16]; - int rc; - - OSMO_ASSERT(route); - OSMO_ASSERT(nhop); - - /* destination address of route: all-zero */ - memset(buf, 0, sizeof(buf)); - dst = nl_addr_build(family, buf, family == AF_INET ? 4 : 16); - OSMO_ASSERT(dst); - nl_addr_set_prefixlen(dst, 0); - - /* gateway address of route: also all-zero */ - gw = nl_addr_clone(dst); - OSMO_ASSERT(gw); - - /* nexthop for route */ - rtnl_route_nh_set_ifindex(nhop, ifindex); - rtnl_route_nh_set_gateway(nhop, gw); - - /* tie everything together in the route */ - rtnl_route_set_dst(route, dst); - rtnl_route_set_family(route, family); - rtnl_route_add_nexthop(route, nhop); - - rc = rtnl_route_add(nlsk, route, NLM_F_CREATE); - - //rtnl_route_nh_free(nhop); - nl_addr_put(gw); - nl_addr_put(dst); - rtnl_route_put(route); - - return rc; -} diff --git a/daemon/tun_device.c b/daemon/tun_device.c index 837fd9d..c12c694 100644 --- a/daemon/tun_device.c +++ b/daemon/tun_device.c @@ -16,7 +16,7 @@ #include <fcntl.h> #include <signal.h> #include <netdb.h> - +#include <net/if.h> #include <netinet/ip.h> #include <netinet/ip6.h>
@@ -26,10 +26,6 @@ #include <linux/if_tun.h> #include <sys/ioctl.h>
-#include <linux/netlink.h> -#include <netlink/socket.h> -#include <netlink/route/link.h> - #include <osmocom/core/linuxlist.h> #include <osmocom/core/talloc.h> #include <osmocom/core/logging.h> @@ -318,9 +314,9 @@ static struct tun_device * _tun_device_create(struct gtp_daemon *d, const char *devname, const char *netns_name) { - struct rtnl_link *link; struct tun_device *tun; struct osmo_netns_switch_state switch_state; + bool inside_netns = false; int rc;
tun = talloc_zero(d, struct tun_device); @@ -349,6 +345,7 @@ tun->netns_name, strerror(errno)); goto err_close_ns; } + inside_netns = true; }
tun->fd = tun_open(0, tun->devname); @@ -357,49 +354,72 @@ goto err_restore_ns; }
- tun->nl = nl_socket_alloc(); - if (!tun->nl || nl_connect(tun->nl, NETLINK_ROUTE) < 0) { - LOGTUN(tun, LOGL_ERROR, "Cannot create netlink socket in namespace '%s'\n", - tun->netns_name); + /* Store interface index: + * (Note: there's a potential race condition here between creating the + * iface with a given name above and attempting to retrieve its ifindex based + * on that name. Someone (ie udev) could have the iface renamed in + * between here. It's a pity that TUNSETIFF doesn't copy back to us the + * newly allocated ifindex as it does with ifname) + */ + tun->ifindex = if_nametoindex(tun->devname); + if (tun->ifindex == 0) { + LOGTUN(tun, LOGL_ERROR, "Unable to find ifindex for dev %s\n", + tun->devname); goto err_close; }
- rc = rtnl_link_get_kernel(tun->nl, 0, tun->devname, &link); - if (rc < 0) { - LOGTUN(tun, LOGL_ERROR, "Cannot get ifindex for netif after create?!?\n"); - goto err_free_nl; - } - tun->ifindex = rtnl_link_get_ifindex(link); - rtnl_link_put(link); - /* switch back to default namespace before creating new thread */ - if (tun->netns_name) + if (inside_netns) { OSMO_ASSERT(osmo_netns_switch_exit(&switch_state) == 0); + inside_netns = false; + } + + tun->netdev = osmo_netdev_alloc(tun, tun->devname); + if (tun->netns_name) { + rc = osmo_netdev_set_netns_name(tun->netdev, tun->netns_name); + if (rc < 0) + goto err_free_netdev; + } + rc = osmo_netdev_set_ifindex(tun->netdev, tun->ifindex); + if (rc < 0) + goto err_free_netdev; + + rc = osmo_netdev_register(tun->netdev); + if (rc < 0) + goto err_free_netdev;
/* bring the network device up */ - rc = netdev_set_link(tun->nl, tun->ifindex, true); + rc = osmo_netdev_ifupdown(tun->netdev, true); if (rc < 0) LOGTUN(tun, LOGL_ERROR, "Cannot set interface to 'up'\n");
if (tun->netns_name) { - rc = netdev_add_defaultroute(tun->nl, tun->ifindex, AF_INET); + struct osmo_sockaddr osa; + + memset(&osa, 0, sizeof(osa)); + osa.u.sin.sin_family = AF_INET; + osa.u.sin.sin_addr.s_addr = 0; + rc = osmo_netdev_add_route(tun->netdev, &osa, 0, NULL); if (rc < 0) LOGTUN(tun, LOGL_ERROR, "Cannot add IPv4 default route " - "(rc=%d): %s\n", rc, nl_geterror(rc)); + "(rc=%d): %s\n", rc, strerror(-rc)); else LOGTUN(tun, LOGL_INFO, "Added IPv4 default route\n");
- rc = netdev_add_defaultroute(tun->nl, tun->ifindex, AF_INET6); + memset(&osa, 0, sizeof(osa)); + osa.u.sin6.sin6_family = AF_INET6; + memset(&osa.u.sin6.sin6_addr, 0, sizeof(osa.u.sin6.sin6_addr)); + rc = osmo_netdev_add_route(tun->netdev, &osa, 0, NULL); if (rc < 0) LOGTUN(tun, LOGL_ERROR, "Cannot add IPv6 default route " - "(rc=%d): %s\n", rc, nl_geterror(rc)); + "(rc=%d): %s\n", rc, strerror(-rc)); else LOGTUN(tun, LOGL_INFO, "Added IPv6 default route\n"); }
if (pthread_create(&tun->thread, NULL, tun_device_thread, tun)) { LOGTUN(tun, LOGL_ERROR, "Cannot create TUN thread: %s\n", strerror(errno)); - goto err_free_nl; + goto err_free_netdev; }
LOGTUN(tun, LOGL_INFO, "Created (in netns '%s')\n", tun->netns_name); @@ -407,12 +427,12 @@
return tun;
-err_free_nl: - nl_socket_free(tun->nl); +err_free_netdev: + osmo_netdev_free(tun->netdev); err_close: close(tun->fd); err_restore_ns: - if (tun->netns_name) + if (inside_netns) OSMO_ASSERT(osmo_netns_switch_exit(&switch_state) == 0); err_close_ns: if (tun->netns_name) @@ -482,7 +502,7 @@ if (tun->netns_name) close(tun->netns_fd); close(tun->fd); - nl_socket_free(tun->nl); + osmo_netdev_free(tun->netdev); talloc_free(tun); }