Commit 979e276e authored by David Ahern's avatar David Ahern Committed by David S. Miller

net: Use common nexthop init and release helpers

With fib_nh_common in place, move common initialization and release
code into helpers used by both ipv4 and ipv6. For the moment, the init
is just the lwt encap and the release is both the netdev reference and
the the lwt state reference. More will be added later.
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Acked-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f1741730
...@@ -441,6 +441,10 @@ int fib_nh_init(struct net *net, struct fib_nh *fib_nh, ...@@ -441,6 +441,10 @@ int fib_nh_init(struct net *net, struct fib_nh *fib_nh,
struct fib_config *cfg, int nh_weight, struct fib_config *cfg, int nh_weight,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
void fib_nh_release(struct net *net, struct fib_nh *fib_nh); void fib_nh_release(struct net *net, struct fib_nh *fib_nh);
int fib_nh_common_init(struct fib_nh_common *nhc, struct nlattr *fc_encap,
u16 fc_encap_type, void *cfg, gfp_t gfp_flags,
struct netlink_ext_ack *extack);
void fib_nh_common_release(struct fib_nh_common *nhc);
/* Exported by fib_trie.c */ /* Exported by fib_trie.c */
void fib_trie_init(void); void fib_trie_init(void);
......
...@@ -204,16 +204,22 @@ static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp) ...@@ -204,16 +204,22 @@ static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp)
free_percpu(rtp); free_percpu(rtp);
} }
void fib_nh_common_release(struct fib_nh_common *nhc)
{
if (nhc->nhc_dev)
dev_put(nhc->nhc_dev);
lwtstate_put(nhc->nhc_lwtstate);
}
EXPORT_SYMBOL_GPL(fib_nh_common_release);
void fib_nh_release(struct net *net, struct fib_nh *fib_nh) void fib_nh_release(struct net *net, struct fib_nh *fib_nh)
{ {
#ifdef CONFIG_IP_ROUTE_CLASSID #ifdef CONFIG_IP_ROUTE_CLASSID
if (fib_nh->nh_tclassid) if (fib_nh->nh_tclassid)
net->ipv4.fib_num_tclassid_users--; net->ipv4.fib_num_tclassid_users--;
#endif #endif
if (fib_nh->fib_nh_dev) fib_nh_common_release(&fib_nh->nh_common);
dev_put(fib_nh->fib_nh_dev);
lwtstate_put(fib_nh->fib_nh_lws);
free_nh_exceptions(fib_nh); free_nh_exceptions(fib_nh);
rt_fibinfo_free_cpus(fib_nh->nh_pcpu_rth_output); rt_fibinfo_free_cpus(fib_nh->nh_pcpu_rth_output);
rt_fibinfo_free(&fib_nh->nh_rth_input); rt_fibinfo_free(&fib_nh->nh_rth_input);
...@@ -462,6 +468,30 @@ static int fib_detect_death(struct fib_info *fi, int order, ...@@ -462,6 +468,30 @@ static int fib_detect_death(struct fib_info *fi, int order,
return 1; return 1;
} }
int fib_nh_common_init(struct fib_nh_common *nhc, struct nlattr *encap,
u16 encap_type, void *cfg, gfp_t gfp_flags,
struct netlink_ext_ack *extack)
{
if (encap) {
struct lwtunnel_state *lwtstate;
int err;
if (encap_type == LWTUNNEL_ENCAP_NONE) {
NL_SET_ERR_MSG(extack, "LWT encap type not specified");
return -EINVAL;
}
err = lwtunnel_build_state(encap_type, encap, nhc->nhc_family,
cfg, &lwtstate, extack);
if (err)
return err;
nhc->nhc_lwtstate = lwtstate_get(lwtstate);
}
return 0;
}
EXPORT_SYMBOL_GPL(fib_nh_common_init);
int fib_nh_init(struct net *net, struct fib_nh *nh, int fib_nh_init(struct net *net, struct fib_nh *nh,
struct fib_config *cfg, int nh_weight, struct fib_config *cfg, int nh_weight,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
...@@ -474,22 +504,10 @@ int fib_nh_init(struct net *net, struct fib_nh *nh, ...@@ -474,22 +504,10 @@ int fib_nh_init(struct net *net, struct fib_nh *nh,
if (!nh->nh_pcpu_rth_output) if (!nh->nh_pcpu_rth_output)
goto err_out; goto err_out;
if (cfg->fc_encap) { err = fib_nh_common_init(&nh->nh_common, cfg->fc_encap,
struct lwtunnel_state *lwtstate; cfg->fc_encap_type, cfg, GFP_KERNEL, extack);
if (err)
err = -EINVAL; goto init_failure;
if (cfg->fc_encap_type == LWTUNNEL_ENCAP_NONE) {
NL_SET_ERR_MSG(extack, "LWT encap type not specified");
goto lwt_failure;
}
err = lwtunnel_build_state(cfg->fc_encap_type,
cfg->fc_encap, AF_INET, cfg,
&lwtstate, extack);
if (err)
goto lwt_failure;
nh->fib_nh_lws = lwtstate_get(lwtstate);
}
nh->fib_nh_oif = cfg->fc_oif; nh->fib_nh_oif = cfg->fc_oif;
if (cfg->fc_gw) { if (cfg->fc_gw) {
...@@ -508,7 +526,7 @@ int fib_nh_init(struct net *net, struct fib_nh *nh, ...@@ -508,7 +526,7 @@ int fib_nh_init(struct net *net, struct fib_nh *nh,
#endif #endif
return 0; return 0;
lwt_failure: init_failure:
rt_fibinfo_free_cpus(nh->nh_pcpu_rth_output); rt_fibinfo_free_cpus(nh->nh_pcpu_rth_output);
nh->nh_pcpu_rth_output = NULL; nh->nh_pcpu_rth_output = NULL;
err_out: err_out:
......
...@@ -2934,18 +2934,6 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh, ...@@ -2934,18 +2934,6 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
fib6_nh->fib_nh_flags |= RTNH_F_ONLINK; fib6_nh->fib_nh_flags |= RTNH_F_ONLINK;
} }
if (cfg->fc_encap) {
struct lwtunnel_state *lwtstate;
err = lwtunnel_build_state(cfg->fc_encap_type,
cfg->fc_encap, AF_INET6, cfg,
&lwtstate, extack);
if (err)
goto out;
fib6_nh->fib_nh_lws = lwtstate_get(lwtstate);
}
fib6_nh->fib_nh_weight = 1; fib6_nh->fib_nh_weight = 1;
/* We cannot add true routes via loopback here, /* We cannot add true routes via loopback here,
...@@ -2999,6 +2987,10 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh, ...@@ -2999,6 +2987,10 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
!netif_carrier_ok(dev)) !netif_carrier_ok(dev))
fib6_nh->fib_nh_flags |= RTNH_F_LINKDOWN; fib6_nh->fib_nh_flags |= RTNH_F_LINKDOWN;
err = fib_nh_common_init(&fib6_nh->nh_common, cfg->fc_encap,
cfg->fc_encap_type, cfg, gfp_flags, extack);
if (err)
goto out;
set_dev: set_dev:
fib6_nh->fib_nh_dev = dev; fib6_nh->fib_nh_dev = dev;
fib6_nh->fib_nh_oif = dev->ifindex; fib6_nh->fib_nh_oif = dev->ifindex;
...@@ -3019,10 +3011,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh, ...@@ -3019,10 +3011,7 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
void fib6_nh_release(struct fib6_nh *fib6_nh) void fib6_nh_release(struct fib6_nh *fib6_nh)
{ {
lwtstate_put(fib6_nh->fib_nh_lws); fib_nh_common_release(&fib6_nh->nh_common);
if (fib6_nh->fib_nh_dev)
dev_put(fib6_nh->fib_nh_dev);
} }
static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg, static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment