Convert OFED rtable interactions to the new routing KPI.

Reviewed by:	hselasky
Differential Revision:	https://reviews.freebsd.org/D24387
This commit is contained in:
melifaro 2020-04-15 13:06:55 +00:00
parent 64767a984d
commit 60042730d6
2 changed files with 59 additions and 82 deletions

View File

@ -44,14 +44,17 @@ __FBSDID("$FreeBSD$");
#include <linux/workqueue.h>
#include <linux/module.h>
#include <net/route.h>
#include <net/route/nhop.h>
#include <net/netevent.h>
#include <rdma/ib_addr.h>
#include <rdma/ib.h>
#include <netinet/in_fib.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet6/scope6_var.h>
#include <netinet6/in6_pcb.h>
#include <netinet6/in6_fib.h>
#include "core_priv.h"
@ -275,11 +278,13 @@ static int addr4_resolve(struct sockaddr_in *src_in,
struct sockaddr_in dst_tmp = *dst_in;
in_port_t src_port;
struct sockaddr *saddr = NULL;
struct rtentry *rte;
struct nhop_object *nh;
struct ifnet *ifp;
int error;
int type;
NET_EPOCH_ASSERT();
/* set VNET, if any */
CURVNET_SET(addr->net);
@ -293,8 +298,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
type |= ADDR_DST_ANY;
/*
* Make sure the socket address length field
* is set, else rtalloc1() will fail.
* Make sure the socket address length field is set.
*/
dst_tmp.sin_len = sizeof(dst_tmp);
@ -303,16 +307,11 @@ static int addr4_resolve(struct sockaddr_in *src_in,
case ADDR_VALID:
case ADDR_SRC_ANY:
/* regular destination route lookup */
rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0);
if (rte == NULL) {
error = EHOSTUNREACH;
goto done;
} else if (rte->rt_ifp == NULL || RT_LINK_IS_UP(rte->rt_ifp) == 0) {
RTFREE_LOCKED(rte);
nh = fib4_lookup(RT_DEFAULT_FIB, dst_tmp.sin_addr,0,NHR_NONE,0);
if (nh == NULL) {
error = EHOSTUNREACH;
goto done;
}
RT_UNLOCK(rte);
break;
default:
error = ENETUNREACH;
@ -332,14 +331,14 @@ static int addr4_resolve(struct sockaddr_in *src_in,
/* check source interface */
if (ifp == NULL) {
error = ENETUNREACH;
goto error_rt_free;
goto done;
} else if (ifp->if_flags & IFF_LOOPBACK) {
/*
* Source address cannot be a loopback device.
*/
error = EHOSTUNREACH;
goto error_put_ifp;
} else if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
} else if (nh->nh_ifp->if_flags & IFF_LOOPBACK) {
if (memcmp(&src_in->sin_addr, &dst_in->sin_addr,
sizeof(src_in->sin_addr))) {
/*
@ -352,9 +351,9 @@ static int addr4_resolve(struct sockaddr_in *src_in,
}
/* get destination network interface from route */
dev_put(ifp);
ifp = rte->rt_ifp;
ifp = nh->nh_ifp;
dev_hold(ifp);
} else if (ifp != rte->rt_ifp) {
} else if (ifp != nh->nh_ifp) {
/*
* Source and destination interfaces are
* different.
@ -365,13 +364,13 @@ static int addr4_resolve(struct sockaddr_in *src_in,
break;
case ADDR_SRC_ANY:
/* check for loopback device */
if (rte->rt_ifp->if_flags & IFF_LOOPBACK)
if (nh->nh_ifp->if_flags & IFF_LOOPBACK)
saddr = (struct sockaddr *)&dst_tmp;
else
saddr = rte->rt_ifa->ifa_addr;
saddr = nh->nh_ifa->ifa_addr;
/* get destination network interface from route */
ifp = rte->rt_ifp;
ifp = nh->nh_ifp;
dev_hold(ifp);
break;
default:
@ -386,7 +385,7 @@ static int addr4_resolve(struct sockaddr_in *src_in,
ifp->if_addrlen, MAX_ADDR_LEN);
error = 0;
} else if (IN_MULTICAST(ntohl(dst_tmp.sin_addr.s_addr))) {
bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
bool is_gw = (nh->nh_flags & NHF_GATEWAY) != 0;
error = addr_resolve_multi(edst, ifp, (struct sockaddr *)&dst_tmp);
if (error != 0)
goto error_put_ifp;
@ -396,10 +395,10 @@ static int addr4_resolve(struct sockaddr_in *src_in,
memset(edst, 0, MAX_ADDR_LEN);
error = 0;
} else {
bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
bool is_gw = (nh->nh_flags & NHF_GATEWAY) != 0;
memset(edst, 0, MAX_ADDR_LEN);
error = arpresolve(ifp, is_gw, NULL, is_gw ?
rte->rt_gateway : (const struct sockaddr *)&dst_tmp,
&nh->gw_sa : (const struct sockaddr *)&dst_tmp,
edst, NULL, NULL);
if (error != 0)
goto error_put_ifp;
@ -416,17 +415,12 @@ static int addr4_resolve(struct sockaddr_in *src_in,
src_in->sin_port = src_port; /* preserve port number */
}
if (rte != NULL)
RTFREE(rte);
*ifpp = ifp;
goto done;
error_put_ifp:
dev_put(ifp);
error_rt_free:
RTFREE(rte);
done:
CURVNET_RESTORE();
@ -460,11 +454,13 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
struct sockaddr_in6 dst_tmp = *dst_in;
in_port_t src_port;
struct sockaddr *saddr = NULL;
struct rtentry *rte;
struct nhop_object *nh;
struct ifnet *ifp;
int error;
int type;
NET_EPOCH_ASSERT();
/* set VNET, if any */
CURVNET_SET(addr->net);
@ -478,14 +474,13 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
type |= ADDR_DST_ANY;
/*
* Make sure the socket address length field
* is set, else rtalloc1() will fail.
* Make sure the socket address length field is set.
*/
dst_tmp.sin6_len = sizeof(dst_tmp);
/*
* Make sure the scope ID gets embedded, else rtalloc1() will
* resolve to the loopback interface.
* Make sure the scope ID gets embedded, else nd6_resolve() will
* not find the record.
*/
dst_tmp.sin6_scope_id = addr->bound_dev_if;
sa6_embedscope(&dst_tmp, 0);
@ -502,16 +497,12 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
/* FALLTHROUGH */
case ADDR_SRC_ANY:
/* regular destination route lookup */
rte = rtalloc1((struct sockaddr *)&dst_tmp, 1, 0);
if (rte == NULL) {
error = EHOSTUNREACH;
goto done;
} else if (rte->rt_ifp == NULL || RT_LINK_IS_UP(rte->rt_ifp) == 0) {
RTFREE_LOCKED(rte);
nh = fib6_lookup(RT_DEFAULT_FIB, &dst_in->sin6_addr,
addr->bound_dev_if, NHR_NONE, 0);
if (nh == NULL) {
error = EHOSTUNREACH;
goto done;
}
RT_UNLOCK(rte);
break;
default:
error = ENETUNREACH;
@ -531,14 +522,14 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
/* check source interface */
if (ifp == NULL) {
error = ENETUNREACH;
goto error_rt_free;
goto done;
} else if (ifp->if_flags & IFF_LOOPBACK) {
/*
* Source address cannot be a loopback device.
*/
error = EHOSTUNREACH;
goto error_put_ifp;
} else if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
} else if (nh->nh_ifp->if_flags & IFF_LOOPBACK) {
if (memcmp(&src_in->sin6_addr, &dst_in->sin6_addr,
sizeof(src_in->sin6_addr))) {
/*
@ -551,9 +542,9 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
}
/* get destination network interface from route */
dev_put(ifp);
ifp = rte->rt_ifp;
ifp = nh->nh_ifp;
dev_hold(ifp);
} else if (ifp != rte->rt_ifp) {
} else if (ifp != nh->nh_ifp) {
/*
* Source and destination interfaces are
* different.
@ -564,13 +555,13 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
break;
case ADDR_SRC_ANY:
/* check for loopback device */
if (rte->rt_ifp->if_flags & IFF_LOOPBACK)
if (nh->nh_ifp->if_flags & IFF_LOOPBACK)
saddr = (struct sockaddr *)&dst_tmp;
else
saddr = rte->rt_ifa->ifa_addr;
saddr = nh->nh_ifa->ifa_addr;
/* get destination network interface from route */
ifp = rte->rt_ifp;
ifp = nh->nh_ifp;
dev_hold(ifp);
break;
default:
@ -581,21 +572,21 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
* Step 3 - resolve destination MAC address
*/
if (IN6_IS_ADDR_MULTICAST(&dst_tmp.sin6_addr)) {
bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
bool is_gw = (nh->nh_flags & NHF_GATEWAY) != 0;
error = addr_resolve_multi(edst, ifp,
(struct sockaddr *)&dst_tmp);
if (error != 0)
goto error_put_ifp;
else if (is_gw)
addr->network = RDMA_NETWORK_IPV6;
} else if (rte->rt_ifp->if_flags & IFF_LOOPBACK) {
} else if (nh->nh_ifp->if_flags & IFF_LOOPBACK) {
memset(edst, 0, MAX_ADDR_LEN);
error = 0;
} else {
bool is_gw = (rte->rt_flags & RTF_GATEWAY) != 0;
bool is_gw = (nh->nh_flags & NHF_GATEWAY) != 0;
memset(edst, 0, MAX_ADDR_LEN);
error = nd6_resolve(ifp, is_gw, NULL, is_gw ?
rte->rt_gateway : (const struct sockaddr *)&dst_tmp,
&nh->gw_sa : (const struct sockaddr *)&dst_tmp,
edst, NULL, NULL);
if (error != 0)
goto error_put_ifp;
@ -612,17 +603,12 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
src_in->sin6_port = src_port; /* preserve port number */
}
if (rte != NULL)
RTFREE(rte);
*ifpp = ifp;
goto done;
error_put_ifp:
dev_put(ifp);
error_rt_free:
RTFREE(rte);
done:
CURVNET_RESTORE();

View File

@ -50,10 +50,14 @@ __FBSDID("$FreeBSD$");
#include <linux/slab.h>
#include <linux/module.h>
#include <net/route.h>
#include <net/route/nhop.h>
#include <net/tcp.h>
#include <net/ipv6.h>
#include <netinet/in_fib.h>
#include <netinet6/in6_fib.h>
#include <netinet6/scope6_var.h>
#include <netinet6/ip6_var.h>
@ -1351,11 +1355,10 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev,
const struct sockaddr_in *src_addr)
{
#ifdef INET
struct sockaddr_in src_tmp = *src_addr;
__be32 daddr = dst_addr->sin_addr.s_addr,
saddr = src_addr->sin_addr.s_addr;
struct net_device *dst_dev;
struct rtentry *rte;
struct nhop_object *nh;
bool ret;
if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) ||
@ -1378,20 +1381,12 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev,
if (saddr == daddr)
return true;
/*
* Make sure the socket address length field
* is set, else rtalloc1() will fail.
*/
src_tmp.sin_len = sizeof(src_tmp);
CURVNET_SET(net_dev->if_vnet);
rte = rtalloc1((struct sockaddr *)&src_tmp, 1, 0);
if (rte != NULL) {
ret = (rte->rt_ifp == net_dev);
RTFREE_LOCKED(rte);
} else {
nh = fib4_lookup(RT_DEFAULT_FIB, src_addr->sin_addr, 0, NHR_NONE, 0);
if (nh != NULL)
ret = (nh->nh_ifp == net_dev);
else
ret = false;
}
CURVNET_RESTORE();
return ret;
#else
@ -1407,7 +1402,7 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev,
struct sockaddr_in6 src_tmp = *src_addr;
struct sockaddr_in6 dst_tmp = *dst_addr;
struct net_device *dst_dev;
struct rtentry *rte;
struct nhop_object *nh;
bool ret;
dst_dev = ip6_dev_find(net_dev->if_vnet, dst_tmp.sin6_addr,
@ -1422,14 +1417,7 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev,
CURVNET_SET(net_dev->if_vnet);
/*
* Make sure the socket address length field
* is set, else rtalloc1() will fail.
*/
src_tmp.sin6_len = sizeof(src_tmp);
/*
* Make sure the scope ID gets embedded, else rtalloc1() will
* resolve to the loopback interface.
* Make sure the scope ID gets embedded.
*/
src_tmp.sin6_scope_id = net_dev->if_index;
sa6_embedscope(&src_tmp, 0);
@ -1446,13 +1434,12 @@ static bool validate_ipv6_net_dev(struct net_device *net_dev,
ret = true;
} else {
/* non-loopback case */
rte = rtalloc1((struct sockaddr *)&src_tmp, 1, 0);
if (rte != NULL) {
ret = (rte->rt_ifp == net_dev);
RTFREE_LOCKED(rte);
} else {
nh = fib6_lookup(RT_DEFAULT_FIB, &src_addr->sin6_addr,
net_dev->if_index, NHR_NONE, 0);
if (nh != NULL)
ret = (nh->nh_ifp == net_dev);
else
ret = false;
}
}
CURVNET_RESTORE();
return ret;
@ -1512,6 +1499,7 @@ static struct net_device *cma_get_net_dev(struct ib_cm_event *ib_event,
*src_addr = (struct sockaddr *)&src_addr_storage;
struct net_device *net_dev;
const union ib_gid *gid = req->has_gid ? &req->local_gid : NULL;
struct epoch_tracker et;
int err;
err = cma_save_ip_info(listen_addr, src_addr, ib_event,
@ -1530,10 +1518,13 @@ static struct net_device *cma_get_net_dev(struct ib_cm_event *ib_event,
if (!net_dev)
return ERR_PTR(-ENODEV);
NET_EPOCH_ENTER(et);
if (!validate_net_dev(net_dev, listen_addr, src_addr)) {
NET_EPOCH_EXIT(et);
dev_put(net_dev);
return ERR_PTR(-EHOSTUNREACH);
}
NET_EPOCH_EXIT(et);
return net_dev;
}