Merge pull request #24 from kenieevan/master

introduce ipvs_mode to share ipvs service and connection between network namespace
This commit is contained in:
fuhaiwang 2020-09-23 19:02:00 +08:00 committed by GitHub
commit d4619cc0fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 236 additions and 55 deletions

View File

@ -32,7 +32,7 @@
#include <net/netfilter/nf_conntrack.h>
#endif
#include <net/net_namespace.h> /* Netw namespace */
#include <linux/netdevice.h>
#define IP_VS_HDR_INVERSE 1
#define IP_VS_HDR_ICMP 2
@ -1712,6 +1712,15 @@ struct bpf_sym_addrs {
const struct file_operations *bpf_prog_fops;
};
struct net *ip_vs_skb_net(struct sk_buff *skb);
enum {
IPVS_ORIGIN_MODE,
IPVS_BPF_MODE,
IPVS_SHARE_NS_MODE,
IPVS_MAX_MODE
};
extern unsigned int ipvs_mode;
extern struct net init_net;
extern struct bpf_sym_addrs resolve_addrs;
extern struct bpf_map *conntrack_map;
extern bool bpf_mode_on;
@ -1738,5 +1747,4 @@ extern struct cidrs __rcu *non_masq_cidrs;
#define IP_VS_SVC_TAB_BITS 8
#define IP_VS_SVC_TAB_SIZE (1 << IP_VS_SVC_TAB_BITS)
extern struct hlist_head ip_vs_svc_table[IP_VS_SVC_TAB_SIZE];
#endif /* _NET_IP_VS_H */

View File

@ -54,15 +54,26 @@ static int ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS;
module_param_named(conn_tab_bits, ip_vs_conn_tab_bits, int, 0444);
MODULE_PARM_DESC(conn_tab_bits, "Set connections' hash size");
bool bpf_mode_on;
module_param_named(mode, bpf_mode_on, bool, 0444);
MODULE_PARM_DESC(mode, "set bpf mode in IPVS");
EXPORT_SYMBOL_GPL(bpf_mode_on);
unsigned int ipvs_mode;
module_param_named(mode, ipvs_mode, uint, 0444);
MODULE_PARM_DESC(mode, "set mode in IPVS");
EXPORT_SYMBOL_GPL(ipvs_mode);
/* size and mask values */
int ip_vs_conn_tab_size __read_mostly;
static int ip_vs_conn_tab_mask __read_mostly;
/* retrieve origin net in skb for xmit
* local-out: ip_queue_xmit->skb_dst_set_noref
* local-in: ip_route_input_slow set it
*/
struct net *ip_vs_skb_net(struct sk_buff *skb)
{
if (skb_dst(skb))
return dev_net(skb_dst(skb)->dev);
return NULL;
}
/*
* Connection hash table: for input and output packets lookups of IPVS
*/
@ -241,7 +252,7 @@ static void ip_vs_unlink_bpf(struct ip_vs_conn *cp)
struct bpf_map *map;
int err = 0;
if (!bpf_mode_on)
if (ipvs_mode != IPVS_BPF_MODE)
return;
k.sip = cp->caddr.ip;
@ -319,7 +330,7 @@ static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
hlist_del_rcu(&cp->c_list);
cp->flags &= ~IP_VS_CONN_F_HASHED;
ret = true;
if (bpf_mode_on)
if (ipvs_mode == IPVS_BPF_MODE)
ip_vs_unlink_bpf(cp);
}
} else
@ -1113,7 +1124,7 @@ static bool ip_vs_conn_new_bpf(struct ip_vs_dest *dest,
BUILD_BUG_ON(sizeof(atomic_t) != 4);
if (!bpf_mode_on)
if (ipvs_mode != IPVS_BPF_MODE)
return true;
svc = rcu_dereference(dest->svc);
@ -1251,7 +1262,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
p->protocol);
int skip = 0;
if (bpf_mode_on) {
if (ipvs_mode == IPVS_BPF_MODE) {
if (!ip_vs_conn_new_bpf(dest, flags, p, &skip))
return NULL;
}
@ -1270,7 +1281,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
cp->protocol = p->protocol;
ip_vs_addr_set(p->af, &cp->caddr, p->caddr);
cp->cport = p->cport;
if (bpf_mode_on)
if (ipvs_mode == IPVS_BPF_MODE)
cp->skip_bpf = skip;
/* proto should only be IPPROTO_IP if p->vaddr is a fwmark */
ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
@ -1795,7 +1806,7 @@ int __init ip_vs_conn_init(void)
spin_lock_init(&__ip_vs_conntbl_lock_array[idx].l);
}
if (bpf_mode_on) {
if (ipvs_mode == IPVS_BPF_MODE) {
for (idx = 0; idx < BPF_CONN_LOCKS; idx++)
spin_lock_init(&bpf_conntrack_locks[idx]);
}

View File

@ -747,11 +747,18 @@ static int ip_route_me_harder2(struct net *net, struct sk_buff *skb,
static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
struct sk_buff *skb, unsigned int hooknum)
{
if (!bpf_mode_on && !sysctl_snat_reroute(ipvs))
struct net *net;
if (ipvs_mode != IPVS_BPF_MODE && !sysctl_snat_reroute(ipvs))
return 0;
/* Reroute replies only to remote clients (FORWARD and LOCAL_OUT) */
if (NF_INET_LOCAL_IN == hooknum)
return 0;
net = ipvs->net;
if (ipvs_mode == IPVS_SHARE_NS_MODE)
net = ip_vs_skb_net(skb);
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
struct dst_entry *dst = skb_dst(skb);
@ -761,9 +768,9 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af,
return 1;
} else
#endif
if (!bpf_mode_on) {
if (ipvs_mode != IPVS_BPF_MODE) {
if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) &&
ip_route_me_harder(ipvs->net, skb, RTN_LOCAL) != 0)
ip_route_me_harder(net, skb, RTN_LOCAL) != 0)
return 1;
} else {
if (ip_route_me_harder2(ipvs->net, skb, RTN_LOCAL) != 0)
@ -930,12 +937,12 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
else
ip_vs_update_conntrack(skb, cp, 0);
if (bpf_mode_on)
if (ipvs_mode == IPVS_BPF_MODE)
(*(resolve_addrs.ip_finish_output))(cp->ipvs->net, skb->sk,
skb);
ignore_cp:
if (bpf_mode_on)
if (ipvs_mode == IPVS_BPF_MODE)
verdict = NF_STOLEN;
else
verdict = NF_ACCEPT;
@ -1354,14 +1361,14 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
else
ip_vs_update_conntrack(skb, cp, 0);
if (bpf_mode_on)
if (ipvs_mode == IPVS_BPF_MODE)
(*(resolve_addrs.ip_finish_output))(cp->ipvs->net, skb->sk,
skb);
ip_vs_conn_put(cp);
LeaveFunction(11);
if (bpf_mode_on)
if (ipvs_mode == IPVS_BPF_MODE)
return NF_STOLEN;
else
return NF_ACCEPT;
@ -1372,6 +1379,12 @@ drop:
return NF_STOLEN;
}
static void switch_netns(struct netns_ipvs **ipvs, struct sk_buff *skb)
{
if (ipvs_mode == IPVS_SHARE_NS_MODE)
*ipvs = net_ipvs(&init_net);
}
/*
* Check if outgoing packet belongs to the established ip_vs_conn.
* bpf: previously, local-in, forward, and local-out may call here!
@ -1388,6 +1401,8 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
EnterFunction(11);
switch_netns(&ipvs, skb);
/* Already marked as IPVS request or reply? */
if (skb->ipvs_property)
return NF_ACCEPT;
@ -1402,7 +1417,7 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
}
/* In bpf mode, this is null */
if (!bpf_mode_on && unlikely(!skb_dst(skb)))
if (ipvs_mode != IPVS_BPF_MODE && unlikely(!skb_dst(skb)))
return NF_ACCEPT;
if (!ipvs->enable)
@ -1631,6 +1646,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
unsigned int offset, offset2, ihl, verdict;
bool ipip, new_cp = false;
switch_netns(&ipvs, skb);
*related = 1;
/* reassemble IP fragments */
@ -1915,6 +1932,8 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
int conn_reuse_mode;
struct sock *sk;
switch_netns(&ipvs, skb);
/* Already marked as IPVS request or reply? */
if (skb->ipvs_property)
return NF_ACCEPT;
@ -1926,7 +1945,7 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
*/
if (unlikely((skb->pkt_type != PACKET_HOST &&
hooknum != NF_INET_LOCAL_OUT) ||
(!bpf_mode_on && !skb_dst(skb)))) {
(ipvs_mode != IPVS_BPF_MODE && !skb_dst(skb)))) {
ip_vs_fill_iph_skb(af, skb, false, &iph);
IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s"
" ignored in hook %u\n",
@ -1995,7 +2014,9 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
* as zero rs may be killed already.
* Only enable in bpf mode currently. Shall promote to IPVS mode later.
*/
if (no_route_to_host_fix && bpf_mode_on && cp && cp->dest &&
if (no_route_to_host_fix &&
ipvs_mode == IPVS_BPF_MODE &&
cp && cp->dest &&
unlikely(!atomic_read(&cp->dest->weight)) &&
is_new_conn(skb, &iph) && !iph.fragoffs &&
conn_reuse_mode == 0) {
@ -2118,7 +2139,8 @@ ip_vs_remote_request4(void *priv, struct sk_buff *skb,
* the defrag may impact performance greatly! Lukily, this is not the
* case for us!
*/
if (bpf_mode_on && unlikely(ip_is_fragment(ip_hdr(skb)))) {
if (ipvs_mode == IPVS_BPF_MODE &&
unlikely(ip_is_fragment(ip_hdr(skb)))) {
if (ip_vs_gather_frags(net_ipvs(state->net), skb,
IP_DEFRAG_VS_IN))
/* return 0 will call skb_free in nf_hook */
@ -2354,6 +2376,113 @@ static const struct nf_hook_ops ip_vs_bpf_ops[] = {
*/
};
static const struct nf_hook_ops ip_vs_ns_ops[] = {
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_reply4,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SRC - 2,
},
{
.hook = ip_vs_remote_request4,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP_PRI_NAT_SRC - 1,
},
/* Delete IPVS nf local_out hook to handle response packet.
* Consider following steps:
* 1. curl vip:vport on a vm. packet is (nodeip:tmport->vip:vport)
* 2. Ipvs does DNAT and choose a POD on this vm.
* packet is (nodeip:tmpport->rsip:rsport)
* 3. The POD replies. packet is (rsip:rsport -> nodeip:tmpport)
* In nf local-out, ipvs ip_vs_local_reply4
* does reverse DNAT, and modifies the packet to be
* (VIP:VPORT->nodeip:tmpport)
* 4. The packet go out of the POD's ENI to the iaas switch.
* 5. Iaas switch will drop the packet as it expects the source
* to be the ENI's ip.
* Any side effect to delete the hook?
* If a client out of the cluster accesses the service on a cvm,
* and the cvm choose a process runs on default net ns as the target,
* Break!. However, It doesn't matter as we haven't such case.
*/
/* After mangle, schedule and forward local requests */
{
.hook = ip_vs_local_request4,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_NAT_DST + 2,
},
/* After packet filtering (but before ip_vs_out_icmp), catch icmp
* destined for 0.0.0.0/0, which is for incoming IPVS connections
*/
{
.hook = ip_vs_forward_icmp,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD,
.priority = 99,
},
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_reply4,
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_FORWARD,
.priority = 100,
},
#ifdef CONFIG_IP_VS_IPV6
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_reply6,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP6_PRI_NAT_SRC - 2,
},
/* After packet filtering, forward packet through VS/DR, VS/TUN,
* or VS/NAT(change destination), so that filtering rules can be
* applied to IPVS
*/
{
.hook = ip_vs_remote_request6,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_IN,
.priority = NF_IP6_PRI_NAT_SRC - 1,
},
/* Before ip_vs_in, change source only for VS/NAT */
{
.hook = ip_vs_local_reply6,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP6_PRI_NAT_DST + 1,
},
/* After mangle, schedule and forward local requests */
{
.hook = ip_vs_local_request6,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP6_PRI_NAT_DST + 2,
},
/* After packet filtering (but before ip_vs_out_icmp), catch icmp
* destined for 0.0.0.0/0, which is for incoming IPVS connections
*/
{
.hook = ip_vs_forward_icmp_v6,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD,
.priority = 99,
},
/* After packet filtering, change source only for VS/NAT */
{
.hook = ip_vs_reply6,
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD,
.priority = 100,
},
#endif
};
/*
* Initialize IP Virtual Server netns mem.
*/
@ -2362,6 +2491,8 @@ static int __net_init __ip_vs_init(struct net *net)
struct netns_ipvs *ipvs;
int ret;
if (ipvs_mode >= IPVS_MAX_MODE)
return -EINVAL;
ipvs = net_generic(net, ip_vs_net_id);
if (ipvs == NULL)
return -ENOMEM;
@ -2392,12 +2523,19 @@ static int __net_init __ip_vs_init(struct net *net)
if (ip_vs_sync_net_init(ipvs) < 0)
goto sync_fail;
if (!bpf_mode_on) {
if (ipvs_mode == IPVS_ORIGIN_MODE) {
ret = nf_register_net_hooks(net, ip_vs_ops,
ARRAY_SIZE(ip_vs_ops));
if (ret < 0)
goto hook_fail;
} else {
}
if (ipvs_mode == IPVS_SHARE_NS_MODE) {
ret = nf_register_net_hooks(net, ip_vs_ns_ops,
ARRAY_SIZE(ip_vs_ns_ops));
if (ret < 0)
goto hook_fail;
}
if (ipvs_mode == IPVS_BPF_MODE) {
ret = nf_register_net_hooks(net, ip_vs_bpf_ops,
ARRAY_SIZE(ip_vs_bpf_ops));
if (ret < 0)
@ -2418,7 +2556,6 @@ static int __net_init __ip_vs_init(struct net *net)
goto hook_fail;
}
}
return 0;
/*
* Error handling
@ -2445,10 +2582,14 @@ static void __net_exit __ip_vs_cleanup(struct net *net)
{
struct netns_ipvs *ipvs = net_ipvs(net);
if (!bpf_mode_on)
nf_unregister_net_hooks(net, ip_vs_ops,
ARRAY_SIZE(ip_vs_ops));
else {
if (ipvs_mode == IPVS_ORIGIN_MODE)
nf_unregister_net_hooks(net, ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
if (ipvs_mode == IPVS_SHARE_NS_MODE)
nf_unregister_net_hooks(net, ip_vs_ns_ops,
ARRAY_SIZE(ip_vs_ns_ops));
if (ipvs_mode == IPVS_BPF_MODE) {
nf_unregister_net_hooks(net, ip_vs_bpf_ops,
ARRAY_SIZE(ip_vs_bpf_ops));
free_percpu(ipvs->bpf_stat);
@ -2494,7 +2635,8 @@ struct bpf_sym_addrs resolve_addrs;
static int __init ip_vs_init(void)
{
int ret;
if (bpf_mode_on) {
if (ipvs_mode == IPVS_BPF_MODE) {
resolve_addrs.ip_finish_output =
(output_t)kallsyms_lookup_name("ip_finish_output");
if (!resolve_addrs.ip_finish_output) {
@ -2530,7 +2672,7 @@ static int __init ip_vs_init(void)
}
}
pr_info("bpf_mode_on is %d\n", bpf_mode_on);
pr_info("ipvs_mode is %d\n", ipvs_mode);
ret = ip_vs_control_init();
if (ret < 0) {
pr_err("can't setup control.\n");
@ -2584,7 +2726,7 @@ static void __exit ip_vs_cleanup(void)
ip_vs_conn_cleanup();
ip_vs_protocol_cleanup();
ip_vs_control_cleanup();
if (bpf_mode_on)
if (ipvs_mode == IPVS_BPF_MODE)
ip_vs_bpf_put();
pr_info("ipvs unloaded.\n");
}

View File

@ -1191,7 +1191,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
ip_vs_use_count_inc();
/* in bpf mode, avoid loopback traffic */
if (bpf_mode_on && strcmp(u->sched_name, "wrr") != 0 &&
if (ipvs_mode == IPVS_BPF_MODE && strcmp(u->sched_name, "wrr") != 0 &&
strcmp(u->sched_name, "rr") != 0 &&
strcmp(u->sched_name, "lc") != 0 &&
strcmp(u->sched_name, "wlc") != 0) {

View File

@ -47,7 +47,8 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
if ((dest->flags & IP_VS_DEST_F_OVERLOAD) ||
atomic_read(&dest->weight) == 0 ||
(bpf_mode_on && dest->addr.ip == iph->saddr.ip))
(ipvs_mode == IPVS_BPF_MODE &&
dest->addr.ip == iph->saddr.ip))
continue;
doh = ip_vs_dest_conn_overhead(dest);
if (!least || doh < loh) {

View File

@ -76,7 +76,7 @@ ip_vs_rr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
atomic_read(&dest->weight) > 0) {
/* HIT */
if (!bpf_mode_on)
if (ipvs_mode != IPVS_BPF_MODE)
goto out;
else if (dest->addr.ip != iph->saddr.ip)
goto out;

View File

@ -56,8 +56,9 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
atomic_read(&dest->weight) > 0) {
if (!bpf_mode_on ||
(bpf_mode_on && dest->addr.ip != iph->saddr.ip)) {
if (ipvs_mode != IPVS_BPF_MODE ||
(ipvs_mode == IPVS_BPF_MODE &&
dest->addr.ip != iph->saddr.ip)) {
least = dest;
loh = ip_vs_dest_conn_overhead(least);
goto nextstage;
@ -74,7 +75,8 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
/* in bpf mode, avoid loopback traffic */
list_for_each_entry_continue_rcu(dest, &svc->destinations, n_list) {
if ((dest->flags & IP_VS_DEST_F_OVERLOAD) ||
(bpf_mode_on && dest->addr.ip == iph->saddr.ip))
(ipvs_mode == IPVS_BPF_MODE &&
dest->addr.ip == iph->saddr.ip))
continue;
doh = ip_vs_dest_conn_overhead(dest);
if ((__s64)loh * atomic_read(&dest->weight) >

View File

@ -185,7 +185,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
n_list) {
if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
atomic_read(&dest->weight) >= mark->cw) {
if (!bpf_mode_on)
if (ipvs_mode != IPVS_BPF_MODE)
goto found;
else if (dest->addr.ip != iph->saddr.ip)
goto found;

View File

@ -316,7 +316,13 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
int mtu;
int local, noref = 1;
if (dest) {
if (ipvs_mode == IPVS_SHARE_NS_MODE)
net = ip_vs_skb_net(skb);
if (!net)
return -1;
/* when share netns, the cache will error */
if (dest && ipvs_mode != IPVS_SHARE_NS_MODE) {
dest_dst = __ip_vs_dst_check(dest);
if (likely(dest_dst))
rt = (struct rtable *) dest_dst->dst_cache;
@ -365,7 +371,7 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
/* In bpf mode, this check always return false.Don't call it to avoid
* access of skb->dst
*/
if (!bpf_mode_on &&
if (ipvs_mode != IPVS_BPF_MODE &&
unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
local))) {
IP_VS_DBG_RL("We are crossing local and non-local addresses"
@ -373,7 +379,10 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
goto err_put;
}
if (unlikely(local)) {
/* traffic to local address shall route to lo dev
* so that traffic from a POD can choose itself as rs.
*/
if (ipvs_mode != IPVS_SHARE_NS_MODE && unlikely(local)) {
/* skb to local stack, preserve old route */
if (!noref)
ip_rt_put(rt);
@ -407,7 +416,7 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
skb_dst_set(skb, &rt->dst);
/* In bpf mode, like ip_output, set output dev */
if (bpf_mode_on)
if (ipvs_mode == IPVS_BPF_MODE)
skb->dev = skb_dst(skb)->dev;
return local;
@ -618,6 +627,11 @@ static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb,
struct ip_vs_conn *cp, int local)
{
int ret = NF_STOLEN;
struct net *net;
net = cp->ipvs->net;
if (ipvs_mode == IPVS_SHARE_NS_MODE)
net = ip_vs_skb_net(skb);
skb->ipvs_property = 1;
if (likely(!(cp->flags & IP_VS_CONN_F_NFCT)))
@ -634,7 +648,7 @@ static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb,
if (!local) {
skb_forward_csum(skb);
NF_HOOK(pf, NF_INET_LOCAL_OUT, cp->ipvs->net, NULL, skb,
NF_HOOK(pf, NF_INET_LOCAL_OUT, net, NULL, skb,
NULL, skb_dst(skb)->dev, dst_output);
} else
ret = NF_ACCEPT;
@ -647,6 +661,11 @@ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb,
struct ip_vs_conn *cp, int local)
{
int ret = NF_STOLEN;
struct net *net;
net = cp->ipvs->net;
if (ipvs_mode == IPVS_SHARE_NS_MODE)
net = ip_vs_skb_net(skb);
skb->ipvs_property = 1;
if (likely(!(cp->flags & IP_VS_CONN_F_NFCT)))
@ -654,7 +673,7 @@ static inline int ip_vs_send_or_cont(int pf, struct sk_buff *skb,
if (!local) {
ip_vs_drop_early_demux_sk(skb);
skb_forward_csum(skb);
NF_HOOK(pf, NF_INET_LOCAL_OUT, cp->ipvs->net, NULL, skb,
NF_HOOK(pf, NF_INET_LOCAL_OUT, net, NULL, skb,
NULL, skb_dst(skb)->dev, dst_output);
} else
ret = NF_ACCEPT;
@ -760,13 +779,11 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p));
}
/* In ipvs mode, ip_route_input_slow will set me to 1 for
* local_in pkt from nic! For pkt local-out this is not set!
/* originally, this was set in ip_route_input_slow
* In bpf mode, this is not useful since local rs is not allowed
*/
if (!bpf_mode_on)
was_input = rt_is_input_route(skb_rtable(skb));
else
was_input = rt_is_input_route(skb_rtable(skb));
if (ipvs_mode == IPVS_BPF_MODE)
was_input = 1;
local = __ip_vs_get_out_rt(cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip,
IP_VS_RT_MODE_LOCAL |
@ -774,7 +791,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
IP_VS_RT_MODE_RDR, NULL, ipvsh);
if (local < 0)
goto tx_error;
if (bpf_mode_on && local == 1) {
if (ipvs_mode == IPVS_BPF_MODE && local == 1) {
pr_err("shall not route to local rs in bpf mode\n");
BPF_STAT_INC(cp->ipvs, BPF_XMIT_LOCAL_RS);
goto tx_error;
@ -833,7 +850,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
/* Another hack: avoid icmp_send in ip_fragment */
skb->ignore_df = 1;
if (!bpf_mode_on) {
if (ipvs_mode != IPVS_BPF_MODE) {
rc = ip_vs_nat_send_or_cont(NFPROTO_IPV4, skb, cp, local);
} else {
/* used by bpf egress to construct the key!
@ -1325,7 +1342,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
/*
* mangle and send the packet here (only for VS/NAT)
*/
if (!bpf_mode_on)
if (ipvs_mode != IPVS_BPF_MODE)
was_input = rt_is_input_route(skb_rtable(skb));
else
was_input = 1;
@ -1378,7 +1395,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
/* Another hack: avoid icmp_send in ip_fragment */
skb->ignore_df = 1;
if (!bpf_mode_on) {
if (ipvs_mode != IPVS_BPF_MODE) {
rc = ip_vs_nat_send_or_cont(NFPROTO_IPV4, skb, cp, local);
} else {
/* used by bpf egress to construct the key!