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 if (dev) 138 mctp_dev_hold(dev); 139 rt->rt.dev = dev; 140 141 list_add_rcu(&rt->rt.list, &net->mctp.routes); 142 143 return rt; 144 } 145 146 /* Convenience function for our test dst; release with mctp_test_dst_release() 147 */ 148 void mctp_test_dst_setup(struct kunit *test, struct mctp_dst *dst, 149 struct mctp_test_dev *dev, 150 struct mctp_test_pktqueue *tpq, unsigned int mtu) 151 { 152 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, dev); 153 154 memset(dst, 0, sizeof(*dst)); 155 156 dst->dev = dev->mdev; 157 __mctp_dev_get(dst->dev->dev); 158 dst->mtu = mtu; 159 dst->output = mctp_test_dst_output; 160 mctp_test_pktqueue_init(tpq); 161 test->priv = tpq; 162 } 163 164 void mctp_test_dst_release(struct mctp_dst *dst, 165 struct mctp_test_pktqueue *tpq) 166 { 167 mctp_dst_release(dst); 168 skb_queue_purge(&tpq->pkts); 169 } 170 171 void mctp_test_route_destroy(struct kunit *test, struct mctp_test_route *rt) 172 { 173 unsigned int refs; 174 175 rtnl_lock(); 176 list_del_rcu(&rt->rt.list); 177 rtnl_unlock(); 178 179 if (rt->rt.dev) 180 mctp_dev_put(rt->rt.dev); 181 182 refs = refcount_read(&rt->rt.refs); 183 KUNIT_ASSERT_EQ_MSG(test, refs, 1, "route ref imbalance"); 184 185 kfree_rcu(&rt->rt, rcu); 186 } 187 188 void mctp_test_skb_set_dev(struct sk_buff *skb, struct mctp_test_dev *dev) 189 { 190 struct mctp_skb_cb *cb; 191 192 cb = mctp_cb(skb); 193 cb->net = READ_ONCE(dev->mdev->net); 194 skb->dev = dev->ndev; 195 } 196 197 struct sk_buff *mctp_test_create_skb(const struct mctp_hdr *hdr, 198 unsigned int data_len) 199 { 200 size_t hdr_len = sizeof(*hdr); 201 struct sk_buff *skb; 202 unsigned int i; 203 u8 *buf; 204 205 skb = alloc_skb(hdr_len + data_len, GFP_KERNEL); 206 if (!skb) 207 return NULL; 208 209 __mctp_cb(skb); 210 memcpy(skb_put(skb, hdr_len), hdr, hdr_len); 211 212 buf = skb_put(skb, data_len); 213 for (i = 0; i < data_len; i++) 214 buf[i] = i & 0xff; 215 216 return skb; 217 } 218 219 struct sk_buff *__mctp_test_create_skb_data(const struct mctp_hdr *hdr, 220 const void *data, size_t data_len) 221 { 222 size_t hdr_len = sizeof(*hdr); 223 struct sk_buff *skb; 224 225 skb = alloc_skb(hdr_len + data_len, GFP_KERNEL); 226 if (!skb) 227 return NULL; 228 229 __mctp_cb(skb); 230 memcpy(skb_put(skb, hdr_len), hdr, hdr_len); 231 memcpy(skb_put(skb, data_len), data, data_len); 232 233 return skb; 234 } 235