| 1 |
|
| 2 | |
| 3 | * Management Component Transport Protocol (MCTP)
|
| 4 | *
|
| 5 | * Copyright (c) 2021 Code Construct
|
| 6 | * Copyright (c) 2021 Google
|
| 7 |
|
| 8 |
|
| 9 | #ifndef __NET_MCTP_H
|
| 10 | #define __NET_MCTP_H
|
| 11 |
|
| 12 | #include <linux/bits.h>
|
| 13 | #include <linux/mctp.h>
|
| 14 | #include <linux/netdevice.h>
|
| 15 | #include <net/net_namespace.h>
|
| 16 | #include <net/sock.h>
|
| 17 |
|
| 18 |
|
| 19 | struct mctp_hdr {
|
| 20 | u8 ver;
|
| 21 | u8 dest;
|
| 22 | u8 src;
|
| 23 | u8 flags_seq_tag;
|
| 24 | };
|
| 25 |
|
| 26 | #define MCTP_VER_MIN 1
|
| 27 | #define MCTP_VER_MAX 1
|
| 28 |
|
| 29 |
|
| 30 | #define MCTP_HDR_VER_MASK GENMASK(3, 0)
|
| 31 |
|
| 32 |
|
| 33 | #define MCTP_HDR_FLAG_SOM BIT(7)
|
| 34 | #define MCTP_HDR_FLAG_EOM BIT(6)
|
| 35 | #define MCTP_HDR_FLAG_TO BIT(3)
|
| 36 | #define MCTP_HDR_FLAGS GENMASK(5, 3)
|
| 37 | #define MCTP_HDR_SEQ_SHIFT 4
|
| 38 | #define MCTP_HDR_SEQ_MASK GENMASK(1, 0)
|
| 39 | #define MCTP_HDR_TAG_SHIFT 0
|
| 40 | #define MCTP_HDR_TAG_MASK GENMASK(2, 0)
|
| 41 |
|
| 42 | #define MCTP_INITIAL_DEFAULT_NET 1
|
| 43 |
|
| 44 | static inline bool mctp_address_unicast(mctp_eid_t eid)
|
| 45 | {
|
| 46 | return eid >= 8 && eid < 255;
|
| 47 | }
|
| 48 |
|
| 49 | static inline bool mctp_address_broadcast(mctp_eid_t eid)
|
| 50 | {
|
| 51 | return eid == 255;
|
| 52 | }
|
| 53 |
|
| 54 | static inline bool mctp_address_null(mctp_eid_t eid)
|
| 55 | {
|
| 56 | return eid == 0;
|
| 57 | }
|
| 58 |
|
| 59 | static inline bool mctp_address_matches(mctp_eid_t match, mctp_eid_t eid)
|
| 60 | {
|
| 61 | return match == eid || match == MCTP_ADDR_ANY;
|
| 62 | }
|
| 63 |
|
| 64 | static inline struct mctp_hdr *mctp_hdr(struct sk_buff *skb)
|
| 65 | {
|
| 66 | return (struct mctp_hdr *)skb_network_header(skb);
|
| 67 | }
|
| 68 |
|
| 69 |
|
| 70 | struct mctp_sock {
|
| 71 | struct sock sk;
|
| 72 |
|
| 73 |
|
| 74 | unsigned int bind_net;
|
| 75 | mctp_eid_t bind_local_addr;
|
| 76 | mctp_eid_t bind_peer_addr;
|
| 77 | unsigned int bind_peer_net;
|
| 78 | bool bind_peer_set;
|
| 79 | __u8 bind_type;
|
| 80 |
|
| 81 |
|
| 82 | bool addr_ext;
|
| 83 |
|
| 84 | |
| 85 | * by sk->net->keys_lock
|
| 86 |
|
| 87 | struct hlist_head keys;
|
| 88 |
|
| 89 | |
| 90 | * tag, and any netdev state for a request/response pairing
|
| 91 |
|
| 92 | struct timer_list key_expiry;
|
| 93 | };
|
| 94 |
|
| 95 | |
| 96 | * Packets are matched on (peer EID, local EID, tag).
|
| 97 | *
|
| 98 | * Lifetime / locking requirements:
|
| 99 | *
|
| 100 | * - individual key data (ie, the struct itself) is protected by key->lock;
|
| 101 | * changes must be made with that lock held.
|
| 102 | *
|
| 103 | * - the lookup fields: peer_addr, local_addr and tag are set before the
|
| 104 | * key is added to lookup lists, and never updated.
|
| 105 | *
|
| 106 | * - A ref to the key must be held (throuh key->refs) if a pointer to the
|
| 107 | * key is to be accessed after key->lock is released.
|
| 108 | *
|
| 109 | * - a mctp_sk_key contains a reference to a struct sock; this is valid
|
| 110 | * for the life of the key. On sock destruction (through unhash), the key is
|
| 111 | * removed from lists (see below), and marked invalid.
|
| 112 | *
|
| 113 | * - these mctp_sk_keys appear on two lists:
|
| 114 | * 1) the struct mctp_sock->keys list
|
| 115 | * 2) the struct netns_mctp->keys list
|
| 116 | *
|
| 117 | * presences on these lists requires a (single) refcount to be held; both
|
| 118 | * lists are updated as a single operation.
|
| 119 | *
|
| 120 | * Updates and lookups in either list are performed under the
|
| 121 | * netns_mctp->keys lock. Lookup functions will need to lock the key and
|
| 122 | * take a reference before unlocking the keys_lock. Consequently, the list's
|
| 123 | * keys_lock *cannot* be acquired with the individual key->lock held.
|
| 124 | *
|
| 125 | * - a key may have a sk_buff attached as part of an in-progress message
|
| 126 | * reassembly (->reasm_head). The reasm data is protected by the individual
|
| 127 | * key->lock.
|
| 128 | *
|
| 129 | * - there are two destruction paths for a mctp_sk_key:
|
| 130 | *
|
| 131 | * - through socket unhash (see mctp_sk_unhash). This performs the list
|
| 132 | * removal under keys_lock.
|
| 133 | *
|
| 134 | * - where a key is established to receive a reply message: after receiving
|
| 135 | * the (complete) reply, or during reassembly errors. Here, we clean up
|
| 136 | * the reassembly context (marking reasm_dead, to prevent another from
|
| 137 | * starting), and remove the socket from the netns & socket lists.
|
| 138 | *
|
| 139 | * - through an expiry timeout, on a per-socket timer
|
| 140 |
|
| 141 | struct mctp_sk_key {
|
| 142 | unsigned int net;
|
| 143 | mctp_eid_t peer_addr;
|
| 144 | mctp_eid_t local_addr;
|
| 145 | __u8 tag;
|
| 146 |
|
| 147 |
|
| 148 | struct sock *sk;
|
| 149 |
|
| 150 |
|
| 151 | struct hlist_node hlist;
|
| 152 |
|
| 153 |
|
| 154 | struct hlist_node sklist;
|
| 155 |
|
| 156 | |
| 157 | * expiry data below.
|
| 158 |
|
| 159 | spinlock_t lock;
|
| 160 |
|
| 161 |
|
| 162 | refcount_t refs;
|
| 163 |
|
| 164 |
|
| 165 | struct sk_buff *reasm_head;
|
| 166 | struct sk_buff **reasm_tailp;
|
| 167 | bool reasm_dead;
|
| 168 | u8 last_seq;
|
| 169 |
|
| 170 |
|
| 171 | bool valid;
|
| 172 |
|
| 173 |
|
| 174 | unsigned long expiry;
|
| 175 |
|
| 176 | |
| 177 | * zero on initial key creation
|
| 178 |
|
| 179 | unsigned long dev_flow_state;
|
| 180 | struct mctp_dev *dev;
|
| 181 |
|
| 182 | |
| 183 | * automatically on timeout or response, instead SIOCMCTPDROPTAG
|
| 184 | * is used.
|
| 185 |
|
| 186 | bool manual_alloc;
|
| 187 | };
|
| 188 |
|
| 189 | struct mctp_skb_cb {
|
| 190 | unsigned int magic;
|
| 191 | unsigned int net;
|
| 192 |
|
| 193 | int ifindex;
|
| 194 | unsigned char halen;
|
| 195 | unsigned char haddr[MAX_ADDR_LEN];
|
| 196 | };
|
| 197 |
|
| 198 | |
| 199 | * development.
|
| 200 | *
|
| 201 | * TODO: remove checks & mctp_skb_cb->magic; replace callers of __mctp_cb
|
| 202 | * with mctp_cb().
|
| 203 | *
|
| 204 | * __mctp_cb() is only for the initial ingress code; we should see ->magic set
|
| 205 | * at all times after this.
|
| 206 |
|
| 207 | static inline struct mctp_skb_cb *__mctp_cb(struct sk_buff *skb)
|
| 208 | {
|
| 209 | struct mctp_skb_cb *cb = (void *)skb->cb;
|
| 210 |
|
| 211 | cb->magic = 0x4d435450;
|
| 212 | return cb;
|
| 213 | }
|
| 214 |
|
| 215 | static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb)
|
| 216 | {
|
| 217 | struct mctp_skb_cb *cb = (void *)skb->cb;
|
| 218 |
|
| 219 | BUILD_BUG_ON(sizeof(struct mctp_skb_cb) > sizeof(skb->cb));
|
| 220 | WARN_ON(cb->magic != 0x4d435450);
|
| 221 | return cb;
|
| 222 | }
|
| 223 |
|
| 224 | |
| 225 | * indicating the flow to the device driver.
|
| 226 |
|
| 227 | struct mctp_flow {
|
| 228 | struct mctp_sk_key *key;
|
| 229 | };
|
| 230 |
|
| 231 | struct mctp_dst;
|
| 232 |
|
| 233 | |
| 234 | *
|
| 235 | * These are held in the pernet->mctp.routes list, with RCU protection for
|
| 236 | * removed routes. We hold a reference to the netdev; routes need to be
|
| 237 | * dropped on NETDEV_UNREGISTER events.
|
| 238 | *
|
| 239 | * Updates to the route table are performed under rtnl; all reads under RCU,
|
| 240 | * so routes cannot be referenced over a RCU grace period.
|
| 241 |
|
| 242 | struct mctp_route {
|
| 243 | mctp_eid_t min, max;
|
| 244 |
|
| 245 | unsigned char type;
|
| 246 |
|
| 247 | unsigned int mtu;
|
| 248 |
|
| 249 | enum {
|
| 250 | MCTP_ROUTE_DIRECT,
|
| 251 | MCTP_ROUTE_GATEWAY,
|
| 252 | } dst_type;
|
| 253 | union {
|
| 254 | struct mctp_dev *dev;
|
| 255 | struct mctp_fq_addr gateway;
|
| 256 | };
|
| 257 |
|
| 258 | int (*output)(struct mctp_dst *dst,
|
| 259 | struct sk_buff *skb);
|
| 260 |
|
| 261 | struct list_head list;
|
| 262 | refcount_t refs;
|
| 263 | struct rcu_head rcu;
|
| 264 | };
|
| 265 |
|
| 266 | |
| 267 | * but is only held over the individual routing operation.
|
| 268 | *
|
| 269 | * Will typically be stored on the caller stack, and must be released after
|
| 270 | * usage.
|
| 271 |
|
| 272 | struct mctp_dst {
|
| 273 | struct mctp_dev *dev;
|
| 274 | unsigned int mtu;
|
| 275 | mctp_eid_t nexthop;
|
| 276 | mctp_eid_t saddr;
|
| 277 |
|
| 278 |
|
| 279 | unsigned char halen;
|
| 280 | unsigned char haddr[MAX_ADDR_LEN];
|
| 281 |
|
| 282 | int (*output)(struct mctp_dst *dst, struct sk_buff *skb);
|
| 283 | };
|
| 284 |
|
| 285 | int mctp_dst_from_extaddr(struct mctp_dst *dst, struct net *net, int ifindex,
|
| 286 | unsigned char halen, const unsigned char *haddr);
|
| 287 |
|
| 288 |
|
| 289 | int mctp_route_lookup(struct net *net, unsigned int dnet,
|
| 290 | mctp_eid_t daddr, struct mctp_dst *dst);
|
| 291 |
|
| 292 | void mctp_dst_release(struct mctp_dst *dst);
|
| 293 |
|
| 294 |
|
| 295 | int mctp_local_output(struct sock *sk, struct mctp_dst *dst,
|
| 296 | struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag);
|
| 297 |
|
| 298 | void mctp_key_unref(struct mctp_sk_key *key);
|
| 299 | struct mctp_sk_key *mctp_alloc_local_tag(struct mctp_sock *msk,
|
| 300 | unsigned int netid,
|
| 301 | mctp_eid_t local, mctp_eid_t peer,
|
| 302 | bool manual, u8 *tagp);
|
| 303 |
|
| 304 |
|
| 305 | unsigned int mctp_default_net(struct net *net);
|
| 306 | int mctp_default_net_set(struct net *net, unsigned int index);
|
| 307 | int mctp_route_add_local(struct mctp_dev *mdev, mctp_eid_t addr);
|
| 308 | int mctp_route_remove_local(struct mctp_dev *mdev, mctp_eid_t addr);
|
| 309 | void mctp_route_remove_dev(struct mctp_dev *mdev);
|
| 310 |
|
| 311 |
|
| 312 | enum mctp_neigh_source {
|
| 313 | MCTP_NEIGH_STATIC,
|
| 314 | MCTP_NEIGH_DISCOVER,
|
| 315 | };
|
| 316 |
|
| 317 | struct mctp_neigh {
|
| 318 | struct mctp_dev *dev;
|
| 319 | mctp_eid_t eid;
|
| 320 | enum mctp_neigh_source source;
|
| 321 |
|
| 322 | unsigned char ha[MAX_ADDR_LEN];
|
| 323 |
|
| 324 | struct list_head list;
|
| 325 | struct rcu_head rcu;
|
| 326 | };
|
| 327 |
|
| 328 | int mctp_neigh_init(void);
|
| 329 | void mctp_neigh_exit(void);
|
| 330 |
|
| 331 | |
| 332 | int mctp_neigh_lookup(struct mctp_dev *dev, mctp_eid_t eid,
|
| 333 | void *ret_hwaddr);
|
| 334 | void mctp_neigh_remove_dev(struct mctp_dev *mdev);
|
| 335 |
|
| 336 | int mctp_routes_init(void);
|
| 337 | void mctp_routes_exit(void);
|
| 338 |
|
| 339 | int mctp_device_init(void);
|
| 340 | void mctp_device_exit(void);
|
| 341 |
|
| 342 | |
| 343 | * "DSP0239 Management Component Transport Protocol (MCTP) IDs and Codes"
|
| 344 | * https://www.dmtf.org/sites/default/files/standards/documents/DSP0239_1.11.1.pdf
|
| 345 |
|
| 346 | enum mctp_phys_binding {
|
| 347 | MCTP_PHYS_BINDING_UNSPEC = 0x00,
|
| 348 | MCTP_PHYS_BINDING_SMBUS = 0x01,
|
| 349 | MCTP_PHYS_BINDING_PCIE_VDM = 0x02,
|
| 350 | MCTP_PHYS_BINDING_USB = 0x03,
|
| 351 | MCTP_PHYS_BINDING_KCS = 0x04,
|
| 352 | MCTP_PHYS_BINDING_SERIAL = 0x05,
|
| 353 | MCTP_PHYS_BINDING_I3C = 0x06,
|
| 354 | MCTP_PHYS_BINDING_MMBI = 0x07,
|
| 355 | MCTP_PHYS_BINDING_PCC = 0x08,
|
| 356 | MCTP_PHYS_BINDING_UCIE = 0x09,
|
| 357 | MCTP_PHYS_BINDING_VENDOR = 0xFF,
|
| 358 | };
|
| 359 |
|
| 360 | #endif
|