1 // SPDX-License-Identifier: GPL-2.0
3 * Management Component Transport Protocol (MCTP) - routing
6 * This is currently based on a simple routing table, with no dst cache. The
7 * number of routes should stay fairly small, so the lookup cost is small.
9 * Copyright (c) 2021 Code Construct
10 * Copyright (c) 2021 Google
13 #include <linux/idr.h>
14 #include <linux/mctp.h>
15 #include <linux/netdevice.h>
16 #include <linux/rtnetlink.h>
17 #include <linux/skbuff.h>
20 #include <net/mctpdevice.h>
21 #include <net/netlink.h>
24 static int mctp_neigh_add(struct mctp_dev
*mdev
, mctp_eid_t eid
,
25 enum mctp_neigh_source source
,
26 size_t lladdr_len
, const void *lladdr
)
28 struct net
*net
= dev_net(mdev
->dev
);
29 struct mctp_neigh
*neigh
;
32 mutex_lock(&net
->mctp
.neigh_lock
);
33 if (mctp_neigh_lookup(mdev
, eid
, NULL
) == 0) {
38 if (lladdr_len
> sizeof(neigh
->ha
)) {
43 neigh
= kzalloc(sizeof(*neigh
), GFP_KERNEL
);
48 INIT_LIST_HEAD(&neigh
->list
);
50 mctp_dev_hold(neigh
->dev
);
52 neigh
->source
= source
;
53 memcpy(neigh
->ha
, lladdr
, lladdr_len
);
55 list_add_rcu(&neigh
->list
, &net
->mctp
.neighbours
);
58 mutex_unlock(&net
->mctp
.neigh_lock
);
62 static void __mctp_neigh_free(struct rcu_head
*rcu
)
64 struct mctp_neigh
*neigh
= container_of(rcu
, struct mctp_neigh
, rcu
);
66 mctp_dev_put(neigh
->dev
);
70 /* Removes all neighbour entries referring to a device */
71 void mctp_neigh_remove_dev(struct mctp_dev
*mdev
)
73 struct net
*net
= dev_net(mdev
->dev
);
74 struct mctp_neigh
*neigh
, *tmp
;
76 mutex_lock(&net
->mctp
.neigh_lock
);
77 list_for_each_entry_safe(neigh
, tmp
, &net
->mctp
.neighbours
, list
) {
78 if (neigh
->dev
== mdev
) {
79 list_del_rcu(&neigh
->list
);
80 /* TODO: immediate RTM_DELNEIGH */
81 call_rcu(&neigh
->rcu
, __mctp_neigh_free
);
85 mutex_unlock(&net
->mctp
.neigh_lock
);
88 static int mctp_neigh_remove(struct mctp_dev
*mdev
, mctp_eid_t eid
,
89 enum mctp_neigh_source source
)
91 struct net
*net
= dev_net(mdev
->dev
);
92 struct mctp_neigh
*neigh
, *tmp
;
95 mutex_lock(&net
->mctp
.neigh_lock
);
96 list_for_each_entry_safe(neigh
, tmp
, &net
->mctp
.neighbours
, list
) {
97 if (neigh
->dev
== mdev
&& neigh
->eid
== eid
&&
98 neigh
->source
== source
) {
99 list_del_rcu(&neigh
->list
);
100 /* TODO: immediate RTM_DELNEIGH */
101 call_rcu(&neigh
->rcu
, __mctp_neigh_free
);
106 mutex_unlock(&net
->mctp
.neigh_lock
);
107 return dropped
? 0 : -ENOENT
;
110 static const struct nla_policy nd_mctp_policy
[NDA_MAX
+ 1] = {
111 [NDA_DST
] = { .type
= NLA_U8
},
112 [NDA_LLADDR
] = { .type
= NLA_BINARY
, .len
= MAX_ADDR_LEN
},
115 static int mctp_rtm_newneigh(struct sk_buff
*skb
, struct nlmsghdr
*nlh
,
116 struct netlink_ext_ack
*extack
)
118 struct net
*net
= sock_net(skb
->sk
);
119 struct net_device
*dev
;
120 struct mctp_dev
*mdev
;
122 struct nlattr
*tb
[NDA_MAX
+ 1];
128 rc
= nlmsg_parse(nlh
, sizeof(*ndm
), tb
, NDA_MAX
, nd_mctp_policy
,
131 NL_SET_ERR_MSG(extack
, "lladdr too large?");
136 NL_SET_ERR_MSG(extack
, "Neighbour EID must be specified");
140 if (!tb
[NDA_LLADDR
]) {
141 NL_SET_ERR_MSG(extack
, "Neighbour lladdr must be specified");
145 eid
= nla_get_u8(tb
[NDA_DST
]);
146 if (!mctp_address_unicast(eid
)) {
147 NL_SET_ERR_MSG(extack
, "Invalid neighbour EID");
151 lladdr
= nla_data(tb
[NDA_LLADDR
]);
152 lladdr_len
= nla_len(tb
[NDA_LLADDR
]);
154 ndm
= nlmsg_data(nlh
);
156 dev
= __dev_get_by_index(net
, ndm
->ndm_ifindex
);
160 mdev
= mctp_dev_get_rtnl(dev
);
164 if (lladdr_len
!= dev
->addr_len
) {
165 NL_SET_ERR_MSG(extack
, "Wrong lladdr length");
169 return mctp_neigh_add(mdev
, eid
, MCTP_NEIGH_STATIC
,
173 static int mctp_rtm_delneigh(struct sk_buff
*skb
, struct nlmsghdr
*nlh
,
174 struct netlink_ext_ack
*extack
)
176 struct net
*net
= sock_net(skb
->sk
);
177 struct nlattr
*tb
[NDA_MAX
+ 1];
178 struct net_device
*dev
;
179 struct mctp_dev
*mdev
;
184 rc
= nlmsg_parse(nlh
, sizeof(*ndm
), tb
, NDA_MAX
, nd_mctp_policy
,
187 NL_SET_ERR_MSG(extack
, "incorrect format");
192 NL_SET_ERR_MSG(extack
, "Neighbour EID must be specified");
195 eid
= nla_get_u8(tb
[NDA_DST
]);
197 ndm
= nlmsg_data(nlh
);
198 dev
= __dev_get_by_index(net
, ndm
->ndm_ifindex
);
202 mdev
= mctp_dev_get_rtnl(dev
);
206 return mctp_neigh_remove(mdev
, eid
, MCTP_NEIGH_STATIC
);
209 static int mctp_fill_neigh(struct sk_buff
*skb
, u32 portid
, u32 seq
, int event
,
210 unsigned int flags
, struct mctp_neigh
*neigh
)
212 struct net_device
*dev
= neigh
->dev
->dev
;
213 struct nlmsghdr
*nlh
;
216 nlh
= nlmsg_put(skb
, portid
, seq
, event
, sizeof(*hdr
), flags
);
220 hdr
= nlmsg_data(nlh
);
221 hdr
->ndm_family
= AF_MCTP
;
222 hdr
->ndm_ifindex
= dev
->ifindex
;
223 hdr
->ndm_state
= 0; // TODO other state bits?
224 if (neigh
->source
== MCTP_NEIGH_STATIC
)
225 hdr
->ndm_state
|= NUD_PERMANENT
;
227 hdr
->ndm_type
= RTN_UNICAST
; // TODO: is loopback RTN_LOCAL?
229 if (nla_put_u8(skb
, NDA_DST
, neigh
->eid
))
232 if (nla_put(skb
, NDA_LLADDR
, dev
->addr_len
, neigh
->ha
))
239 nlmsg_cancel(skb
, nlh
);
243 static int mctp_rtm_getneigh(struct sk_buff
*skb
, struct netlink_callback
*cb
)
245 struct net
*net
= sock_net(skb
->sk
);
246 int rc
, idx
, req_ifindex
;
247 struct mctp_neigh
*neigh
;
251 } *cbctx
= (void *)cb
->ctx
;
253 ndmsg
= nlmsg_data(cb
->nlh
);
254 req_ifindex
= ndmsg
->ndm_ifindex
;
258 list_for_each_entry_rcu(neigh
, &net
->mctp
.neighbours
, list
) {
259 if (idx
< cbctx
->idx
)
263 if (req_ifindex
== 0 || req_ifindex
== neigh
->dev
->dev
->ifindex
)
264 rc
= mctp_fill_neigh(skb
, NETLINK_CB(cb
->skb
).portid
,
266 RTM_NEWNEIGH
, NLM_F_MULTI
, neigh
);
279 int mctp_neigh_lookup(struct mctp_dev
*mdev
, mctp_eid_t eid
, void *ret_hwaddr
)
281 struct net
*net
= dev_net(mdev
->dev
);
282 struct mctp_neigh
*neigh
;
283 int rc
= -EHOSTUNREACH
; // TODO: or ENOENT?
286 list_for_each_entry_rcu(neigh
, &net
->mctp
.neighbours
, list
) {
287 if (mdev
== neigh
->dev
&& eid
== neigh
->eid
) {
289 memcpy(ret_hwaddr
, neigh
->ha
,
299 /* namespace registration */
300 static int __net_init
mctp_neigh_net_init(struct net
*net
)
302 struct netns_mctp
*ns
= &net
->mctp
;
304 INIT_LIST_HEAD(&ns
->neighbours
);
305 mutex_init(&ns
->neigh_lock
);
309 static void __net_exit
mctp_neigh_net_exit(struct net
*net
)
311 struct netns_mctp
*ns
= &net
->mctp
;
312 struct mctp_neigh
*neigh
;
314 list_for_each_entry(neigh
, &ns
->neighbours
, list
)
315 call_rcu(&neigh
->rcu
, __mctp_neigh_free
);
318 /* net namespace implementation */
320 static struct pernet_operations mctp_net_ops
= {
321 .init
= mctp_neigh_net_init
,
322 .exit
= mctp_neigh_net_exit
,
325 static const struct rtnl_msg_handler mctp_neigh_rtnl_msg_handlers
[] = {
326 {THIS_MODULE
, PF_MCTP
, RTM_NEWNEIGH
, mctp_rtm_newneigh
, NULL
, 0},
327 {THIS_MODULE
, PF_MCTP
, RTM_DELNEIGH
, mctp_rtm_delneigh
, NULL
, 0},
328 {THIS_MODULE
, PF_MCTP
, RTM_GETNEIGH
, NULL
, mctp_rtm_getneigh
, 0},
331 int __init
mctp_neigh_init(void)
335 err
= register_pernet_subsys(&mctp_net_ops
);
339 err
= rtnl_register_many(mctp_neigh_rtnl_msg_handlers
);
341 unregister_pernet_subsys(&mctp_net_ops
);
346 void mctp_neigh_exit(void)
348 rtnl_unregister_many(mctp_neigh_rtnl_msg_handlers
);
349 unregister_pernet_subsys(&mctp_net_ops
);