Skip to content

Commit 5e4a8cc

Browse files
q2venkuba-moo
authored andcommitted
Revert "ipv6: Factorise ip6_route_multipath_add()."
Commit 71c0efb ("ipv6: Factorise ip6_route_multipath_add().") split a loop in ip6_route_multipath_add() so that we can put rcu_read_lock() between ip6_route_info_create() and ip6_route_info_create_nh(). We no longer need to do so as ip6_route_info_create_nh() does not require RCU now. Let's revert the commit to simplify the code. Signed-off-by: Kuniyuki Iwashima <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent cefe6e1 commit 5e4a8cc

File tree

1 file changed

+70
-123
lines changed

1 file changed

+70
-123
lines changed

net/ipv6/route.c

Lines changed: 70 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -5335,131 +5335,29 @@ struct rt6_nh {
53355335
struct fib6_info *fib6_info;
53365336
struct fib6_config r_cfg;
53375337
struct list_head list;
5338-
int weight;
53395338
};
53405339

5341-
static void ip6_route_mpath_info_cleanup(struct list_head *rt6_nh_list)
5340+
static int ip6_route_info_append(struct list_head *rt6_nh_list,
5341+
struct fib6_info *rt,
5342+
struct fib6_config *r_cfg)
53425343
{
5343-
struct rt6_nh *nh, *nh_next;
5344+
struct rt6_nh *nh;
53445345

5345-
list_for_each_entry_safe(nh, nh_next, rt6_nh_list, list) {
5346-
struct fib6_info *rt = nh->fib6_info;
5347-
5348-
if (rt) {
5349-
free_percpu(rt->fib6_nh->nh_common.nhc_pcpu_rth_output);
5350-
free_percpu(rt->fib6_nh->rt6i_pcpu);
5351-
ip_fib_metrics_put(rt->fib6_metrics);
5352-
kfree(rt);
5353-
}
5354-
5355-
list_del(&nh->list);
5356-
kfree(nh);
5346+
list_for_each_entry(nh, rt6_nh_list, list) {
5347+
/* check if fib6_info already exists */
5348+
if (rt6_duplicate_nexthop(nh->fib6_info, rt))
5349+
return -EEXIST;
53575350
}
5358-
}
5359-
5360-
static int ip6_route_mpath_info_create(struct list_head *rt6_nh_list,
5361-
struct fib6_config *cfg,
5362-
struct netlink_ext_ack *extack)
5363-
{
5364-
struct rtnexthop *rtnh;
5365-
int remaining;
5366-
int err;
5367-
5368-
remaining = cfg->fc_mp_len;
5369-
rtnh = (struct rtnexthop *)cfg->fc_mp;
5370-
5371-
/* Parse a Multipath Entry and build a list (rt6_nh_list) of
5372-
* fib6_info structs per nexthop
5373-
*/
5374-
while (rtnh_ok(rtnh, remaining)) {
5375-
struct fib6_config r_cfg;
5376-
struct fib6_info *rt;
5377-
struct rt6_nh *nh;
5378-
int attrlen;
5379-
5380-
nh = kzalloc(sizeof(*nh), GFP_KERNEL);
5381-
if (!nh) {
5382-
err = -ENOMEM;
5383-
goto err;
5384-
}
53855351

5386-
list_add_tail(&nh->list, rt6_nh_list);
5387-
5388-
memcpy(&r_cfg, cfg, sizeof(*cfg));
5389-
if (rtnh->rtnh_ifindex)
5390-
r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
5391-
5392-
attrlen = rtnh_attrlen(rtnh);
5393-
if (attrlen > 0) {
5394-
struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
5395-
5396-
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
5397-
if (nla) {
5398-
r_cfg.fc_gateway = nla_get_in6_addr(nla);
5399-
r_cfg.fc_flags |= RTF_GATEWAY;
5400-
}
5401-
5402-
r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP);
5403-
nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
5404-
if (nla)
5405-
r_cfg.fc_encap_type = nla_get_u16(nla);
5406-
}
5407-
5408-
r_cfg.fc_flags |= (rtnh->rtnh_flags & RTNH_F_ONLINK);
5409-
5410-
rt = ip6_route_info_create(&r_cfg, GFP_KERNEL, extack);
5411-
if (IS_ERR(rt)) {
5412-
err = PTR_ERR(rt);
5413-
goto err;
5414-
}
5415-
5416-
nh->fib6_info = rt;
5417-
nh->weight = rtnh->rtnh_hops + 1;
5418-
memcpy(&nh->r_cfg, &r_cfg, sizeof(r_cfg));
5352+
nh = kzalloc(sizeof(*nh), GFP_KERNEL);
5353+
if (!nh)
5354+
return -ENOMEM;
54195355

5420-
rtnh = rtnh_next(rtnh, &remaining);
5421-
}
5356+
nh->fib6_info = rt;
5357+
memcpy(&nh->r_cfg, r_cfg, sizeof(*r_cfg));
5358+
list_add_tail(&nh->list, rt6_nh_list);
54225359

54235360
return 0;
5424-
err:
5425-
ip6_route_mpath_info_cleanup(rt6_nh_list);
5426-
return err;
5427-
}
5428-
5429-
static int ip6_route_mpath_info_create_nh(struct list_head *rt6_nh_list,
5430-
struct netlink_ext_ack *extack)
5431-
{
5432-
struct rt6_nh *nh, *nh_next, *nh_tmp;
5433-
LIST_HEAD(tmp);
5434-
int err;
5435-
5436-
list_for_each_entry_safe(nh, nh_next, rt6_nh_list, list) {
5437-
struct fib6_info *rt = nh->fib6_info;
5438-
5439-
err = ip6_route_info_create_nh(rt, &nh->r_cfg, extack);
5440-
if (err) {
5441-
nh->fib6_info = NULL;
5442-
goto err;
5443-
}
5444-
5445-
rt->fib6_nh->fib_nh_weight = nh->weight;
5446-
5447-
list_move_tail(&nh->list, &tmp);
5448-
5449-
list_for_each_entry(nh_tmp, rt6_nh_list, list) {
5450-
/* check if fib6_info already exists */
5451-
if (rt6_duplicate_nexthop(nh_tmp->fib6_info, rt)) {
5452-
err = -EEXIST;
5453-
goto err;
5454-
}
5455-
}
5456-
}
5457-
out:
5458-
list_splice(&tmp, rt6_nh_list);
5459-
return err;
5460-
err:
5461-
ip6_route_mpath_info_cleanup(rt6_nh_list);
5462-
goto out;
54635361
}
54645362

54655363
static void ip6_route_mpath_notify(struct fib6_info *rt,
@@ -5519,11 +5417,16 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
55195417
struct fib6_info *rt_notif = NULL, *rt_last = NULL;
55205418
struct nl_info *info = &cfg->fc_nlinfo;
55215419
struct rt6_nh *nh, *nh_safe;
5420+
struct fib6_config r_cfg;
5421+
struct rtnexthop *rtnh;
55225422
LIST_HEAD(rt6_nh_list);
55235423
struct rt6_nh *err_nh;
5424+
struct fib6_info *rt;
55245425
__u16 nlflags;
5525-
int nhn = 0;
5426+
int remaining;
5427+
int attrlen;
55265428
int replace;
5429+
int nhn = 0;
55275430
int err;
55285431

55295432
replace = (cfg->fc_nlinfo.nlh &&
@@ -5533,13 +5436,57 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
55335436
if (info->nlh && info->nlh->nlmsg_flags & NLM_F_APPEND)
55345437
nlflags |= NLM_F_APPEND;
55355438

5536-
err = ip6_route_mpath_info_create(&rt6_nh_list, cfg, extack);
5537-
if (err)
5538-
return err;
5439+
remaining = cfg->fc_mp_len;
5440+
rtnh = (struct rtnexthop *)cfg->fc_mp;
55395441

5540-
err = ip6_route_mpath_info_create_nh(&rt6_nh_list, extack);
5541-
if (err)
5542-
goto cleanup;
5442+
/* Parse a Multipath Entry and build a list (rt6_nh_list) of
5443+
* fib6_info structs per nexthop
5444+
*/
5445+
while (rtnh_ok(rtnh, remaining)) {
5446+
memcpy(&r_cfg, cfg, sizeof(*cfg));
5447+
if (rtnh->rtnh_ifindex)
5448+
r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
5449+
5450+
attrlen = rtnh_attrlen(rtnh);
5451+
if (attrlen > 0) {
5452+
struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
5453+
5454+
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
5455+
if (nla) {
5456+
r_cfg.fc_gateway = nla_get_in6_addr(nla);
5457+
r_cfg.fc_flags |= RTF_GATEWAY;
5458+
}
5459+
5460+
r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP);
5461+
nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
5462+
if (nla)
5463+
r_cfg.fc_encap_type = nla_get_u16(nla);
5464+
}
5465+
5466+
r_cfg.fc_flags |= (rtnh->rtnh_flags & RTNH_F_ONLINK);
5467+
rt = ip6_route_info_create(&r_cfg, GFP_KERNEL, extack);
5468+
if (IS_ERR(rt)) {
5469+
err = PTR_ERR(rt);
5470+
rt = NULL;
5471+
goto cleanup;
5472+
}
5473+
5474+
err = ip6_route_info_create_nh(rt, &r_cfg, extack);
5475+
if (err) {
5476+
rt = NULL;
5477+
goto cleanup;
5478+
}
5479+
5480+
rt->fib6_nh->fib_nh_weight = rtnh->rtnh_hops + 1;
5481+
5482+
err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
5483+
if (err) {
5484+
fib6_info_release(rt);
5485+
goto cleanup;
5486+
}
5487+
5488+
rtnh = rtnh_next(rtnh, &remaining);
5489+
}
55435490

55445491
/* for add and replace send one notification with all nexthops.
55455492
* Skip the notification in fib6_add_rt2node and send one with

0 commit comments

Comments
 (0)