Message ID | 20211014023739.2032160-1-jk@codeconstruct.com.au (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net-next,v2] mctp: Implement extended addressing | expand |
Context | Check | Description |
---|---|---|
netdev/cover_letter | success | Single patches do not need cover letters |
netdev/fixes_present | success | Fixes tag not required for -next series |
netdev/patch_count | success | Link |
netdev/tree_selection | success | Clearly marked for net-next |
netdev/subject_prefix | success | Link |
netdev/cc_maintainers | success | CCed 5 of 5 maintainers |
netdev/source_inline | success | Was 0 now: 0 |
netdev/verify_signedoff | success | Signed-off-by tag matches author and committer |
netdev/module_param | success | Was 0 now: 0 |
netdev/build_32bit | success | Errors and warnings before: 2 this patch: 2 |
netdev/kdoc | success | Errors and warnings before: 0 this patch: 0 |
netdev/verify_fixes | success | No Fixes tag |
netdev/checkpatch | success | total: 0 errors, 0 warnings, 0 checks, 385 lines checked |
netdev/build_allmodconfig_warn | success | Errors and warnings before: 2 this patch: 2 |
netdev/header_inline | success | No static functions without inline keyword in header files |
Hi Jeremy,
I love your patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
url: https://github.com/0day-ci/linux/commits/Jeremy-Kerr/mctp-Implement-extended-addressing/20211014-103942
base: https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git 39e222bfd7f37e7a98069869375b903d7096c113
config: hexagon-randconfig-r041-20211014 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 6c76d0101193aa4eb891a6954ff047eda2f9cf71)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/2fed3ce68e4fc1a6f8faaa838ce84829cd030f6b
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Jeremy-Kerr/mctp-Implement-extended-addressing/20211014-103942
git checkout 2fed3ce68e4fc1a6f8faaa838ce84829cd030f6b
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=hexagon
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
All warnings (new ones prefixed by >>):
>> net/mctp/route.c:752:7: warning: variable 'rc' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
if (WARN_ON(!rt->dev))
^~~~~~~~~~~~~~~~~
include/asm-generic/bug.h:120:28: note: expanded from macro 'WARN_ON'
#define WARN_ON(condition) ({ \
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
net/mctp/route.c:838:9: note: uninitialized use occurs here
return rc;
^~
net/mctp/route.c:752:3: note: remove the 'if' if its condition is always false
if (WARN_ON(!rt->dev))
^~~~~~~~~~~~~~~~~~~~~~
net/mctp/route.c:745:8: note: initialize the variable 'rc' to silence this warning
int rc;
^
= 0
1 warning generated.
vim +752 net/mctp/route.c
4a992bbd365094 Jeremy Kerr 2021-07-29 732
889b7da23abf92 Jeremy Kerr 2021-07-29 733 int mctp_local_output(struct sock *sk, struct mctp_route *rt,
889b7da23abf92 Jeremy Kerr 2021-07-29 734 struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag)
889b7da23abf92 Jeremy Kerr 2021-07-29 735 {
833ef3b91de692 Jeremy Kerr 2021-07-29 736 struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk);
889b7da23abf92 Jeremy Kerr 2021-07-29 737 struct mctp_skb_cb *cb = mctp_cb(skb);
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 738 struct mctp_route tmp_rt;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 739 struct net_device *dev;
889b7da23abf92 Jeremy Kerr 2021-07-29 740 struct mctp_hdr *hdr;
889b7da23abf92 Jeremy Kerr 2021-07-29 741 unsigned long flags;
4a992bbd365094 Jeremy Kerr 2021-07-29 742 unsigned int mtu;
889b7da23abf92 Jeremy Kerr 2021-07-29 743 mctp_eid_t saddr;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 744 bool ext_rt;
889b7da23abf92 Jeremy Kerr 2021-07-29 745 int rc;
833ef3b91de692 Jeremy Kerr 2021-07-29 746 u8 tag;
889b7da23abf92 Jeremy Kerr 2021-07-29 747
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 748 if (rt) {
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 749 ext_rt = false;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 750 dev = NULL;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 751
889b7da23abf92 Jeremy Kerr 2021-07-29 @752 if (WARN_ON(!rt->dev))
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 753 goto out_release;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 754
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 755 } else if (cb->ifindex) {
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 756 ext_rt = true;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 757 rt = &tmp_rt;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 758
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 759 rc = -ENODEV;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 760 rcu_read_lock();
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 761 dev = dev_get_by_index_rcu(sock_net(sk), cb->ifindex);
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 762 if (!dev) {
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 763 rcu_read_unlock();
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 764 return rc;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 765 }
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 766
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 767 rt->dev = __mctp_dev_get(dev);
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 768 rcu_read_unlock();
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 769
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 770 if (!rt->dev)
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 771 goto out_release;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 772
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 773 /* establish temporary route - we set up enough to keep
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 774 * mctp_route_output happy
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 775 */
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 776 rt->output = mctp_route_output;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 777 rt->mtu = 0;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 778
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 779 } else {
889b7da23abf92 Jeremy Kerr 2021-07-29 780 return -EINVAL;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 781 }
889b7da23abf92 Jeremy Kerr 2021-07-29 782
889b7da23abf92 Jeremy Kerr 2021-07-29 783 spin_lock_irqsave(&rt->dev->addrs_lock, flags);
889b7da23abf92 Jeremy Kerr 2021-07-29 784 if (rt->dev->num_addrs == 0) {
889b7da23abf92 Jeremy Kerr 2021-07-29 785 rc = -EHOSTUNREACH;
889b7da23abf92 Jeremy Kerr 2021-07-29 786 } else {
889b7da23abf92 Jeremy Kerr 2021-07-29 787 /* use the outbound interface's first address as our source */
889b7da23abf92 Jeremy Kerr 2021-07-29 788 saddr = rt->dev->addrs[0];
889b7da23abf92 Jeremy Kerr 2021-07-29 789 rc = 0;
889b7da23abf92 Jeremy Kerr 2021-07-29 790 }
889b7da23abf92 Jeremy Kerr 2021-07-29 791 spin_unlock_irqrestore(&rt->dev->addrs_lock, flags);
889b7da23abf92 Jeremy Kerr 2021-07-29 792
889b7da23abf92 Jeremy Kerr 2021-07-29 793 if (rc)
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 794 goto out_release;
889b7da23abf92 Jeremy Kerr 2021-07-29 795
833ef3b91de692 Jeremy Kerr 2021-07-29 796 if (req_tag & MCTP_HDR_FLAG_TO) {
833ef3b91de692 Jeremy Kerr 2021-07-29 797 rc = mctp_alloc_local_tag(msk, saddr, daddr, &tag);
833ef3b91de692 Jeremy Kerr 2021-07-29 798 if (rc)
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 799 goto out_release;
833ef3b91de692 Jeremy Kerr 2021-07-29 800 tag |= MCTP_HDR_FLAG_TO;
833ef3b91de692 Jeremy Kerr 2021-07-29 801 } else {
833ef3b91de692 Jeremy Kerr 2021-07-29 802 tag = req_tag;
833ef3b91de692 Jeremy Kerr 2021-07-29 803 }
833ef3b91de692 Jeremy Kerr 2021-07-29 804
4a992bbd365094 Jeremy Kerr 2021-07-29 805 skb->protocol = htons(ETH_P_MCTP);
4a992bbd365094 Jeremy Kerr 2021-07-29 806 skb->priority = 0;
889b7da23abf92 Jeremy Kerr 2021-07-29 807 skb_reset_transport_header(skb);
889b7da23abf92 Jeremy Kerr 2021-07-29 808 skb_push(skb, sizeof(struct mctp_hdr));
889b7da23abf92 Jeremy Kerr 2021-07-29 809 skb_reset_network_header(skb);
4a992bbd365094 Jeremy Kerr 2021-07-29 810 skb->dev = rt->dev->dev;
4a992bbd365094 Jeremy Kerr 2021-07-29 811
4a992bbd365094 Jeremy Kerr 2021-07-29 812 /* cb->net will have been set on initial ingress */
4a992bbd365094 Jeremy Kerr 2021-07-29 813 cb->src = saddr;
4a992bbd365094 Jeremy Kerr 2021-07-29 814
4a992bbd365094 Jeremy Kerr 2021-07-29 815 /* set up common header fields */
889b7da23abf92 Jeremy Kerr 2021-07-29 816 hdr = mctp_hdr(skb);
889b7da23abf92 Jeremy Kerr 2021-07-29 817 hdr->ver = 1;
889b7da23abf92 Jeremy Kerr 2021-07-29 818 hdr->dest = daddr;
889b7da23abf92 Jeremy Kerr 2021-07-29 819 hdr->src = saddr;
889b7da23abf92 Jeremy Kerr 2021-07-29 820
4a992bbd365094 Jeremy Kerr 2021-07-29 821 mtu = mctp_route_mtu(rt);
889b7da23abf92 Jeremy Kerr 2021-07-29 822
4a992bbd365094 Jeremy Kerr 2021-07-29 823 if (skb->len + sizeof(struct mctp_hdr) <= mtu) {
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 824 hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM |
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 825 MCTP_HDR_FLAG_EOM | tag;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 826 rc = rt->output(rt, skb);
4a992bbd365094 Jeremy Kerr 2021-07-29 827 } else {
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 828 rc = mctp_do_fragment_route(rt, skb, mtu, tag);
4a992bbd365094 Jeremy Kerr 2021-07-29 829 }
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 830
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 831 out_release:
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 832 if (!ext_rt)
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 833 mctp_route_release(rt);
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 834
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 835 if (dev)
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 836 dev_put(dev);
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 837
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 838 return rc;
2fed3ce68e4fc1 Jeremy Kerr 2021-10-14 839
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/include/net/mctp.h b/include/net/mctp.h index b9ed62a63c24..716405e0294c 100644 --- a/include/net/mctp.h +++ b/include/net/mctp.h @@ -58,6 +58,9 @@ struct mctp_sock { mctp_eid_t bind_addr; __u8 bind_type; + /* sendmsg()/recvmsg() uses struct sockaddr_mctp_ext */ + bool addr_ext; + /* list of mctp_sk_key, for incoming tag lookup. updates protected * by sk->net->keys_lock */ @@ -152,10 +155,16 @@ struct mctp_sk_key { struct mctp_skb_cb { unsigned int magic; - unsigned int net; + int net; + int ifindex; /* extended/direct addressing if set */ + unsigned char halen; mctp_eid_t src; + unsigned char haddr[]; }; +#define MCTP_SKB_CB_HADDR_MAXLEN (sizeof((((struct sk_buff *)(NULL))->cb)) \ + - offsetof(struct mctp_skb_cb, haddr)) + /* skb control-block accessors with a little extra debugging for initial * development. * @@ -189,8 +198,7 @@ static inline struct mctp_skb_cb *mctp_cb(struct sk_buff *skb) * * Updates to the route table are performed under rtnl; all reads under RCU, * so routes cannot be referenced over a RCU grace period. Specifically: A - * caller cannot block between mctp_route_lookup and passing the route to - * mctp_do_route. + * caller cannot block between mctp_route_lookup and mctp_route_release() */ struct mctp_route { mctp_eid_t min, max; @@ -210,8 +218,6 @@ struct mctp_route { struct mctp_route *mctp_route_lookup(struct net *net, unsigned int dnet, mctp_eid_t daddr); -int mctp_do_route(struct mctp_route *rt, struct sk_buff *skb); - int mctp_local_output(struct sock *sk, struct mctp_route *rt, struct sk_buff *skb, mctp_eid_t daddr, u8 req_tag); diff --git a/include/uapi/linux/mctp.h b/include/uapi/linux/mctp.h index 52b54d13f385..896432ce3c71 100644 --- a/include/uapi/linux/mctp.h +++ b/include/uapi/linux/mctp.h @@ -10,6 +10,7 @@ #define __UAPI_MCTP_H #include <linux/types.h> +#include <linux/netdevice.h> typedef __u8 mctp_eid_t; @@ -25,6 +26,13 @@ struct sockaddr_mctp { __u8 smctp_tag; }; +struct sockaddr_mctp_ext { + struct sockaddr_mctp smctp_base; + int smctp_ifindex; + unsigned char smctp_halen; + unsigned char smctp_haddr[MAX_ADDR_LEN]; +}; + #define MCTP_NET_ANY 0x0 #define MCTP_ADDR_NULL 0x00 @@ -33,4 +41,9 @@ struct sockaddr_mctp { #define MCTP_TAG_MASK 0x07 #define MCTP_TAG_OWNER 0x08 +/* setsockopt(2) level & options */ +#define SOL_MCTP 0 + +#define MCTP_OPT_ADDR_EXT 1 + #endif /* __UAPI_MCTP_H */ diff --git a/net/mctp/af_mctp.c b/net/mctp/af_mctp.c index 66a411d60b6c..5eae06aaf65c 100644 --- a/net/mctp/af_mctp.c +++ b/net/mctp/af_mctp.c @@ -77,6 +77,7 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) const int hlen = MCTP_HEADER_MAXLEN + sizeof(struct mctp_hdr); int rc, addrlen = msg->msg_namelen; struct sock *sk = sock->sk; + struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); struct mctp_skb_cb *cb; struct mctp_route *rt; struct sk_buff *skb; @@ -100,11 +101,6 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) if (addr->smctp_network == MCTP_NET_ANY) addr->smctp_network = mctp_default_net(sock_net(sk)); - rt = mctp_route_lookup(sock_net(sk), addr->smctp_network, - addr->smctp_addr.s_addr); - if (!rt) - return -EHOSTUNREACH; - skb = sock_alloc_send_skb(sk, hlen + 1 + len, msg->msg_flags & MSG_DONTWAIT, &rc); if (!skb) @@ -116,19 +112,45 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) *(u8 *)skb_put(skb, 1) = addr->smctp_type; rc = memcpy_from_msg((void *)skb_put(skb, len), msg, len); - if (rc < 0) { - kfree_skb(skb); - return rc; - } + if (rc < 0) + goto err_free; /* set up cb */ cb = __mctp_cb(skb); cb->net = addr->smctp_network; + /* direct addressing */ + if (msk->addr_ext && addrlen >= sizeof(struct sockaddr_mctp_ext)) { + DECLARE_SOCKADDR(struct sockaddr_mctp_ext *, + extaddr, msg->msg_name); + + if (extaddr->smctp_halen > MCTP_SKB_CB_HADDR_MAXLEN) { + rc = -EINVAL; + goto err_free; + } + + cb->ifindex = extaddr->smctp_ifindex; + cb->halen = extaddr->smctp_halen; + memcpy(cb->haddr, extaddr->smctp_haddr, cb->halen); + + rt = NULL; + } else { + rt = mctp_route_lookup(sock_net(sk), addr->smctp_network, + addr->smctp_addr.s_addr); + if (!rt) { + rc = -EHOSTUNREACH; + goto err_free; + } + } + rc = mctp_local_output(sk, rt, skb, addr->smctp_addr.s_addr, addr->smctp_tag); return rc ? : len; + +err_free: + kfree_skb(skb); + return rc; } static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, @@ -136,6 +158,7 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, { DECLARE_SOCKADDR(struct sockaddr_mctp *, addr, msg->msg_name); struct sock *sk = sock->sk; + struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); struct sk_buff *skb; size_t msglen; u8 type; @@ -181,6 +204,16 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, addr->smctp_tag = hdr->flags_seq_tag & (MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO); msg->msg_namelen = sizeof(*addr); + + if (msk->addr_ext) { + DECLARE_SOCKADDR(struct sockaddr_mctp_ext *, ae, + msg->msg_name); + msg->msg_namelen = sizeof(*ae); + ae->smctp_ifindex = cb->ifindex; + ae->smctp_halen = cb->halen; + memset(ae->smctp_haddr, 0x0, sizeof(ae->smctp_haddr)); + memcpy(ae->smctp_haddr, cb->haddr, cb->halen); + } } rc = len; @@ -196,12 +229,45 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, static int mctp_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int optlen) { - return -EINVAL; + struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); + int val; + + if (level != SOL_MCTP) + return -EINVAL; + + if (optname == MCTP_OPT_ADDR_EXT) { + if (optlen != sizeof(int)) + return -EINVAL; + if (copy_from_sockptr(&val, optval, sizeof(int))) + return -EFAULT; + msk->addr_ext = val; + return 0; + } + + return -ENOPROTOOPT; } static int mctp_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) { + struct mctp_sock *msk = container_of(sock->sk, struct mctp_sock, sk); + int len, val; + + if (level != SOL_MCTP) + return -EINVAL; + + if (get_user(len, optlen)) + return -EFAULT; + + if (optname == MCTP_OPT_ADDR_EXT) { + if (len != sizeof(int)) + return -EINVAL; + val = !!msk->addr_ext; + if (copy_to_user(optval, &val, len)) + return -EFAULT; + return 0; + } + return -EINVAL; } diff --git a/net/mctp/route.c b/net/mctp/route.c index 04781459b2be..3d77bb5e34d2 100644 --- a/net/mctp/route.c +++ b/net/mctp/route.c @@ -433,6 +433,7 @@ static unsigned int mctp_route_mtu(struct mctp_route *rt) static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb) { + struct mctp_skb_cb *cb = mctp_cb(skb); struct mctp_hdr *hdr = mctp_hdr(skb); char daddr_buf[MAX_ADDR_LEN]; char *daddr = NULL; @@ -447,9 +448,14 @@ static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb) return -EMSGSIZE; } - /* If lookup fails let the device handle daddr==NULL */ - if (mctp_neigh_lookup(route->dev, hdr->dest, daddr_buf) == 0) - daddr = daddr_buf; + if (cb->ifindex) { + /* direct route; use the hwaddr we stashed in sendmsg */ + daddr = cb->haddr; + } else { + /* If lookup fails let the device handle daddr==NULL */ + if (mctp_neigh_lookup(route->dev, hdr->dest, daddr_buf) == 0) + daddr = daddr_buf; + } rc = dev_hard_header(skb, skb->dev, ntohs(skb->protocol), daddr, skb->dev->dev_addr, skb->len); @@ -645,16 +651,6 @@ static struct mctp_route *mctp_route_lookup_null(struct net *net, return NULL; } -/* sends a skb to rt and releases the route. */ -int mctp_do_route(struct mctp_route *rt, struct sk_buff *skb) -{ - int rc; - - rc = rt->output(rt, skb); - mctp_route_release(rt); - return rc; -} - static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb, unsigned int mtu, u8 tag) { @@ -721,7 +717,7 @@ static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb, /* copy message payload */ skb_copy_bits(skb, pos, skb_transport_header(skb2), size); - /* do route, but don't drop the rt reference */ + /* do route */ rc = rt->output(rt, skb2); if (rc) break; @@ -730,7 +726,6 @@ static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb, pos += size; } - mctp_route_release(rt); consume_skb(skb); return rc; } @@ -740,15 +735,50 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, { struct mctp_sock *msk = container_of(sk, struct mctp_sock, sk); struct mctp_skb_cb *cb = mctp_cb(skb); + struct mctp_route tmp_rt; + struct net_device *dev; struct mctp_hdr *hdr; unsigned long flags; unsigned int mtu; mctp_eid_t saddr; + bool ext_rt; int rc; u8 tag; - if (WARN_ON(!rt->dev)) + if (rt) { + ext_rt = false; + dev = NULL; + + if (WARN_ON(!rt->dev)) + goto out_release; + + } else if (cb->ifindex) { + ext_rt = true; + rt = &tmp_rt; + + rc = -ENODEV; + rcu_read_lock(); + dev = dev_get_by_index_rcu(sock_net(sk), cb->ifindex); + if (!dev) { + rcu_read_unlock(); + return rc; + } + + rt->dev = __mctp_dev_get(dev); + rcu_read_unlock(); + + if (!rt->dev) + goto out_release; + + /* establish temporary route - we set up enough to keep + * mctp_route_output happy + */ + rt->output = mctp_route_output; + rt->mtu = 0; + + } else { return -EINVAL; + } spin_lock_irqsave(&rt->dev->addrs_lock, flags); if (rt->dev->num_addrs == 0) { @@ -761,18 +791,17 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, spin_unlock_irqrestore(&rt->dev->addrs_lock, flags); if (rc) - return rc; + goto out_release; if (req_tag & MCTP_HDR_FLAG_TO) { rc = mctp_alloc_local_tag(msk, saddr, daddr, &tag); if (rc) - return rc; + goto out_release; tag |= MCTP_HDR_FLAG_TO; } else { tag = req_tag; } - skb->protocol = htons(ETH_P_MCTP); skb->priority = 0; skb_reset_transport_header(skb); @@ -792,12 +821,22 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt, mtu = mctp_route_mtu(rt); if (skb->len + sizeof(struct mctp_hdr) <= mtu) { - hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM | MCTP_HDR_FLAG_EOM | - tag; - return mctp_do_route(rt, skb); + hdr->flags_seq_tag = MCTP_HDR_FLAG_SOM | + MCTP_HDR_FLAG_EOM | tag; + rc = rt->output(rt, skb); } else { - return mctp_do_fragment_route(rt, skb, mtu, tag); + rc = mctp_do_fragment_route(rt, skb, mtu, tag); } + +out_release: + if (!ext_rt) + mctp_route_release(rt); + + if (dev) + dev_put(dev); + + return rc; + } /* route management */ @@ -938,8 +977,15 @@ static int mctp_pkttype_receive(struct sk_buff *skb, struct net_device *dev, if (mh->ver < MCTP_VER_MIN || mh->ver > MCTP_VER_MAX) goto err_drop; - cb = __mctp_cb(skb); + /* MCTP drivers must populate halen/haddr */ + if (dev->type == ARPHRD_MCTP) { + cb = mctp_cb(skb); + } else { + cb = __mctp_cb(skb); + cb->halen = 0; + } cb->net = READ_ONCE(mdev->net); + cb->ifindex = dev->ifindex; rt = mctp_route_lookup(net, cb->net, mh->dest); @@ -950,7 +996,8 @@ static int mctp_pkttype_receive(struct sk_buff *skb, struct net_device *dev, if (!rt) goto err_drop; - mctp_do_route(rt, skb); + rt->output(rt, skb); + mctp_route_release(rt); return NET_RX_SUCCESS;
This change allows an extended address struct - struct sockaddr_mctp_ext - to be passed to sendmsg/recvmsg. This allows userspace to specify output ifindex and physical address information (for sendmsg) or receive the input ifindex/physaddr for incoming messages (for recvmsg). This is typically used by userspace for MCTP address discovery and assignment operations. The extended addressing facility is conditional on a new sockopt: MCTP_OPT_ADDR_EXT; userspace must explicitly enable addressing before the kernel will consume/populate the extended address data. Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au> --- v2: - non-RFC - learn to spell "typically" RFC: this patch adds a bit of an new ABI, in that the struct sockaddr for MCTP has been extended, with extra addressing data being available for applications after setting a sockopt. Using something like IP_PKTINFO might be suitable instead, but that requires sendmsg/recvmsg, and control message setup, whereas this is a a simpler interface, and also allows extended addressing info in sendto/recvfrom too. Comments most welcome! --- include/net/mctp.h | 16 +++++-- include/uapi/linux/mctp.h | 13 ++++++ net/mctp/af_mctp.c | 86 ++++++++++++++++++++++++++++++---- net/mctp/route.c | 97 +++++++++++++++++++++++++++++---------- 4 files changed, 172 insertions(+), 40 deletions(-)