Commit d23647fd authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'net-mctp-add-support-for-gateway-routing'



Jeremy Kerr says:

====================
net: mctp: Add support for gateway routing

This series adds a gateway route type for the MCTP core, allowing
non-local EIDs as the match for a route.

Example setup using the mctp tools:

    mctp route add 9 via mctpi2c0
    mctp neigh add 9 dev mctpi2c0 lladdr 0x1d
    mctp route add 10 gw 9

- will route packets to eid 10 through mctpi2c0, using a dest lladdr
of 0x1d (ie, that of the directly-attached eid 9).

The core change to support this is the introduction of a struct
mctp_dst, which represents the result of a route lookup. Since this
involves a bit of surgery through the routing code, we add a few tests
along the way.

We're introducing an ABI change in the new RTM_{NEW,GET,DEL}ROUTE
netlink formats, with the support for a RTA_GATEWAY attribute. Because
we need a network ID specified to fully-qualify a gateway EID, the
RTA_GATEWAY attribute carries the (net, eid) tuple in full:

    struct mctp_fq_addr {
        unsigned int net;
        mctp_eid_t eid;
    }

Of course, any questions, comments etc are most welcome.

Signed-off-by: default avatarJeremy Kerr <jk@codeconstruct.com.au>
====================

Link: https://patch.msgid.link/20250702-dev-forwarding-v5-0-1468191da8a4@codeconstruct.com.au


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 05cc60ef 48e1736e
Loading
Loading
Loading
Loading
+43 −9
Original line number Diff line number Diff line
@@ -183,8 +183,8 @@ struct mctp_sk_key {
struct mctp_skb_cb {
	unsigned int	magic;
	unsigned int	net;
	int		ifindex; /* extended/direct addressing if set */
	mctp_eid_t	src;
	/* fields below provide extended addressing for ingress to recvmsg() */
	int		ifindex;
	unsigned char	halen;
	unsigned char	haddr[MAX_ADDR_LEN];
};
@@ -222,6 +222,8 @@ struct mctp_flow {
	struct mctp_sk_key *key;
};

struct mctp_dst;

/* Route definition.
 *
 * These are held in the pernet->mctp.routes list, with RCU protection for
@@ -229,16 +231,25 @@ struct mctp_flow {
 * dropped on NETDEV_UNREGISTER events.
 *
 * Updates to the route table are performed under rtnl; all reads under RCU,
 * so routes cannot be referenced over a RCU grace period. Specifically: A
 * caller cannot block between mctp_route_lookup and mctp_route_release()
 * so routes cannot be referenced over a RCU grace period.
 */
struct mctp_route {
	mctp_eid_t		min, max;

	unsigned char		type;

	unsigned int		mtu;

	enum {
		MCTP_ROUTE_DIRECT,
		MCTP_ROUTE_GATEWAY,
	} dst_type;
	union {
		struct mctp_dev	*dev;
	int			(*output)(struct mctp_route *route,
		struct mctp_fq_addr gateway;
	};

	int			(*output)(struct mctp_dst *dst,
					  struct sk_buff *skb);

	struct list_head	list;
@@ -246,12 +257,35 @@ struct mctp_route {
	struct rcu_head		rcu;
};

/* Route lookup result: dst. Represents the results of a routing decision,
 * but is only held over the individual routing operation.
 *
 * Will typically be stored on the caller stack, and must be released after
 * usage.
 */
struct mctp_dst {
	struct mctp_dev *dev;
	unsigned int mtu;
	mctp_eid_t nexthop;

	/* set for direct addressing */
	unsigned char halen;
	unsigned char haddr[MAX_ADDR_LEN];

	int (*output)(struct mctp_dst *dst, struct sk_buff *skb);
};

int mctp_dst_from_extaddr(struct mctp_dst *dst, struct net *net, int ifindex,
			  unsigned char halen, const unsigned char *haddr);

/* route interfaces */
struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet,
				     mctp_eid_t daddr);
int mctp_route_lookup(struct net *net, unsigned int dnet,
		      mctp_eid_t daddr, struct mctp_dst *dst);

void mctp_dst_release(struct mctp_dst *dst);

/* always takes ownership of skb */
int mctp_local_output(struct sock *sk, struct mctp_route *rt,
int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
		      struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag);

void mctp_key_unref(struct mctp_sk_key *key);
+8 −0
Original line number Diff line number Diff line
@@ -37,6 +37,14 @@ struct sockaddr_mctp_ext {
	__u8			smctp_haddr[MAX_ADDR_LEN];
};

/* A "fully qualified" MCTP address, which includes the system-local network ID,
 * required to uniquely resolve a routable EID.
 */
struct mctp_fq_addr {
	unsigned int	net;
	mctp_eid_t	eid;
};

#define MCTP_NET_ANY		0x0

#define MCTP_ADDR_NULL		0x00
+26 −40
Original line number Diff line number Diff line
@@ -97,8 +97,8 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
	struct sock *sk = sock->sk;
	struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
	struct mctp_skb_cb *cb;
	struct mctp_route *rt;
	struct sk_buff *skb = NULL;
	struct mctp_dst dst;
	int hlen;

	if (addr) {
@@ -133,34 +133,30 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
	if (msk->addr_ext && addrlen >= sizeof(struct sockaddr_mctp_ext)) {
		DECLARE_SOCKADDR(struct sockaddr_mctp_ext *,
				 extaddr, msg->msg_name);
		struct net_device *dev;

		rc = -EINVAL;
		rcu_read_lock();
		dev = dev_get_by_index_rcu(sock_net(sk), extaddr->smctp_ifindex);
		/* check for correct halen */
		if (dev && extaddr->smctp_halen == dev->addr_len) {
			hlen = LL_RESERVED_SPACE(dev) + sizeof(struct mctp_hdr);
			rc = 0;
		}
		rcu_read_unlock();
		if (!mctp_sockaddr_ext_is_ok(extaddr))
			return -EINVAL;

		rc = mctp_dst_from_extaddr(&dst, sock_net(sk),
					   extaddr->smctp_ifindex,
					   extaddr->smctp_halen,
					   extaddr->smctp_haddr);
		if (rc)
			goto err_free;
		rt = NULL;
			return rc;

	} else {
		rt = mctp_route_lookup(sock_net(sk), addr->smctp_network,
				       addr->smctp_addr.s_addr);
		if (!rt) {
			rc = -EHOSTUNREACH;
			goto err_free;
		}
		hlen = LL_RESERVED_SPACE(rt->dev->dev) + sizeof(struct mctp_hdr);
		rc = mctp_route_lookup(sock_net(sk), addr->smctp_network,
				       addr->smctp_addr.s_addr, &dst);
		if (rc)
			return rc;
	}

	hlen = LL_RESERVED_SPACE(dst.dev->dev) + sizeof(struct mctp_hdr);

	skb = sock_alloc_send_skb(sk, hlen + 1 + len,
				  msg->msg_flags & MSG_DONTWAIT, &rc);
	if (!skb)
		return rc;
		goto err_release_dst;

	skb_reserve(skb, hlen);

@@ -175,30 +171,16 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
	cb = __mctp_cb(skb);
	cb->net = addr->smctp_network;

	if (!rt) {
		/* fill extended address in cb */
		DECLARE_SOCKADDR(struct sockaddr_mctp_ext *,
				 extaddr, msg->msg_name);

		if (!mctp_sockaddr_ext_is_ok(extaddr) ||
		    extaddr->smctp_halen > sizeof(cb->haddr)) {
			rc = -EINVAL;
			goto err_free;
		}

		cb->ifindex = extaddr->smctp_ifindex;
		/* smctp_halen is checked above */
		cb->halen = extaddr->smctp_halen;
		memcpy(cb->haddr, extaddr->smctp_haddr, cb->halen);
	}

	rc = mctp_local_output(sk, rt, skb, addr->smctp_addr.s_addr,
	rc = mctp_local_output(sk, &dst, skb, addr->smctp_addr.s_addr,
			       addr->smctp_tag);

	mctp_dst_release(&dst);
	return rc ? : len;

err_free:
	kfree_skb(skb);
err_release_dst:
	mctp_dst_release(&dst);
	return rc;
}

@@ -793,3 +775,7 @@ MODULE_DESCRIPTION("MCTP core");
MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");

MODULE_ALIAS_NETPROTO(PF_MCTP);

#if IS_ENABLED(CONFIG_MCTP_TEST)
#include "test/sock-test.c"
#endif
+385 −189

File changed.

Preview size limit exceeded, changes collapsed.

+395 −217

File changed.

Preview size limit exceeded, changes collapsed.

Loading