Skip to content

Commit

Permalink
nexthop: Support bucket get [xxx]
Browse files Browse the repository at this point in the history
  • Loading branch information
pmachata committed Dec 11, 2020
1 parent cbc4a06 commit 9ef9862
Showing 1 changed file with 107 additions and 1 deletion.
108 changes: 107 additions & 1 deletion net/ipv4/nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ static const struct nla_policy rtm_nh_res_policy_new[NHA_MAX + 1] = {
[NHA_RES_GROUP_UNBALANCED_TIMER]= { .type = NLA_U32 },
};

static const struct nla_policy rtm_nh_policy_get_bucket[NHA_MAX + 1] = {
[NHA_ID] = { .type = NLA_U32 },
[NHA_RES_BUCKET] = { .type = NLA_NESTED },
};

static const struct nla_policy rtm_nh_res_bucket_policy_get[NHA_MAX + 1] = {
[NHA_RES_BUCKET_INDEX] = { .type = NLA_U32 },
};

static bool nexthop_notifiers_is_empty(struct net *net)
{
return !net->nexthop.notifier_chain.head;
Expand Down Expand Up @@ -2966,6 +2975,103 @@ static int rtm_dump_nexthop_bucket(struct sk_buff *skb,
return err;
}

static int nh_valid_get_bucket_req_res_bucket(struct nlattr *res,
u32 *bucket_idx,
struct netlink_ext_ack *extack)
{
struct nlattr *tb[NHA_RES_BUCKET_MAX + 1];
int err;

err = nla_parse_nested(tb, NHA_RES_BUCKET_MAX, res,
rtm_nh_res_bucket_policy_get, extack);
if (err < 0)
return err;

if (!tb[NHA_RES_BUCKET_INDEX]) {
NL_SET_ERR_MSG(extack, "Bucket index is missing");
return -EINVAL;
}

*bucket_idx = nla_get_u32(tb[NHA_RES_BUCKET_INDEX]);
return 0;
}

static int nh_valid_get_bucket_req(const struct nlmsghdr *nlh,
u32 *id, u32 *bucket_idx,
struct netlink_ext_ack *extack)
{
struct nlattr *tb[NHA_MAX + 1];
int err;

err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
rtm_nh_policy_get_bucket, extack);
if (err < 0)
return err;

err = __nh_valid_get_del_req(nlh, tb, id, extack);
if (err)
return err;

if (!tb[NHA_RES_BUCKET]) {
NL_SET_ERR_MSG(extack, "Bucket information is missing");
return -EINVAL;
}

err = nh_valid_get_bucket_req_res_bucket(tb[NHA_RES_BUCKET],
bucket_idx, extack);
if (err)
return err;

return 0;
}

/* rtnl */
static int rtm_get_nexthop_bucket(struct sk_buff *in_skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{
struct net *net = sock_net(in_skb->sk);
struct nh_res_table *res_table;
struct sk_buff *skb = NULL;
struct nh_group *nhg;
struct nexthop *nh;
u32 id, bucket_idx;
int err;

err = nh_valid_get_bucket_req(nlh, &id, &bucket_idx, extack);
if (err)
return err;

nh = nexthop_find_group_resilient(net, id, extack);
if (IS_ERR(nh))
return PTR_ERR(nh);

nhg = rtnl_dereference(nh->nh_grp);
res_table = rtnl_dereference(nhg->res_table);
if (bucket_idx >= res_table->num_nh_buckets) {
NL_SET_ERR_MSG(extack, "Bucket index out of bounds");
return -ENOENT;
}

skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
if (!skb)
return -ENOBUFS;

err = nh_fill_res_bucket(skb, nh, &res_table->nh_buckets[bucket_idx],
bucket_idx, RTM_NEWNEXTHOPBUCKET,
NETLINK_CB(in_skb).portid, nlh->nlmsg_seq,
0, extack);
if (err < 0) {
WARN_ON(err == -EMSGSIZE);
goto errout_free;
}

return rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);

errout_free:
kfree_skb(skb);
return err;
}

static void nexthop_sync_mtu(struct net_device *dev, u32 orig_mtu)
{
unsigned int hash = nh_dev_hashfn(dev->ifindex);
Expand Down Expand Up @@ -3185,7 +3291,7 @@ static int __init nexthop_init(void)
rtnl_register(PF_INET6, RTM_NEWNEXTHOP, rtm_new_nexthop, NULL, 0);
rtnl_register(PF_INET6, RTM_GETNEXTHOP, NULL, rtm_dump_nexthop, 0);

rtnl_register(PF_UNSPEC, RTM_GETNEXTHOPBUCKET, NULL,
rtnl_register(PF_UNSPEC, RTM_GETNEXTHOPBUCKET, rtm_get_nexthop_bucket,
rtm_dump_nexthop_bucket, 0);

return 0;
Expand Down

0 comments on commit 9ef9862

Please sign in to comment.