Convert OFED rtable interactions to the new routing KPI.
Reviewed by: hselasky Differential Revision: https://reviews.freebsd.org/D24387
This commit is contained in:
parent
64767a984d
commit
60042730d6
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user