Skip to content

Commit

Permalink
mctp: Pass flow data & flow release events to drivers
Browse files Browse the repository at this point in the history
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.

Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
  • Loading branch information
jk-ozlabs authored and intel-lab-lkp committed Oct 28, 2021
1 parent 587328c commit 27aeac2
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 2 deletions.
5 changes: 5 additions & 0 deletions include/net/mctp.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ struct mctp_sk_key {

/* expiry timeout; valid (above) cleared on expiry */
unsigned long expiry;

/* free to use for device flow state tracking. Initialised to
* zero on inital key creation*/
unsigned long dev_flow_state;
struct mctp_dev *dev;
};

struct mctp_skb_cb {
Expand Down
14 changes: 14 additions & 0 deletions include/net/mctpdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ struct mctp_dev {

unsigned int net;

const struct mctp_netdev_ops *ops;

/* Only modified under RTNL. Reads have addrs_lock held */
u8 *addrs;
size_t num_addrs;
Expand All @@ -29,12 +31,24 @@ struct mctp_dev {
struct rcu_head rcu;
};

struct mctp_netdev_ops {
void (*release_flow)(struct mctp_dev *dev,
struct mctp_sk_key *key);
};

#define MCTP_INITIAL_DEFAULT_NET 1

struct mctp_dev *mctp_dev_get_rtnl(const struct net_device *dev);
struct mctp_dev *__mctp_dev_get(const struct net_device *dev);

int mctp_register_netdev(struct net_device *dev,
const struct mctp_netdev_ops *ops);
void mctp_unregister_netdev(struct net_device *dev);

void mctp_dev_hold(struct mctp_dev *mdev);
void mctp_dev_put(struct mctp_dev *mdev);

void mctp_dev_set_key(struct mctp_dev *dev, struct mctp_sk_key *key);
void mctp_dev_release_key(struct mctp_dev *dev, struct mctp_sk_key *key);

#endif /* __NET_MCTPDEVICE_H */
51 changes: 51 additions & 0 deletions net/mctp/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,24 @@ void mctp_dev_put(struct mctp_dev *mdev)
}
}

void mctp_dev_release_key(struct mctp_dev *dev, struct mctp_sk_key *key)
__must_hold(&key->lock)
{
if (!dev)
return;
if (dev->ops && dev->ops->release_flow)
dev->ops->release_flow(dev, key);
key->dev = NULL;
mctp_dev_put(dev);
}

void mctp_dev_set_key(struct mctp_dev *dev, struct mctp_sk_key *key)
__must_hold(&key->lock)
{
mctp_dev_hold(dev);
key->dev = dev;
}

static struct mctp_dev *mctp_add_dev(struct net_device *dev)
{
struct mctp_dev *mdev;
Expand Down Expand Up @@ -414,6 +432,39 @@ static int mctp_dev_notify(struct notifier_block *this, unsigned long event,
return NOTIFY_OK;
}

static int mctp_register_netdevice(struct net_device *dev,
const struct mctp_netdev_ops *ops)
{
struct mctp_dev *mdev;

mdev = mctp_add_dev(dev);
if (IS_ERR(mdev))
return PTR_ERR(mdev);

mdev->ops = ops;

return register_netdevice(dev);
}

int mctp_register_netdev(struct net_device *dev,
const struct mctp_netdev_ops *ops)
{
int rc;

rtnl_lock();
rc = mctp_register_netdevice(dev, ops);
rtnl_unlock();

return rc;
}
EXPORT_SYMBOL_GPL(mctp_register_netdev);

void mctp_unregister_netdev(struct net_device *dev)
{
unregister_netdev(dev);
}
EXPORT_SYMBOL_GPL(mctp_unregister_netdev);

static struct rtnl_af_ops mctp_af_ops = {
.family = AF_MCTP,
.fill_link_af = mctp_fill_link_af,
Expand Down
55 changes: 53 additions & 2 deletions net/mctp/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
static const unsigned int mctp_message_maxlen = 64 * 1024;
static const unsigned long mctp_key_lifetime = 6 * CONFIG_HZ;

static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev);

/* route output callbacks */
static int mctp_route_discard(struct mctp_route *route, struct sk_buff *skb)
{
Expand Down Expand Up @@ -152,8 +154,19 @@ static struct mctp_sk_key *mctp_key_alloc(struct mctp_sock *msk,

void mctp_key_unref(struct mctp_sk_key *key)
{
if (refcount_dec_and_test(&key->refs))
kfree(key);
unsigned long flags;

if (!refcount_dec_and_test(&key->refs))
return;

/* even though no refs exist here, the lock allows us to stay
* consistent with the locking requirement of mctp_dev_release_key
*/
spin_lock_irqsave(&key->lock, flags);
mctp_dev_release_key(key->dev, key);
spin_unlock_irqrestore(&key->lock, flags);

kfree(key);
}

static int mctp_key_add(struct mctp_sk_key *key, struct mctp_sock *msk)
Expand Down Expand Up @@ -204,6 +217,7 @@ static void __mctp_key_unlock_drop(struct mctp_sk_key *key, struct net *net,
key->reasm_head = NULL;
key->reasm_dead = true;
key->valid = false;
mctp_dev_release_key(key->dev, key);
spin_unlock_irqrestore(&key->lock, flags);

spin_lock_irqsave(&net->mctp.keys_lock, flags);
Expand All @@ -222,6 +236,40 @@ static void __mctp_key_unlock_drop(struct mctp_sk_key *key, struct net *net,

}

#ifdef CONFIG_MCTP_FLOWS
static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key)
{
struct mctp_flow *flow;

flow = skb_ext_add(skb, SKB_EXT_MCTP);
if (!flow)
return;

refcount_inc(&key->refs);
flow->key = key;
}

static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev)
{
struct mctp_sk_key *key;
struct mctp_flow *flow;

flow = skb_ext_find(skb, SKB_EXT_MCTP);
if (!flow)
return;

key = flow->key;

if (WARN_ON(key->dev && key->dev != dev))
return;

mctp_dev_set_key(dev, key);
}
#else
static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key) {}
static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) {}
#endif

static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
{
struct mctp_hdr *hdr = mctp_hdr(skb);
Expand Down Expand Up @@ -465,6 +513,8 @@ static int mctp_route_output(struct mctp_route *route, struct sk_buff *skb)
return -EHOSTUNREACH;
}

mctp_flow_prepare_output(skb, route->dev);

rc = dev_queue_xmit(skb);
if (rc)
rc = net_xmit_errno(rc);
Expand Down Expand Up @@ -803,6 +853,7 @@ int mctp_local_output(struct sock *sk, struct mctp_route *rt,
rc = PTR_ERR(key);
goto out_release;
}
mctp_skb_set_flow(skb, key);
/* done with the key in this scope */
mctp_key_unref(key);
tag |= MCTP_HDR_FLAG_TO;
Expand Down

0 comments on commit 27aeac2

Please sign in to comment.