xref: /openbmc/linux/include/net/mctp.h (revision 67737c457281dd199ceb9e31b6ba7efd3bfe566d)
12c8e2e9aSJeremy Kerr /* SPDX-License-Identifier: GPL-2.0 */
22c8e2e9aSJeremy Kerr /*
32c8e2e9aSJeremy Kerr  * Management Component Transport Protocol (MCTP)
42c8e2e9aSJeremy Kerr  *
52c8e2e9aSJeremy Kerr  * Copyright (c) 2021 Code Construct
62c8e2e9aSJeremy Kerr  * Copyright (c) 2021 Google
72c8e2e9aSJeremy Kerr  */
82c8e2e9aSJeremy Kerr 
92c8e2e9aSJeremy Kerr #ifndef __NET_MCTP_H
102c8e2e9aSJeremy Kerr #define __NET_MCTP_H
112c8e2e9aSJeremy Kerr 
122c8e2e9aSJeremy Kerr #include <linux/bits.h>
13583be982SJeremy Kerr #include <linux/mctp.h>
1499ce45d5SJeremy Kerr #include <linux/netdevice.h>
15889b7da2SJeremy Kerr #include <net/net_namespace.h>
16833ef3b9SJeremy Kerr #include <net/sock.h>
172c8e2e9aSJeremy Kerr 
182c8e2e9aSJeremy Kerr /* MCTP packet definitions */
192c8e2e9aSJeremy Kerr struct mctp_hdr {
202c8e2e9aSJeremy Kerr 	u8	ver;
212c8e2e9aSJeremy Kerr 	u8	dest;
222c8e2e9aSJeremy Kerr 	u8	src;
232c8e2e9aSJeremy Kerr 	u8	flags_seq_tag;
242c8e2e9aSJeremy Kerr };
252c8e2e9aSJeremy Kerr 
262c8e2e9aSJeremy Kerr #define MCTP_VER_MIN	1
272c8e2e9aSJeremy Kerr #define MCTP_VER_MAX	1
282c8e2e9aSJeremy Kerr 
292c8e2e9aSJeremy Kerr /* Definitions for flags_seq_tag field */
302c8e2e9aSJeremy Kerr #define MCTP_HDR_FLAG_SOM	BIT(7)
312c8e2e9aSJeremy Kerr #define MCTP_HDR_FLAG_EOM	BIT(6)
322c8e2e9aSJeremy Kerr #define MCTP_HDR_FLAG_TO	BIT(3)
332c8e2e9aSJeremy Kerr #define MCTP_HDR_FLAGS		GENMASK(5, 3)
342c8e2e9aSJeremy Kerr #define MCTP_HDR_SEQ_SHIFT	4
352c8e2e9aSJeremy Kerr #define MCTP_HDR_SEQ_MASK	GENMASK(1, 0)
362c8e2e9aSJeremy Kerr #define MCTP_HDR_TAG_SHIFT	0
372c8e2e9aSJeremy Kerr #define MCTP_HDR_TAG_MASK	GENMASK(2, 0)
382c8e2e9aSJeremy Kerr 
39889b7da2SJeremy Kerr #define MCTP_HEADER_MAXLEN	4
40889b7da2SJeremy Kerr 
4103f2bbc4SMatt Johnston #define MCTP_INITIAL_DEFAULT_NET	1
4203f2bbc4SMatt Johnston 
43583be982SJeremy Kerr static inline bool mctp_address_ok(mctp_eid_t eid)
44583be982SJeremy Kerr {
45583be982SJeremy Kerr 	return eid >= 8 && eid < 255;
46583be982SJeremy Kerr }
47583be982SJeremy Kerr 
48583be982SJeremy Kerr static inline struct mctp_hdr *mctp_hdr(struct sk_buff *skb)
49583be982SJeremy Kerr {
50583be982SJeremy Kerr 	return (struct mctp_hdr *)skb_network_header(skb);
51583be982SJeremy Kerr }
52583be982SJeremy Kerr 
53833ef3b9SJeremy Kerr /* socket implementation */
54833ef3b9SJeremy Kerr struct mctp_sock {
55833ef3b9SJeremy Kerr 	struct sock	sk;
56833ef3b9SJeremy Kerr 
57833ef3b9SJeremy Kerr 	/* bind() params */
58b416beb2SJeremy Kerr 	unsigned int	bind_net;
59833ef3b9SJeremy Kerr 	mctp_eid_t	bind_addr;
60833ef3b9SJeremy Kerr 	__u8		bind_type;
61833ef3b9SJeremy Kerr 
6299ce45d5SJeremy Kerr 	/* sendmsg()/recvmsg() uses struct sockaddr_mctp_ext */
6399ce45d5SJeremy Kerr 	bool		addr_ext;
6499ce45d5SJeremy Kerr 
65833ef3b9SJeremy Kerr 	/* list of mctp_sk_key, for incoming tag lookup. updates protected
66833ef3b9SJeremy Kerr 	 * by sk->net->keys_lock
67833ef3b9SJeremy Kerr 	 */
68833ef3b9SJeremy Kerr 	struct hlist_head keys;
697b14e15aSJeremy Kerr 
707b14e15aSJeremy Kerr 	/* mechanism for expiring allocated keys; will release an allocated
717b14e15aSJeremy Kerr 	 * tag, and any netdev state for a request/response pairing
727b14e15aSJeremy Kerr 	 */
737b14e15aSJeremy Kerr 	struct timer_list key_expiry;
74833ef3b9SJeremy Kerr };
75833ef3b9SJeremy Kerr 
76833ef3b9SJeremy Kerr /* Key for matching incoming packets to sockets or reassembly contexts.
77833ef3b9SJeremy Kerr  * Packets are matched on (src,dest,tag).
78833ef3b9SJeremy Kerr  *
7973c61845SJeremy Kerr  * Lifetime / locking requirements:
80833ef3b9SJeremy Kerr  *
8173c61845SJeremy Kerr  *  - individual key data (ie, the struct itself) is protected by key->lock;
8273c61845SJeremy Kerr  *    changes must be made with that lock held.
8373c61845SJeremy Kerr  *
8473c61845SJeremy Kerr  *  - the lookup fields: peer_addr, local_addr and tag are set before the
8573c61845SJeremy Kerr  *    key is added to lookup lists, and never updated.
8673c61845SJeremy Kerr  *
8773c61845SJeremy Kerr  *  - A ref to the key must be held (throuh key->refs) if a pointer to the
8873c61845SJeremy Kerr  *    key is to be accessed after key->lock is released.
89833ef3b9SJeremy Kerr  *
90833ef3b9SJeremy Kerr  *  - a mctp_sk_key contains a reference to a struct sock; this is valid
91833ef3b9SJeremy Kerr  *    for the life of the key. On sock destruction (through unhash), the key is
9273c61845SJeremy Kerr  *    removed from lists (see below), and marked invalid.
93833ef3b9SJeremy Kerr  *
94833ef3b9SJeremy Kerr  * - these mctp_sk_keys appear on two lists:
95833ef3b9SJeremy Kerr  *     1) the struct mctp_sock->keys list
96833ef3b9SJeremy Kerr  *     2) the struct netns_mctp->keys list
97833ef3b9SJeremy Kerr  *
9873c61845SJeremy Kerr  *   presences on these lists requires a (single) refcount to be held; both
9973c61845SJeremy Kerr  *   lists are updated as a single operation.
10073c61845SJeremy Kerr  *
10173c61845SJeremy Kerr  *   Updates and lookups in either list are performed under the
10273c61845SJeremy Kerr  *   netns_mctp->keys lock. Lookup functions will need to lock the key and
10373c61845SJeremy Kerr  *   take a reference before unlocking the keys_lock. Consequently, the list's
10473c61845SJeremy Kerr  *   keys_lock *cannot* be acquired with the individual key->lock held.
105833ef3b9SJeremy Kerr  *
1064a992bbdSJeremy Kerr  * - a key may have a sk_buff attached as part of an in-progress message
10773c61845SJeremy Kerr  *   reassembly (->reasm_head). The reasm data is protected by the individual
10873c61845SJeremy Kerr  *   key->lock.
1094a992bbdSJeremy Kerr  *
1104a992bbdSJeremy Kerr  * - there are two destruction paths for a mctp_sk_key:
1114a992bbdSJeremy Kerr  *
1124a992bbdSJeremy Kerr  *    - through socket unhash (see mctp_sk_unhash). This performs the list
1134a992bbdSJeremy Kerr  *      removal under keys_lock.
1144a992bbdSJeremy Kerr  *
1154a992bbdSJeremy Kerr  *    - where a key is established to receive a reply message: after receiving
1164a992bbdSJeremy Kerr  *      the (complete) reply, or during reassembly errors. Here, we clean up
1174a992bbdSJeremy Kerr  *      the reassembly context (marking reasm_dead, to prevent another from
1184a992bbdSJeremy Kerr  *      starting), and remove the socket from the netns & socket lists.
1197b14e15aSJeremy Kerr  *
1207b14e15aSJeremy Kerr  *    - through an expiry timeout, on a per-socket timer
121833ef3b9SJeremy Kerr  */
122833ef3b9SJeremy Kerr struct mctp_sk_key {
123833ef3b9SJeremy Kerr 	mctp_eid_t	peer_addr;
124833ef3b9SJeremy Kerr 	mctp_eid_t	local_addr;
125833ef3b9SJeremy Kerr 	__u8		tag; /* incoming tag match; invert TO for local */
126833ef3b9SJeremy Kerr 
127833ef3b9SJeremy Kerr 	/* we hold a ref to sk when set */
128833ef3b9SJeremy Kerr 	struct sock	*sk;
129833ef3b9SJeremy Kerr 
130833ef3b9SJeremy Kerr 	/* routing lookup list */
131833ef3b9SJeremy Kerr 	struct hlist_node hlist;
132833ef3b9SJeremy Kerr 
133833ef3b9SJeremy Kerr 	/* per-socket list */
134833ef3b9SJeremy Kerr 	struct hlist_node sklist;
135833ef3b9SJeremy Kerr 
13673c61845SJeremy Kerr 	/* lock protects against concurrent updates to the reassembly and
13773c61845SJeremy Kerr 	 * expiry data below.
13873c61845SJeremy Kerr 	 */
13973c61845SJeremy Kerr 	spinlock_t	lock;
14073c61845SJeremy Kerr 
14173c61845SJeremy Kerr 	/* Keys are referenced during the output path, which may sleep */
14273c61845SJeremy Kerr 	refcount_t	refs;
14373c61845SJeremy Kerr 
1444a992bbdSJeremy Kerr 	/* incoming fragment reassembly context */
1454a992bbdSJeremy Kerr 	struct sk_buff	*reasm_head;
1464a992bbdSJeremy Kerr 	struct sk_buff	**reasm_tailp;
1474a992bbdSJeremy Kerr 	bool		reasm_dead;
1484a992bbdSJeremy Kerr 	u8		last_seq;
1494a992bbdSJeremy Kerr 
15073c61845SJeremy Kerr 	/* key validity */
15173c61845SJeremy Kerr 	bool		valid;
1527b14e15aSJeremy Kerr 
1537b14e15aSJeremy Kerr 	/* expiry timeout; valid (above) cleared on expiry */
1547b14e15aSJeremy Kerr 	unsigned long	expiry;
155*67737c45SJeremy Kerr 
156*67737c45SJeremy Kerr 	/* free to use for device flow state tracking. Initialised to
157*67737c45SJeremy Kerr 	 * zero on initial key creation
158*67737c45SJeremy Kerr 	 */
159*67737c45SJeremy Kerr 	unsigned long	dev_flow_state;
160*67737c45SJeremy Kerr 	struct mctp_dev	*dev;
161833ef3b9SJeremy Kerr };
162833ef3b9SJeremy Kerr 
163889b7da2SJeremy Kerr struct mctp_skb_cb {
164889b7da2SJeremy Kerr 	unsigned int	magic;
165889b7da2SJeremy Kerr 	unsigned int	net;
16699ce45d5SJeremy Kerr 	int		ifindex; /* extended/direct addressing if set */
167889b7da2SJeremy Kerr 	mctp_eid_t	src;
16899ce45d5SJeremy Kerr 	unsigned char	halen;
16999ce45d5SJeremy Kerr 	unsigned char	haddr[MAX_ADDR_LEN];
170889b7da2SJeremy Kerr };
171889b7da2SJeremy Kerr 
172889b7da2SJeremy Kerr /* skb control-block accessors with a little extra debugging for initial
173889b7da2SJeremy Kerr  * development.
174889b7da2SJeremy Kerr  *
175889b7da2SJeremy Kerr  * TODO: remove checks & mctp_skb_cb->magic; replace callers of __mctp_cb
176889b7da2SJeremy Kerr  * with mctp_cb().
177889b7da2SJeremy Kerr  *
178889b7da2SJeremy Kerr  * __mctp_cb() is only for the initial ingress code; we should see ->magic set
179889b7da2SJeremy Kerr  * at all times after this.
180889b7da2SJeremy Kerr  */
181889b7da2SJeremy Kerr static inline struct mctp_skb_cb *__mctp_cb(struct sk_buff *skb)
182889b7da2SJeremy Kerr {
183889b7da2SJeremy Kerr 	struct mctp_skb_cb *cb = (void *)skb->cb;
184889b7da2SJeremy Kerr 
185889b7da2SJeremy Kerr 	cb->magic = 0x4d435450;
186889b7da2SJeremy Kerr 	return cb;
187889b7da2SJeremy Kerr }
188889b7da2SJeremy Kerr 
189889b7da2SJeremy Kerr static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb)
190889b7da2SJeremy Kerr {
191889b7da2SJeremy Kerr 	struct mctp_skb_cb *cb = (void *)skb->cb;
192889b7da2SJeremy Kerr 
19399ce45d5SJeremy Kerr 	BUILD_BUG_ON(sizeof(struct mctp_skb_cb) > sizeof(skb->cb));
194889b7da2SJeremy Kerr 	WARN_ON(cb->magic != 0x4d435450);
195889b7da2SJeremy Kerr 	return (void *)(skb->cb);
196889b7da2SJeremy Kerr }
197889b7da2SJeremy Kerr 
19878476d31SJeremy Kerr /* If CONFIG_MCTP_FLOWS, we may add one of these as a SKB extension,
19978476d31SJeremy Kerr  * indicating the flow to the device driver.
20078476d31SJeremy Kerr  */
20178476d31SJeremy Kerr struct mctp_flow {
20278476d31SJeremy Kerr 	struct mctp_sk_key *key;
20378476d31SJeremy Kerr };
20478476d31SJeremy Kerr 
205889b7da2SJeremy Kerr /* Route definition.
206889b7da2SJeremy Kerr  *
207889b7da2SJeremy Kerr  * These are held in the pernet->mctp.routes list, with RCU protection for
208889b7da2SJeremy Kerr  * removed routes. We hold a reference to the netdev; routes need to be
209889b7da2SJeremy Kerr  * dropped on NETDEV_UNREGISTER events.
210889b7da2SJeremy Kerr  *
211889b7da2SJeremy Kerr  * Updates to the route table are performed under rtnl; all reads under RCU,
212889b7da2SJeremy Kerr  * so routes cannot be referenced over a RCU grace period. Specifically: A
21399ce45d5SJeremy Kerr  * caller cannot block between mctp_route_lookup and mctp_route_release()
214889b7da2SJeremy Kerr  */
215889b7da2SJeremy Kerr struct mctp_route {
216889b7da2SJeremy Kerr 	mctp_eid_t		min, max;
217889b7da2SJeremy Kerr 
218889b7da2SJeremy Kerr 	struct mctp_dev		*dev;
219889b7da2SJeremy Kerr 	unsigned int		mtu;
22083f0a0b7SJeremy Kerr 	unsigned char		type;
221889b7da2SJeremy Kerr 	int			(*output)(struct mctp_route *route,
222889b7da2SJeremy Kerr 					  struct sk_buff *skb);
223889b7da2SJeremy Kerr 
224889b7da2SJeremy Kerr 	struct list_head	list;
225889b7da2SJeremy Kerr 	refcount_t		refs;
226889b7da2SJeremy Kerr 	struct rcu_head		rcu;
227889b7da2SJeremy Kerr };
228889b7da2SJeremy Kerr 
229889b7da2SJeremy Kerr /* route interfaces */
230889b7da2SJeremy Kerr struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet,
231889b7da2SJeremy Kerr 				     mctp_eid_t daddr);
232889b7da2SJeremy Kerr 
233889b7da2SJeremy Kerr int mctp_local_output(struct sock *sk, struct mctp_route *rt,
234889b7da2SJeremy Kerr 		      struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag);
235889b7da2SJeremy Kerr 
23673c61845SJeremy Kerr void mctp_key_unref(struct mctp_sk_key *key);
23773c61845SJeremy Kerr 
238889b7da2SJeremy Kerr /* routing <--> device interface */
23906d2f4c5SMatt Johnston unsigned int mctp_default_net(struct net *net);
24006d2f4c5SMatt Johnston int mctp_default_net_set(struct net *net, unsigned int index);
241889b7da2SJeremy Kerr int mctp_route_add_local(struct mctp_dev *mdev, mctp_eid_t addr);
242889b7da2SJeremy Kerr int mctp_route_remove_local(struct mctp_dev *mdev, mctp_eid_t addr);
243889b7da2SJeremy Kerr void mctp_route_remove_dev(struct mctp_dev *mdev);
244889b7da2SJeremy Kerr 
2454d8b9319SMatt Johnston /* neighbour definitions */
2464d8b9319SMatt Johnston enum mctp_neigh_source {
2474d8b9319SMatt Johnston 	MCTP_NEIGH_STATIC,
2484d8b9319SMatt Johnston 	MCTP_NEIGH_DISCOVER,
2494d8b9319SMatt Johnston };
2504d8b9319SMatt Johnston 
2514d8b9319SMatt Johnston struct mctp_neigh {
2524d8b9319SMatt Johnston 	struct mctp_dev		*dev;
2534d8b9319SMatt Johnston 	mctp_eid_t		eid;
2544d8b9319SMatt Johnston 	enum mctp_neigh_source	source;
2554d8b9319SMatt Johnston 
2564d8b9319SMatt Johnston 	unsigned char		ha[MAX_ADDR_LEN];
2574d8b9319SMatt Johnston 
2584d8b9319SMatt Johnston 	struct list_head	list;
2594d8b9319SMatt Johnston 	struct rcu_head		rcu;
2604d8b9319SMatt Johnston };
2614d8b9319SMatt Johnston 
2624d8b9319SMatt Johnston int mctp_neigh_init(void);
2634d8b9319SMatt Johnston void mctp_neigh_exit(void);
2644d8b9319SMatt Johnston 
2654d8b9319SMatt Johnston // ret_hwaddr may be NULL, otherwise must have space for MAX_ADDR_LEN
2664d8b9319SMatt Johnston int mctp_neigh_lookup(struct mctp_dev *dev, mctp_eid_t eid,
2674d8b9319SMatt Johnston 		      void *ret_hwaddr);
2684d8b9319SMatt Johnston void mctp_neigh_remove_dev(struct mctp_dev *mdev);
2694d8b9319SMatt Johnston 
270889b7da2SJeremy Kerr int mctp_routes_init(void);
271889b7da2SJeremy Kerr void mctp_routes_exit(void);
272889b7da2SJeremy Kerr 
273583be982SJeremy Kerr void mctp_device_init(void);
274583be982SJeremy Kerr void mctp_device_exit(void);
275583be982SJeremy Kerr 
2762c8e2e9aSJeremy Kerr #endif /* __NET_MCTP_H */
277