Commit fc723250 authored by Hans Schillstrom's avatar Hans Schillstrom Committed by Simon Horman

IPVS: netns to services part 1

Services hash tables got netns ptr a hash arg,
While Real Servers (rs) has been moved to ipvs struct.
Two new inline functions added to get net ptr from skb.

Since ip_vs is called from different contexts there is two
places to dig for the net ptr skb->dev or skb->sk
this is handled in skb_net() and skb_sknet()

Global functions, ip_vs_service_get() ip_vs_lookup_real_service()
etc have got  struct net *net as first param.
If possible get net ptr skb etc,
 - if not &init_net is used at this early stage of patching.

ip_vs_ctl.c  procfs not ready for netns yet.

*v3
 Comments by Julian
- __ip_vs_service_find and __ip_vs_svc_fwm_find are fast path,
  net_eq(svc->net, net) so the check is at the end now.
- net = skb_net(skb) in ip_vs_out moved after check for skb_dst.
Signed-off-by: default avatarHans Schillstrom <hans.schillstrom@ericsson.com>
Acked-by: default avatarJulian Anastasov <ja@ssi.bg>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent 61b1ab45
...@@ -37,6 +37,59 @@ static inline struct netns_ipvs *net_ipvs(struct net* net) ...@@ -37,6 +37,59 @@ static inline struct netns_ipvs *net_ipvs(struct net* net)
{ {
return net->ipvs; return net->ipvs;
} }
/*
* Get net ptr from skb in traffic cases
* use skb_sknet when call is from userland (ioctl or netlink)
*/
static inline struct net *skb_net(struct sk_buff *skb)
{
#ifdef CONFIG_NET_NS
#ifdef CONFIG_IP_VS_DEBUG
/*
* This is used for debug only.
* Start with the most likely hit
* End with BUG
*/
if (likely(skb->dev && skb->dev->nd_net))
return dev_net(skb->dev);
if (skb_dst(skb)->dev)
return dev_net(skb_dst(skb)->dev);
WARN(skb->sk, "Maybe skb_sknet should be used in %s() at line:%d\n",
__func__, __LINE__);
if (likely(skb->sk && skb->sk->sk_net))
return sock_net(skb->sk);
pr_err("There is no net ptr to find in the skb in %s() line:%d\n",
__func__, __LINE__);
BUG();
#else
return dev_net(skb->dev ? : skb_dst(skb)->dev);
#endif
#else
return &init_net;
#endif
}
static inline struct net *skb_sknet(struct sk_buff *skb)
{
#ifdef CONFIG_NET_NS
#ifdef CONFIG_IP_VS_DEBUG
/* Start with the most likely hit */
if (likely(skb->sk && skb->sk->sk_net))
return sock_net(skb->sk);
WARN(skb->dev, "Maybe skb_net should be used instead in %s() line:%d\n",
__func__, __LINE__);
if (likely(skb->dev && skb->dev->nd_net))
return dev_net(skb->dev);
pr_err("There is no net ptr to find in the skb in %s() line:%d\n",
__func__, __LINE__);
BUG();
#else
return sock_net(skb->sk);
#endif
#else
return &init_net;
#endif
}
/* Connections' size value needed by ip_vs_ctl.c */ /* Connections' size value needed by ip_vs_ctl.c */
extern int ip_vs_conn_tab_size; extern int ip_vs_conn_tab_size;
...@@ -496,6 +549,7 @@ struct ip_vs_service { ...@@ -496,6 +549,7 @@ struct ip_vs_service {
unsigned flags; /* service status flags */ unsigned flags; /* service status flags */
unsigned timeout; /* persistent timeout in ticks */ unsigned timeout; /* persistent timeout in ticks */
__be32 netmask; /* grouping granularity */ __be32 netmask; /* grouping granularity */
struct net *net;
struct list_head destinations; /* real server d-linked list */ struct list_head destinations; /* real server d-linked list */
__u32 num_dests; /* number of servers */ __u32 num_dests; /* number of servers */
...@@ -896,7 +950,7 @@ extern int sysctl_ip_vs_sync_ver; ...@@ -896,7 +950,7 @@ extern int sysctl_ip_vs_sync_ver;
extern void ip_vs_sync_switch_mode(int mode); extern void ip_vs_sync_switch_mode(int mode);
extern struct ip_vs_service * extern struct ip_vs_service *
ip_vs_service_get(int af, __u32 fwmark, __u16 protocol, ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol,
const union nf_inet_addr *vaddr, __be16 vport); const union nf_inet_addr *vaddr, __be16 vport);
static inline void ip_vs_service_put(struct ip_vs_service *svc) static inline void ip_vs_service_put(struct ip_vs_service *svc)
...@@ -905,7 +959,7 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc) ...@@ -905,7 +959,7 @@ static inline void ip_vs_service_put(struct ip_vs_service *svc)
} }
extern struct ip_vs_dest * extern struct ip_vs_dest *
ip_vs_lookup_real_service(int af, __u16 protocol, ip_vs_lookup_real_service(struct net *net, int af, __u16 protocol,
const union nf_inet_addr *daddr, __be16 dport); const union nf_inet_addr *daddr, __be16 dport);
extern int ip_vs_use_count_inc(void); extern int ip_vs_use_count_inc(void);
...@@ -913,9 +967,9 @@ extern void ip_vs_use_count_dec(void); ...@@ -913,9 +967,9 @@ extern void ip_vs_use_count_dec(void);
extern int ip_vs_control_init(void); extern int ip_vs_control_init(void);
extern void ip_vs_control_cleanup(void); extern void ip_vs_control_cleanup(void);
extern struct ip_vs_dest * extern struct ip_vs_dest *
ip_vs_find_dest(int af, const union nf_inet_addr *daddr, __be16 dport, ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr,
const union nf_inet_addr *vaddr, __be16 vport, __u16 protocol, __be16 dport, const union nf_inet_addr *vaddr, __be16 vport,
__u32 fwmark); __u16 protocol, __u32 fwmark);
extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
......
...@@ -20,6 +20,14 @@ struct ctl_table_header; ...@@ -20,6 +20,14 @@ struct ctl_table_header;
struct netns_ipvs { struct netns_ipvs {
int gen; /* Generation */ int gen; /* Generation */
/*
* Hash table: for real service lookups
*/
#define IP_VS_RTAB_BITS 4
#define IP_VS_RTAB_SIZE (1 << IP_VS_RTAB_BITS)
#define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1)
struct list_head rs_table[IP_VS_RTAB_SIZE];
}; };
#endif /* IP_VS_H_ */ #endif /* IP_VS_H_ */
...@@ -611,7 +611,7 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp) ...@@ -611,7 +611,7 @@ struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp)
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
if ((cp) && (!cp->dest)) { if ((cp) && (!cp->dest)) {
dest = ip_vs_find_dest(cp->af, &cp->daddr, cp->dport, dest = ip_vs_find_dest(&init_net, cp->af, &cp->daddr, cp->dport,
&cp->vaddr, cp->vport, &cp->vaddr, cp->vport,
cp->protocol, cp->fwmark); cp->protocol, cp->fwmark);
ip_vs_bind_dest(cp, dest); ip_vs_bind_dest(cp, dest);
......
...@@ -1031,6 +1031,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -1031,6 +1031,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
static unsigned int static unsigned int
ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
{ {
struct net *net = NULL;
struct ip_vs_iphdr iph; struct ip_vs_iphdr iph;
struct ip_vs_protocol *pp; struct ip_vs_protocol *pp;
struct ip_vs_conn *cp; struct ip_vs_conn *cp;
...@@ -1054,6 +1055,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ...@@ -1054,6 +1055,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
if (unlikely(!skb_dst(skb))) if (unlikely(!skb_dst(skb)))
return NF_ACCEPT; return NF_ACCEPT;
net = skb_net(skb);
ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
#ifdef CONFIG_IP_VS_IPV6 #ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) { if (af == AF_INET6) {
...@@ -1119,7 +1121,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) ...@@ -1119,7 +1121,7 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
sizeof(_ports), _ports); sizeof(_ports), _ports);
if (pptr == NULL) if (pptr == NULL)
return NF_ACCEPT; /* Not for me */ return NF_ACCEPT; /* Not for me */
if (ip_vs_lookup_real_service(af, iph.protocol, if (ip_vs_lookup_real_service(net, af, iph.protocol,
&iph.saddr, &iph.saddr,
pptr[0])) { pptr[0])) {
/* /*
......
This diff is collapsed.
...@@ -12,6 +12,7 @@ static int ...@@ -12,6 +12,7 @@ static int
sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
int *verdict, struct ip_vs_conn **cpp) int *verdict, struct ip_vs_conn **cpp)
{ {
struct net *net;
struct ip_vs_service *svc; struct ip_vs_service *svc;
sctp_chunkhdr_t _schunkh, *sch; sctp_chunkhdr_t _schunkh, *sch;
sctp_sctphdr_t *sh, _sctph; sctp_sctphdr_t *sh, _sctph;
...@@ -27,9 +28,9 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -27,9 +28,9 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
sizeof(_schunkh), &_schunkh); sizeof(_schunkh), &_schunkh);
if (sch == NULL) if (sch == NULL)
return 0; return 0;
net = skb_net(skb);
if ((sch->type == SCTP_CID_INIT) && if ((sch->type == SCTP_CID_INIT) &&
(svc = ip_vs_service_get(af, skb->mark, iph.protocol, (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
&iph.daddr, sh->dest))) { &iph.daddr, sh->dest))) {
int ignored; int ignored;
......
...@@ -31,6 +31,7 @@ static int ...@@ -31,6 +31,7 @@ static int
tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
int *verdict, struct ip_vs_conn **cpp) int *verdict, struct ip_vs_conn **cpp)
{ {
struct net *net;
struct ip_vs_service *svc; struct ip_vs_service *svc;
struct tcphdr _tcph, *th; struct tcphdr _tcph, *th;
struct ip_vs_iphdr iph; struct ip_vs_iphdr iph;
...@@ -42,11 +43,11 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -42,11 +43,11 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
*verdict = NF_DROP; *verdict = NF_DROP;
return 0; return 0;
} }
net = skb_net(skb);
/* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */ /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */
if (th->syn && if (th->syn &&
(svc = ip_vs_service_get(af, skb->mark, iph.protocol, &iph.daddr, (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
th->dest))) { &iph.daddr, th->dest))) {
int ignored; int ignored;
if (ip_vs_todrop()) { if (ip_vs_todrop()) {
......
...@@ -31,6 +31,7 @@ static int ...@@ -31,6 +31,7 @@ static int
udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
int *verdict, struct ip_vs_conn **cpp) int *verdict, struct ip_vs_conn **cpp)
{ {
struct net *net;
struct ip_vs_service *svc; struct ip_vs_service *svc;
struct udphdr _udph, *uh; struct udphdr _udph, *uh;
struct ip_vs_iphdr iph; struct ip_vs_iphdr iph;
...@@ -42,8 +43,8 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -42,8 +43,8 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
*verdict = NF_DROP; *verdict = NF_DROP;
return 0; return 0;
} }
net = skb_net(skb);
svc = ip_vs_service_get(af, skb->mark, iph.protocol, svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
&iph.daddr, uh->dest); &iph.daddr, uh->dest);
if (svc) { if (svc) {
int ignored; int ignored;
......
...@@ -749,7 +749,7 @@ static void ip_vs_proc_conn(struct ip_vs_conn_param *param, unsigned flags, ...@@ -749,7 +749,7 @@ static void ip_vs_proc_conn(struct ip_vs_conn_param *param, unsigned flags,
* If it is not found the connection will remain unbound * If it is not found the connection will remain unbound
* but still handled. * but still handled.
*/ */
dest = ip_vs_find_dest(type, daddr, dport, param->vaddr, dest = ip_vs_find_dest(&init_net, type, daddr, dport, param->vaddr,
param->vport, protocol, fwmark); param->vport, protocol, fwmark);
/* Set the approprite ativity flag */ /* Set the approprite ativity flag */
......
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