xref: /openbmc/linux/include/net/mctp.h (revision 833ef3b91de692ef33b800bca6b1569c39dece74)
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>
15*833ef3b9SJeremy 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 
50*833ef3b9SJeremy Kerr /* socket implementation */
51*833ef3b9SJeremy Kerr struct mctp_sock {
52*833ef3b9SJeremy Kerr 	struct sock	sk;
53*833ef3b9SJeremy Kerr 
54*833ef3b9SJeremy Kerr 	/* bind() params */
55*833ef3b9SJeremy Kerr 	int		bind_net;
56*833ef3b9SJeremy Kerr 	mctp_eid_t	bind_addr;
57*833ef3b9SJeremy Kerr 	__u8		bind_type;
58*833ef3b9SJeremy Kerr 
59*833ef3b9SJeremy Kerr 	/* list of mctp_sk_key, for incoming tag lookup. updates protected
60*833ef3b9SJeremy Kerr 	 * by sk->net->keys_lock
61*833ef3b9SJeremy Kerr 	 */
62*833ef3b9SJeremy Kerr 	struct hlist_head keys;
63*833ef3b9SJeremy Kerr };
64*833ef3b9SJeremy Kerr 
65*833ef3b9SJeremy Kerr /* Key for matching incoming packets to sockets or reassembly contexts.
66*833ef3b9SJeremy Kerr  * Packets are matched on (src,dest,tag).
67*833ef3b9SJeremy Kerr  *
68*833ef3b9SJeremy Kerr  * Lifetime requirements:
69*833ef3b9SJeremy Kerr  *
70*833ef3b9SJeremy Kerr  *  - keys are free()ed via RCU
71*833ef3b9SJeremy Kerr  *
72*833ef3b9SJeremy Kerr  *  - a mctp_sk_key contains a reference to a struct sock; this is valid
73*833ef3b9SJeremy Kerr  *    for the life of the key. On sock destruction (through unhash), the key is
74*833ef3b9SJeremy Kerr  *    removed from lists (see below), and will not be observable after a RCU
75*833ef3b9SJeremy Kerr  *    grace period.
76*833ef3b9SJeremy Kerr  *
77*833ef3b9SJeremy Kerr  *    any RX occurring within that grace period may still queue to the socket,
78*833ef3b9SJeremy Kerr  *    but will hit the SOCK_DEAD case before the socket is freed.
79*833ef3b9SJeremy Kerr  *
80*833ef3b9SJeremy Kerr  * - these mctp_sk_keys appear on two lists:
81*833ef3b9SJeremy Kerr  *     1) the struct mctp_sock->keys list
82*833ef3b9SJeremy Kerr  *     2) the struct netns_mctp->keys list
83*833ef3b9SJeremy Kerr  *
84*833ef3b9SJeremy Kerr  *        updates to either list are performed under the netns_mctp->keys
85*833ef3b9SJeremy Kerr  *        lock.
86*833ef3b9SJeremy Kerr  *
87*833ef3b9SJeremy Kerr  * - there is a single destruction path for a mctp_sk_key - through socket
88*833ef3b9SJeremy Kerr  *   unhash (see mctp_sk_unhash). This performs the list removal under
89*833ef3b9SJeremy Kerr  *   keys_lock.
90*833ef3b9SJeremy Kerr  */
91*833ef3b9SJeremy Kerr struct mctp_sk_key {
92*833ef3b9SJeremy Kerr 	mctp_eid_t	peer_addr;
93*833ef3b9SJeremy Kerr 	mctp_eid_t	local_addr;
94*833ef3b9SJeremy Kerr 	__u8		tag; /* incoming tag match; invert TO for local */
95*833ef3b9SJeremy Kerr 
96*833ef3b9SJeremy Kerr 	/* we hold a ref to sk when set */
97*833ef3b9SJeremy Kerr 	struct sock	*sk;
98*833ef3b9SJeremy Kerr 
99*833ef3b9SJeremy Kerr 	/* routing lookup list */
100*833ef3b9SJeremy Kerr 	struct hlist_node hlist;
101*833ef3b9SJeremy Kerr 
102*833ef3b9SJeremy Kerr 	/* per-socket list */
103*833ef3b9SJeremy Kerr 	struct hlist_node sklist;
104*833ef3b9SJeremy Kerr 
105*833ef3b9SJeremy Kerr 	struct rcu_head	rcu;
106*833ef3b9SJeremy Kerr };
107*833ef3b9SJeremy Kerr 
108889b7da2SJeremy Kerr struct mctp_skb_cb {
109889b7da2SJeremy Kerr 	unsigned int	magic;
110889b7da2SJeremy Kerr 	unsigned int	net;
111889b7da2SJeremy Kerr 	mctp_eid_t	src;
112889b7da2SJeremy Kerr };
113889b7da2SJeremy Kerr 
114889b7da2SJeremy Kerr /* skb control-block accessors with a little extra debugging for initial
115889b7da2SJeremy Kerr  * development.
116889b7da2SJeremy Kerr  *
117889b7da2SJeremy Kerr  * TODO: remove checks & mctp_skb_cb->magic; replace callers of __mctp_cb
118889b7da2SJeremy Kerr  * with mctp_cb().
119889b7da2SJeremy Kerr  *
120889b7da2SJeremy Kerr  * __mctp_cb() is only for the initial ingress code; we should see ->magic set
121889b7da2SJeremy Kerr  * at all times after this.
122889b7da2SJeremy Kerr  */
123889b7da2SJeremy Kerr static inline struct mctp_skb_cb *__mctp_cb(struct sk_buff *skb)
124889b7da2SJeremy Kerr {
125889b7da2SJeremy Kerr 	struct mctp_skb_cb *cb = (void *)skb->cb;
126889b7da2SJeremy Kerr 
127889b7da2SJeremy Kerr 	cb->magic = 0x4d435450;
128889b7da2SJeremy Kerr 	return cb;
129889b7da2SJeremy Kerr }
130889b7da2SJeremy Kerr 
131889b7da2SJeremy Kerr static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb)
132889b7da2SJeremy Kerr {
133889b7da2SJeremy Kerr 	struct mctp_skb_cb *cb = (void *)skb->cb;
134889b7da2SJeremy Kerr 
135889b7da2SJeremy Kerr 	WARN_ON(cb->magic != 0x4d435450);
136889b7da2SJeremy Kerr 	return (void *)(skb->cb);
137889b7da2SJeremy Kerr }
138889b7da2SJeremy Kerr 
139889b7da2SJeremy Kerr /* Route definition.
140889b7da2SJeremy Kerr  *
141889b7da2SJeremy Kerr  * These are held in the pernet->mctp.routes list, with RCU protection for
142889b7da2SJeremy Kerr  * removed routes. We hold a reference to the netdev; routes need to be
143889b7da2SJeremy Kerr  * dropped on NETDEV_UNREGISTER events.
144889b7da2SJeremy Kerr  *
145889b7da2SJeremy Kerr  * Updates to the route table are performed under rtnl; all reads under RCU,
146889b7da2SJeremy Kerr  * so routes cannot be referenced over a RCU grace period. Specifically: A
147889b7da2SJeremy Kerr  * caller cannot block between mctp_route_lookup and passing the route to
148889b7da2SJeremy Kerr  * mctp_do_route.
149889b7da2SJeremy Kerr  */
150889b7da2SJeremy Kerr struct mctp_route {
151889b7da2SJeremy Kerr 	mctp_eid_t		min, max;
152889b7da2SJeremy Kerr 
153889b7da2SJeremy Kerr 	struct mctp_dev		*dev;
154889b7da2SJeremy Kerr 	unsigned int		mtu;
155889b7da2SJeremy Kerr 	int			(*output)(struct mctp_route *route,
156889b7da2SJeremy Kerr 					  struct sk_buff *skb);
157889b7da2SJeremy Kerr 
158889b7da2SJeremy Kerr 	struct list_head	list;
159889b7da2SJeremy Kerr 	refcount_t		refs;
160889b7da2SJeremy Kerr 	struct rcu_head		rcu;
161889b7da2SJeremy Kerr };
162889b7da2SJeremy Kerr 
163889b7da2SJeremy Kerr /* route interfaces */
164889b7da2SJeremy Kerr struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet,
165889b7da2SJeremy Kerr 				     mctp_eid_t daddr);
166889b7da2SJeremy Kerr 
167889b7da2SJeremy Kerr int mctp_do_route(struct mctp_route *rt, struct sk_buff *skb);
168889b7da2SJeremy Kerr 
169889b7da2SJeremy Kerr int mctp_local_output(struct sock *sk, struct mctp_route *rt,
170889b7da2SJeremy Kerr 		      struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag);
171889b7da2SJeremy Kerr 
172889b7da2SJeremy Kerr /* routing <--> device interface */
17306d2f4c5SMatt Johnston unsigned int mctp_default_net(struct net *net);
17406d2f4c5SMatt Johnston int mctp_default_net_set(struct net *net, unsigned int index);
175889b7da2SJeremy Kerr int mctp_route_add_local(struct mctp_dev *mdev, mctp_eid_t addr);
176889b7da2SJeremy Kerr int mctp_route_remove_local(struct mctp_dev *mdev, mctp_eid_t addr);
177889b7da2SJeremy Kerr void mctp_route_remove_dev(struct mctp_dev *mdev);
178889b7da2SJeremy Kerr 
1794d8b9319SMatt Johnston /* neighbour definitions */
1804d8b9319SMatt Johnston enum mctp_neigh_source {
1814d8b9319SMatt Johnston 	MCTP_NEIGH_STATIC,
1824d8b9319SMatt Johnston 	MCTP_NEIGH_DISCOVER,
1834d8b9319SMatt Johnston };
1844d8b9319SMatt Johnston 
1854d8b9319SMatt Johnston struct mctp_neigh {
1864d8b9319SMatt Johnston 	struct mctp_dev		*dev;
1874d8b9319SMatt Johnston 	mctp_eid_t		eid;
1884d8b9319SMatt Johnston 	enum mctp_neigh_source	source;
1894d8b9319SMatt Johnston 
1904d8b9319SMatt Johnston 	unsigned char		ha[MAX_ADDR_LEN];
1914d8b9319SMatt Johnston 
1924d8b9319SMatt Johnston 	struct list_head	list;
1934d8b9319SMatt Johnston 	struct rcu_head		rcu;
1944d8b9319SMatt Johnston };
1954d8b9319SMatt Johnston 
1964d8b9319SMatt Johnston int mctp_neigh_init(void);
1974d8b9319SMatt Johnston void mctp_neigh_exit(void);
1984d8b9319SMatt Johnston 
1994d8b9319SMatt Johnston // ret_hwaddr may be NULL, otherwise must have space for MAX_ADDR_LEN
2004d8b9319SMatt Johnston int mctp_neigh_lookup(struct mctp_dev *dev, mctp_eid_t eid,
2014d8b9319SMatt Johnston 		      void *ret_hwaddr);
2024d8b9319SMatt Johnston void mctp_neigh_remove_dev(struct mctp_dev *mdev);
2034d8b9319SMatt Johnston 
204889b7da2SJeremy Kerr int mctp_routes_init(void);
205889b7da2SJeremy Kerr void mctp_routes_exit(void);
206889b7da2SJeremy Kerr 
207583be982SJeremy Kerr void mctp_device_init(void);
208583be982SJeremy Kerr void mctp_device_exit(void);
209583be982SJeremy Kerr 
2102c8e2e9aSJeremy Kerr #endif /* __NET_MCTP_H */
211