xref: /openbmc/linux/include/net/mctp.h (revision 4a992bbd365094730a31bae1e12a6ca695336d57)
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>
14889b7da2SJeremy Kerr #include <net/net_namespace.h>
15833ef3b9SJeremy Kerr #include <net/sock.h>
162c8e2e9aSJeremy Kerr 
172c8e2e9aSJeremy Kerr /* MCTP packet definitions */
182c8e2e9aSJeremy Kerr struct mctp_hdr {
192c8e2e9aSJeremy Kerr 	u8	ver;
202c8e2e9aSJeremy Kerr 	u8	dest;
212c8e2e9aSJeremy Kerr 	u8	src;
222c8e2e9aSJeremy Kerr 	u8	flags_seq_tag;
232c8e2e9aSJeremy Kerr };
242c8e2e9aSJeremy Kerr 
252c8e2e9aSJeremy Kerr #define MCTP_VER_MIN	1
262c8e2e9aSJeremy Kerr #define MCTP_VER_MAX	1
272c8e2e9aSJeremy Kerr 
282c8e2e9aSJeremy Kerr /* Definitions for flags_seq_tag field */
292c8e2e9aSJeremy Kerr #define MCTP_HDR_FLAG_SOM	BIT(7)
302c8e2e9aSJeremy Kerr #define MCTP_HDR_FLAG_EOM	BIT(6)
312c8e2e9aSJeremy Kerr #define MCTP_HDR_FLAG_TO	BIT(3)
322c8e2e9aSJeremy Kerr #define MCTP_HDR_FLAGS		GENMASK(5, 3)
332c8e2e9aSJeremy Kerr #define MCTP_HDR_SEQ_SHIFT	4
342c8e2e9aSJeremy Kerr #define MCTP_HDR_SEQ_MASK	GENMASK(1, 0)
352c8e2e9aSJeremy Kerr #define MCTP_HDR_TAG_SHIFT	0
362c8e2e9aSJeremy Kerr #define MCTP_HDR_TAG_MASK	GENMASK(2, 0)
372c8e2e9aSJeremy Kerr 
38889b7da2SJeremy Kerr #define MCTP_HEADER_MAXLEN	4
39889b7da2SJeremy Kerr 
40583be982SJeremy Kerr static inline bool mctp_address_ok(mctp_eid_t eid)
41583be982SJeremy Kerr {
42583be982SJeremy Kerr 	return eid >= 8 && eid < 255;
43583be982SJeremy Kerr }
44583be982SJeremy Kerr 
45583be982SJeremy Kerr static inline struct mctp_hdr *mctp_hdr(struct sk_buff *skb)
46583be982SJeremy Kerr {
47583be982SJeremy Kerr 	return (struct mctp_hdr *)skb_network_header(skb);
48583be982SJeremy Kerr }
49583be982SJeremy Kerr 
50833ef3b9SJeremy Kerr /* socket implementation */
51833ef3b9SJeremy Kerr struct mctp_sock {
52833ef3b9SJeremy Kerr 	struct sock	sk;
53833ef3b9SJeremy Kerr 
54833ef3b9SJeremy Kerr 	/* bind() params */
55833ef3b9SJeremy Kerr 	int		bind_net;
56833ef3b9SJeremy Kerr 	mctp_eid_t	bind_addr;
57833ef3b9SJeremy Kerr 	__u8		bind_type;
58833ef3b9SJeremy Kerr 
59833ef3b9SJeremy Kerr 	/* list of mctp_sk_key, for incoming tag lookup. updates protected
60833ef3b9SJeremy Kerr 	 * by sk->net->keys_lock
61833ef3b9SJeremy Kerr 	 */
62833ef3b9SJeremy Kerr 	struct hlist_head keys;
63833ef3b9SJeremy Kerr };
64833ef3b9SJeremy Kerr 
65833ef3b9SJeremy Kerr /* Key for matching incoming packets to sockets or reassembly contexts.
66833ef3b9SJeremy Kerr  * Packets are matched on (src,dest,tag).
67833ef3b9SJeremy Kerr  *
68833ef3b9SJeremy Kerr  * Lifetime requirements:
69833ef3b9SJeremy Kerr  *
70833ef3b9SJeremy Kerr  *  - keys are free()ed via RCU
71833ef3b9SJeremy Kerr  *
72833ef3b9SJeremy Kerr  *  - a mctp_sk_key contains a reference to a struct sock; this is valid
73833ef3b9SJeremy Kerr  *    for the life of the key. On sock destruction (through unhash), the key is
74833ef3b9SJeremy Kerr  *    removed from lists (see below), and will not be observable after a RCU
75833ef3b9SJeremy Kerr  *    grace period.
76833ef3b9SJeremy Kerr  *
77833ef3b9SJeremy Kerr  *    any RX occurring within that grace period may still queue to the socket,
78833ef3b9SJeremy Kerr  *    but will hit the SOCK_DEAD case before the socket is freed.
79833ef3b9SJeremy Kerr  *
80833ef3b9SJeremy Kerr  * - these mctp_sk_keys appear on two lists:
81833ef3b9SJeremy Kerr  *     1) the struct mctp_sock->keys list
82833ef3b9SJeremy Kerr  *     2) the struct netns_mctp->keys list
83833ef3b9SJeremy Kerr  *
84833ef3b9SJeremy Kerr  *        updates to either list are performed under the netns_mctp->keys
85833ef3b9SJeremy Kerr  *        lock.
86833ef3b9SJeremy Kerr  *
87*4a992bbdSJeremy Kerr  * - a key may have a sk_buff attached as part of an in-progress message
88*4a992bbdSJeremy Kerr  *   reassembly (->reasm_head). The reassembly context is protected by
89*4a992bbdSJeremy Kerr  *   reasm_lock, which may be acquired with the keys lock (above) held, if
90*4a992bbdSJeremy Kerr  *   necessary. Consequently, keys lock *cannot* be acquired with the
91*4a992bbdSJeremy Kerr  *   reasm_lock held.
92*4a992bbdSJeremy Kerr  *
93*4a992bbdSJeremy Kerr  * - there are two destruction paths for a mctp_sk_key:
94*4a992bbdSJeremy Kerr  *
95*4a992bbdSJeremy Kerr  *    - through socket unhash (see mctp_sk_unhash). This performs the list
96*4a992bbdSJeremy Kerr  *      removal under keys_lock.
97*4a992bbdSJeremy Kerr  *
98*4a992bbdSJeremy Kerr  *    - where a key is established to receive a reply message: after receiving
99*4a992bbdSJeremy Kerr  *      the (complete) reply, or during reassembly errors. Here, we clean up
100*4a992bbdSJeremy Kerr  *      the reassembly context (marking reasm_dead, to prevent another from
101*4a992bbdSJeremy Kerr  *      starting), and remove the socket from the netns & socket lists.
102833ef3b9SJeremy Kerr  */
103833ef3b9SJeremy Kerr struct mctp_sk_key {
104833ef3b9SJeremy Kerr 	mctp_eid_t	peer_addr;
105833ef3b9SJeremy Kerr 	mctp_eid_t	local_addr;
106833ef3b9SJeremy Kerr 	__u8		tag; /* incoming tag match; invert TO for local */
107833ef3b9SJeremy Kerr 
108833ef3b9SJeremy Kerr 	/* we hold a ref to sk when set */
109833ef3b9SJeremy Kerr 	struct sock	*sk;
110833ef3b9SJeremy Kerr 
111833ef3b9SJeremy Kerr 	/* routing lookup list */
112833ef3b9SJeremy Kerr 	struct hlist_node hlist;
113833ef3b9SJeremy Kerr 
114833ef3b9SJeremy Kerr 	/* per-socket list */
115833ef3b9SJeremy Kerr 	struct hlist_node sklist;
116833ef3b9SJeremy Kerr 
117*4a992bbdSJeremy Kerr 	/* incoming fragment reassembly context */
118*4a992bbdSJeremy Kerr 	spinlock_t	reasm_lock;
119*4a992bbdSJeremy Kerr 	struct sk_buff	*reasm_head;
120*4a992bbdSJeremy Kerr 	struct sk_buff	**reasm_tailp;
121*4a992bbdSJeremy Kerr 	bool		reasm_dead;
122*4a992bbdSJeremy Kerr 	u8		last_seq;
123*4a992bbdSJeremy Kerr 
124833ef3b9SJeremy Kerr 	struct rcu_head	rcu;
125833ef3b9SJeremy Kerr };
126833ef3b9SJeremy Kerr 
127889b7da2SJeremy Kerr struct mctp_skb_cb {
128889b7da2SJeremy Kerr 	unsigned int	magic;
129889b7da2SJeremy Kerr 	unsigned int	net;
130889b7da2SJeremy Kerr 	mctp_eid_t	src;
131889b7da2SJeremy Kerr };
132889b7da2SJeremy Kerr 
133889b7da2SJeremy Kerr /* skb control-block accessors with a little extra debugging for initial
134889b7da2SJeremy Kerr  * development.
135889b7da2SJeremy Kerr  *
136889b7da2SJeremy Kerr  * TODO: remove checks & mctp_skb_cb->magic; replace callers of __mctp_cb
137889b7da2SJeremy Kerr  * with mctp_cb().
138889b7da2SJeremy Kerr  *
139889b7da2SJeremy Kerr  * __mctp_cb() is only for the initial ingress code; we should see ->magic set
140889b7da2SJeremy Kerr  * at all times after this.
141889b7da2SJeremy Kerr  */
142889b7da2SJeremy Kerr static inline struct mctp_skb_cb *__mctp_cb(struct sk_buff *skb)
143889b7da2SJeremy Kerr {
144889b7da2SJeremy Kerr 	struct mctp_skb_cb *cb = (void *)skb->cb;
145889b7da2SJeremy Kerr 
146889b7da2SJeremy Kerr 	cb->magic = 0x4d435450;
147889b7da2SJeremy Kerr 	return cb;
148889b7da2SJeremy Kerr }
149889b7da2SJeremy Kerr 
150889b7da2SJeremy Kerr static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb)
151889b7da2SJeremy Kerr {
152889b7da2SJeremy Kerr 	struct mctp_skb_cb *cb = (void *)skb->cb;
153889b7da2SJeremy Kerr 
154889b7da2SJeremy Kerr 	WARN_ON(cb->magic != 0x4d435450);
155889b7da2SJeremy Kerr 	return (void *)(skb->cb);
156889b7da2SJeremy Kerr }
157889b7da2SJeremy Kerr 
158889b7da2SJeremy Kerr /* Route definition.
159889b7da2SJeremy Kerr  *
160889b7da2SJeremy Kerr  * These are held in the pernet->mctp.routes list, with RCU protection for
161889b7da2SJeremy Kerr  * removed routes. We hold a reference to the netdev; routes need to be
162889b7da2SJeremy Kerr  * dropped on NETDEV_UNREGISTER events.
163889b7da2SJeremy Kerr  *
164889b7da2SJeremy Kerr  * Updates to the route table are performed under rtnl; all reads under RCU,
165889b7da2SJeremy Kerr  * so routes cannot be referenced over a RCU grace period. Specifically: A
166889b7da2SJeremy Kerr  * caller cannot block between mctp_route_lookup and passing the route to
167889b7da2SJeremy Kerr  * mctp_do_route.
168889b7da2SJeremy Kerr  */
169889b7da2SJeremy Kerr struct mctp_route {
170889b7da2SJeremy Kerr 	mctp_eid_t		min, max;
171889b7da2SJeremy Kerr 
172889b7da2SJeremy Kerr 	struct mctp_dev		*dev;
173889b7da2SJeremy Kerr 	unsigned int		mtu;
174889b7da2SJeremy Kerr 	int			(*output)(struct mctp_route *route,
175889b7da2SJeremy Kerr 					  struct sk_buff *skb);
176889b7da2SJeremy Kerr 
177889b7da2SJeremy Kerr 	struct list_head	list;
178889b7da2SJeremy Kerr 	refcount_t		refs;
179889b7da2SJeremy Kerr 	struct rcu_head		rcu;
180889b7da2SJeremy Kerr };
181889b7da2SJeremy Kerr 
182889b7da2SJeremy Kerr /* route interfaces */
183889b7da2SJeremy Kerr struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet,
184889b7da2SJeremy Kerr 				     mctp_eid_t daddr);
185889b7da2SJeremy Kerr 
186889b7da2SJeremy Kerr int mctp_do_route(struct mctp_route *rt, struct sk_buff *skb);
187889b7da2SJeremy Kerr 
188889b7da2SJeremy Kerr int mctp_local_output(struct sock *sk, struct mctp_route *rt,
189889b7da2SJeremy Kerr 		      struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag);
190889b7da2SJeremy Kerr 
191889b7da2SJeremy Kerr /* routing <--> device interface */
19206d2f4c5SMatt Johnston unsigned int mctp_default_net(struct net *net);
19306d2f4c5SMatt Johnston int mctp_default_net_set(struct net *net, unsigned int index);
194889b7da2SJeremy Kerr int mctp_route_add_local(struct mctp_dev *mdev, mctp_eid_t addr);
195889b7da2SJeremy Kerr int mctp_route_remove_local(struct mctp_dev *mdev, mctp_eid_t addr);
196889b7da2SJeremy Kerr void mctp_route_remove_dev(struct mctp_dev *mdev);
197889b7da2SJeremy Kerr 
1984d8b9319SMatt Johnston /* neighbour definitions */
1994d8b9319SMatt Johnston enum mctp_neigh_source {
2004d8b9319SMatt Johnston 	MCTP_NEIGH_STATIC,
2014d8b9319SMatt Johnston 	MCTP_NEIGH_DISCOVER,
2024d8b9319SMatt Johnston };
2034d8b9319SMatt Johnston 
2044d8b9319SMatt Johnston struct mctp_neigh {
2054d8b9319SMatt Johnston 	struct mctp_dev		*dev;
2064d8b9319SMatt Johnston 	mctp_eid_t		eid;
2074d8b9319SMatt Johnston 	enum mctp_neigh_source	source;
2084d8b9319SMatt Johnston 
2094d8b9319SMatt Johnston 	unsigned char		ha[MAX_ADDR_LEN];
2104d8b9319SMatt Johnston 
2114d8b9319SMatt Johnston 	struct list_head	list;
2124d8b9319SMatt Johnston 	struct rcu_head		rcu;
2134d8b9319SMatt Johnston };
2144d8b9319SMatt Johnston 
2154d8b9319SMatt Johnston int mctp_neigh_init(void);
2164d8b9319SMatt Johnston void mctp_neigh_exit(void);
2174d8b9319SMatt Johnston 
2184d8b9319SMatt Johnston // ret_hwaddr may be NULL, otherwise must have space for MAX_ADDR_LEN
2194d8b9319SMatt Johnston int mctp_neigh_lookup(struct mctp_dev *dev, mctp_eid_t eid,
2204d8b9319SMatt Johnston 		      void *ret_hwaddr);
2214d8b9319SMatt Johnston void mctp_neigh_remove_dev(struct mctp_dev *mdev);
2224d8b9319SMatt Johnston 
223889b7da2SJeremy Kerr int mctp_routes_init(void);
224889b7da2SJeremy Kerr void mctp_routes_exit(void);
225889b7da2SJeremy Kerr 
226583be982SJeremy Kerr void mctp_device_init(void);
227583be982SJeremy Kerr void mctp_device_exit(void);
228583be982SJeremy Kerr 
2292c8e2e9aSJeremy Kerr #endif /* __NET_MCTP_H */
230