Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mctp: Pass flow data & flow release events to drivers

Now that we have an extension for MCTP data in skbs, populate the flow
when a key has been created for the packet, and add a device driver
operation to inform of flow destruction.

Includes a fix for a warning with test builds:
Reported-by: kernel test robot <lkp@intel.com>

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Jeremy Kerr and committed by
David S. Miller
67737c45 78476d31

+126 -2
+6
include/net/mctp.h
··· 152 152 153 153 /* expiry timeout; valid (above) cleared on expiry */ 154 154 unsigned long expiry; 155 + 156 + /* free to use for device flow state tracking. Initialised to 157 + * zero on initial key creation 158 + */ 159 + unsigned long dev_flow_state; 160 + struct mctp_dev *dev; 155 161 }; 156 162 157 163 struct mctp_skb_cb {
+16
include/net/mctpdevice.h
··· 14 14 #include <linux/types.h> 15 15 #include <linux/refcount.h> 16 16 17 + struct mctp_sk_key; 18 + 17 19 struct mctp_dev { 18 20 struct net_device *dev; 19 21 20 22 refcount_t refs; 21 23 22 24 unsigned int net; 25 + 26 + const struct mctp_netdev_ops *ops; 23 27 24 28 /* Only modified under RTNL. Reads have addrs_lock held */ 25 29 u8 *addrs; ··· 33 29 struct rcu_head rcu; 34 30 }; 35 31 32 + struct mctp_netdev_ops { 33 + void (*release_flow)(struct mctp_dev *dev, 34 + struct mctp_sk_key *key); 35 + }; 36 + 36 37 #define MCTP_INITIAL_DEFAULT_NET 1 37 38 38 39 struct mctp_dev *mctp_dev_get_rtnl(const struct net_device *dev); 39 40 struct mctp_dev *__mctp_dev_get(const struct net_device *dev); 40 41 42 + int mctp_register_netdev(struct net_device *dev, 43 + const struct mctp_netdev_ops *ops); 44 + void mctp_unregister_netdev(struct net_device *dev); 45 + 41 46 void mctp_dev_hold(struct mctp_dev *mdev); 42 47 void mctp_dev_put(struct mctp_dev *mdev); 48 + 49 + void mctp_dev_set_key(struct mctp_dev *dev, struct mctp_sk_key *key); 50 + void mctp_dev_release_key(struct mctp_dev *dev, struct mctp_sk_key *key); 43 51 44 52 #endif /* __NET_MCTPDEVICE_H */
+51
net/mctp/device.c
··· 260 260 } 261 261 } 262 262 263 + void mctp_dev_release_key(struct mctp_dev *dev, struct mctp_sk_key *key) 264 + __must_hold(&key->lock) 265 + { 266 + if (!dev) 267 + return; 268 + if (dev->ops && dev->ops->release_flow) 269 + dev->ops->release_flow(dev, key); 270 + key->dev = NULL; 271 + mctp_dev_put(dev); 272 + } 273 + 274 + void mctp_dev_set_key(struct mctp_dev *dev, struct mctp_sk_key *key) 275 + __must_hold(&key->lock) 276 + { 277 + mctp_dev_hold(dev); 278 + key->dev = dev; 279 + } 280 + 263 281 static struct mctp_dev *mctp_add_dev(struct net_device *dev) 264 282 { 265 283 struct mctp_dev *mdev; ··· 431 413 432 414 return NOTIFY_OK; 433 415 } 416 + 417 + static int mctp_register_netdevice(struct net_device *dev, 418 + const struct mctp_netdev_ops *ops) 419 + { 420 + struct mctp_dev *mdev; 421 + 422 + mdev = mctp_add_dev(dev); 423 + if (IS_ERR(mdev)) 424 + return PTR_ERR(mdev); 425 + 426 + mdev->ops = ops; 427 + 428 + return register_netdevice(dev); 429 + } 430 + 431 + int mctp_register_netdev(struct net_device *dev, 432 + const struct mctp_netdev_ops *ops) 433 + { 434 + int rc; 435 + 436 + rtnl_lock(); 437 + rc = mctp_register_netdevice(dev, ops); 438 + rtnl_unlock(); 439 + 440 + return rc; 441 + } 442 + EXPORT_SYMBOL_GPL(mctp_register_netdev); 443 + 444 + void mctp_unregister_netdev(struct net_device *dev) 445 + { 446 + unregister_netdev(dev); 447 + } 448 + EXPORT_SYMBOL_GPL(mctp_unregister_netdev); 434 449 435 450 static struct rtnl_af_ops mctp_af_ops = { 436 451 .family = AF_MCTP,
+53 -2
net/mctp/route.c
··· 29 29 static const unsigned int mctp_message_maxlen = 64 * 1024; 30 30 static const unsigned long mctp_key_lifetime = 6 * CONFIG_HZ; 31 31 32 + static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev); 33 + 32 34 /* route output callbacks */ 33 35 static int mctp_route_discard(struct mctp_route *route, struct sk_buff *skb) 34 36 { ··· 154 152 155 153 void mctp_key_unref(struct mctp_sk_key *key) 156 154 { 157 - if (refcount_dec_and_test(&key->refs)) 158 - kfree(key); 155 + unsigned long flags; 156 + 157 + if (!refcount_dec_and_test(&key->refs)) 158 + return; 159 + 160 + /* even though no refs exist here, the lock allows us to stay 161 + * consistent with the locking requirement of mctp_dev_release_key 162 + */ 163 + spin_lock_irqsave(&key->lock, flags); 164 + mctp_dev_release_key(key->dev, key); 165 + spin_unlock_irqrestore(&key->lock, flags); 166 + 167 + kfree(key); 159 168 } 160 169 161 170 static int mctp_key_add(struct mctp_sk_key *key, struct mctp_sock *msk) ··· 217 204 key->reasm_head = NULL; 218 205 key->reasm_dead = true; 219 206 key->valid = false; 207 + mctp_dev_release_key(key->dev, key); 220 208 spin_unlock_irqrestore(&key->lock, flags); 221 209 222 210 spin_lock_irqsave(&net->mctp.keys_lock, flags); ··· 235 221 kfree_skb(skb); 236 222 237 223 } 224 + 225 + #ifdef CONFIG_MCTP_FLOWS 226 + static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key) 227 + { 228 + struct mctp_flow *flow; 229 + 230 + flow = skb_ext_add(skb, SKB_EXT_MCTP); 231 + if (!flow) 232 + return; 233 + 234 + refcount_inc(&key->refs); 235 + flow->key = key; 236 + } 237 + 238 + static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) 239 + { 240 + struct mctp_sk_key *key; 241 + struct mctp_flow *flow; 242 + 243 + flow = skb_ext_find(skb, SKB_EXT_MCTP); 244 + if (!flow) 245 + return; 246 + 247 + key = flow->key; 248 + 249 + if (WARN_ON(key->dev && key->dev != dev)) 250 + return; 251 + 252 + mctp_dev_set_key(dev, key); 253 + } 254 + #else 255 + static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key) {} 256 + static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) {} 257 + #endif 238 258 239 259 static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb) 240 260 { ··· 512 464 kfree_skb(skb); 513 465 return -EHOSTUNREACH; 514 466 } 467 + 468 + mctp_flow_prepare_output(skb, route->dev); 515 469 516 470 rc = dev_queue_xmit(skb); 517 471 if (rc) ··· 853 803 rc = PTR_ERR(key); 854 804 goto out_release; 855 805 } 806 + mctp_skb_set_flow(skb, key); 856 807 /* done with the key in this scope */ 857 808 mctp_key_unref(key); 858 809 tag |= MCTP_HDR_FLAG_TO;