1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/netdevice.h> 4 #include <linux/mctp.h> 5 #include <linux/if_arp.h> 6 7 #include <net/mctp.h> 8 #include <net/mctpdevice.h> 9 #include <net/pkt_sched.h> 10 11 #include "utils.h" 12 13 static netdev_tx_t mctp_test_dev_tx(struct sk_buff *skb, 14 struct net_device *ndev) 15 { 16 kfree_skb(skb); 17 return NETDEV_TX_OK; 18 } 19 20 static const struct net_device_ops mctp_test_netdev_ops = { 21 .ndo_start_xmit = mctp_test_dev_tx, 22 }; 23 24 static void mctp_test_dev_setup(struct net_device *ndev) 25 { 26 ndev->type = ARPHRD_MCTP; 27 ndev->mtu = MCTP_DEV_TEST_MTU; 28 ndev->hard_header_len = 0; 29 ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN; 30 ndev->flags = IFF_NOARP; 31 ndev->netdev_ops = &mctp_test_netdev_ops; 32 ndev->needs_free_netdev = true; 33 } 34 35 static struct mctp_test_dev *__mctp_test_create_dev(unsigned short lladdr_len, 36 const unsigned char *lladdr) 37 { 38 struct mctp_test_dev *dev; 39 struct net_device *ndev; 40 int rc; 41 42 if (WARN_ON(lladdr_len > MAX_ADDR_LEN)) 43 return NULL; 44 45 ndev = alloc_netdev(sizeof(*dev), "mctptest%d", NET_NAME_ENUM, 46 mctp_test_dev_setup); 47 if (!ndev) 48 return NULL; 49 50 dev = netdev_priv(ndev); 51 dev->ndev = ndev; 52 ndev->addr_len = lladdr_len; 53 dev_addr_set(ndev, lladdr); 54 55 rc = register_netdev(ndev); 56 if (rc) { 57 free_netdev(ndev); 58 return NULL; 59 } 60 61 rcu_read_lock(); 62 dev->mdev = __mctp_dev_get(ndev); 63 dev->mdev->net = mctp_default_net(dev_net(ndev)); 64 rcu_read_unlock(); 65 66 return dev; 67 } 68 69 struct mctp_test_dev *mctp_test_create_dev(void) 70 { 71 return __mctp_test_create_dev(0, NULL); 72 } 73 74 struct mctp_test_dev *mctp_test_create_dev_lladdr(unsigned short lladdr_len, 75 const unsigned char *lladdr) 76 { 77 return __mctp_test_create_dev(lladdr_len, lladdr); 78 } 79 80 void mctp_test_destroy_dev(struct mctp_test_dev *dev) 81 { 82 mctp_dev_put(dev->mdev); 83 unregister_netdev(dev->ndev); 84 } 85 86 static const unsigned int test_pktqueue_magic = 0x5f713aef; 87 88 void mctp_test_pktqueue_init(struct mctp_test_pktqueue *tpq) 89 { 90 tpq->magic = test_pktqueue_magic; 91 skb_queue_head_init(&tpq->pkts); 92 } 93 94 static int mctp_test_dst_output(struct mctp_dst *dst, struct sk_buff *skb) 95 { 96 struct kunit *test = current->kunit_test; 97 struct mctp_test_pktqueue *tpq = test->priv; 98 99 KUNIT_ASSERT_EQ(test, tpq->magic, test_pktqueue_magic); 100 101 skb_queue_tail(&tpq->pkts, skb); 102 103 return 0; 104 } 105 106 /* local version of mctp_route_alloc() */ 107 static struct mctp_test_route *mctp_route_test_alloc(void) 108 { 109 struct mctp_test_route *rt; 110 111 rt = kzalloc(sizeof(*rt), GFP_KERNEL); 112 if (!rt) 113 return NULL; 114 115 INIT_LIST_HEAD(&rt->rt.list); 116 refcount_set(&rt->rt.refs, 1); 117 rt->rt.output = mctp_test_dst_output; 118 119 return rt; 120 } 121 122 struct mctp_test_route *mctp_test_create_route(struct net *net, 123 struct mctp_dev *dev, 124 mctp_eid_t eid, 125 unsigned int mtu) 126 { 127 struct mctp_test_route *rt; 128 129 rt = mctp_route_test_alloc(); 130 if (!rt) 131 return NULL; 132 133 rt->rt.min = eid; 134 rt->rt.max = eid; 135 rt->rt.mtu = mtu; 136 rt->rt.type = RTN_UNSPEC; 137 rt->rt.dst_type = MCTP_ROUTE_DIRECT; 138 if (dev) 139 mctp_dev_hold(dev); 140 rt->rt.dev = dev; 141 142 list_add_rcu(&rt->rt.list, &net->mctp.routes); 143 144 return rt; 145 } 146 147 /* Convenience function for our test dst; release with mctp_test_dst_release() 148 */ 149 void mctp_test_dst_setup(struct kunit *test, struct mctp_dst *dst, 150 struct mctp_test_dev *dev, 151 struct mctp_test_pktqueue *tpq, unsigned int mtu) 152 { 153 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev); 154 155 memset(dst, 0, sizeof(*dst)); 156 157 dst->dev = dev->mdev; 158 __mctp_dev_get(dst->dev->dev); 159 dst->mtu = mtu; 160 dst->output = mctp_test_dst_output; 161 mctp_test_pktqueue_init(tpq); 162 test->priv = tpq; 163 } 164 165 void mctp_test_dst_release(struct mctp_dst *dst, 166 struct mctp_test_pktqueue *tpq) 167 { 168 mctp_dst_release(dst); 169 skb_queue_purge(&tpq->pkts); 170 } 171 172 void mctp_test_route_destroy(struct kunit *test, struct mctp_test_route *rt) 173 { 174 unsigned int refs; 175 176 rtnl_lock(); 177 list_del_rcu(&rt->rt.list); 178 rtnl_unlock(); 179 180 if (rt->rt.dst_type == MCTP_ROUTE_DIRECT && rt->rt.dev) 181 mctp_dev_put(rt->rt.dev); 182 183 refs = refcount_read(&rt->rt.refs); 184 KUNIT_ASSERT_EQ_MSG(test, refs, 1, "route ref imbalance"); 185 186 kfree_rcu(&rt->rt, rcu); 187 } 188 189 void mctp_test_skb_set_dev(struct sk_buff *skb, struct mctp_test_dev *dev) 190 { 191 struct mctp_skb_cb *cb; 192 193 cb = mctp_cb(skb); 194 cb->net = READ_ONCE(dev->mdev->net); 195 skb->dev = dev->ndev; 196 } 197 198 struct sk_buff *mctp_test_create_skb(const struct mctp_hdr *hdr, 199 unsigned int data_len) 200 { 201 size_t hdr_len = sizeof(*hdr); 202 struct sk_buff *skb; 203 unsigned int i; 204 u8 *buf; 205 206 skb = alloc_skb(hdr_len + data_len, GFP_KERNEL); 207 if (!skb) 208 return NULL; 209 210 __mctp_cb(skb); 211 memcpy(skb_put(skb, hdr_len), hdr, hdr_len); 212 213 buf = skb_put(skb, data_len); 214 for (i = 0; i < data_len; i++) 215 buf[i] = i & 0xff; 216 217 return skb; 218 } 219 220 struct sk_buff *__mctp_test_create_skb_data(const struct mctp_hdr *hdr, 221 const void *data, size_t data_len) 222 { 223 size_t hdr_len = sizeof(*hdr); 224 struct sk_buff *skb; 225 226 skb = alloc_skb(hdr_len + data_len, GFP_KERNEL); 227 if (!skb) 228 return NULL; 229 230 __mctp_cb(skb); 231 memcpy(skb_put(skb, hdr_len), hdr, hdr_len); 232 memcpy(skb_put(skb, data_len), data, data_len); 233 234 return skb; 235 } 236