diff options
-rw-r--r-- | include/net/ip_vs.h | 20 | ||||
-rw-r--r-- | include/net/netns/ip_vs.h | 3 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_proto.c | 66 |
3 files changed, 88 insertions, 1 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index d551e0d8fd9a..88d4e40b538a 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h | |||
@@ -352,6 +352,7 @@ struct iphdr; | |||
352 | struct ip_vs_conn; | 352 | struct ip_vs_conn; |
353 | struct ip_vs_app; | 353 | struct ip_vs_app; |
354 | struct sk_buff; | 354 | struct sk_buff; |
355 | struct ip_vs_proto_data; | ||
355 | 356 | ||
356 | struct ip_vs_protocol { | 357 | struct ip_vs_protocol { |
357 | struct ip_vs_protocol *next; | 358 | struct ip_vs_protocol *next; |
@@ -366,6 +367,10 @@ struct ip_vs_protocol { | |||
366 | 367 | ||
367 | void (*exit)(struct ip_vs_protocol *pp); | 368 | void (*exit)(struct ip_vs_protocol *pp); |
368 | 369 | ||
370 | void (*init_netns)(struct net *net, struct ip_vs_proto_data *pd); | ||
371 | |||
372 | void (*exit_netns)(struct net *net, struct ip_vs_proto_data *pd); | ||
373 | |||
369 | int (*conn_schedule)(int af, struct sk_buff *skb, | 374 | int (*conn_schedule)(int af, struct sk_buff *skb, |
370 | struct ip_vs_protocol *pp, | 375 | struct ip_vs_protocol *pp, |
371 | int *verdict, struct ip_vs_conn **cpp); | 376 | int *verdict, struct ip_vs_conn **cpp); |
@@ -417,7 +422,20 @@ struct ip_vs_protocol { | |||
417 | int (*set_state_timeout)(struct ip_vs_protocol *pp, char *sname, int to); | 422 | int (*set_state_timeout)(struct ip_vs_protocol *pp, char *sname, int to); |
418 | }; | 423 | }; |
419 | 424 | ||
420 | extern struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto); | 425 | /* |
426 | * protocol data per netns | ||
427 | */ | ||
428 | struct ip_vs_proto_data { | ||
429 | struct ip_vs_proto_data *next; | ||
430 | struct ip_vs_protocol *pp; | ||
431 | int *timeout_table; /* protocol timeout table */ | ||
432 | atomic_t appcnt; /* counter of proto app incs. */ | ||
433 | struct tcp_states_t *tcp_state_table; | ||
434 | }; | ||
435 | |||
436 | extern struct ip_vs_protocol *ip_vs_proto_get(unsigned short proto); | ||
437 | extern struct ip_vs_proto_data *ip_vs_proto_data_get(struct net *net, | ||
438 | unsigned short proto); | ||
421 | 439 | ||
422 | struct ip_vs_conn_param { | 440 | struct ip_vs_conn_param { |
423 | const union nf_inet_addr *caddr; | 441 | const union nf_inet_addr *caddr; |
diff --git a/include/net/netns/ip_vs.h b/include/net/netns/ip_vs.h index d14581cc4fe0..6f4e089b8db2 100644 --- a/include/net/netns/ip_vs.h +++ b/include/net/netns/ip_vs.h | |||
@@ -28,6 +28,9 @@ struct netns_ipvs { | |||
28 | #define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1) | 28 | #define IP_VS_RTAB_MASK (IP_VS_RTAB_SIZE - 1) |
29 | 29 | ||
30 | struct list_head rs_table[IP_VS_RTAB_SIZE]; | 30 | struct list_head rs_table[IP_VS_RTAB_SIZE]; |
31 | /* ip_vs_proto */ | ||
32 | #define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */ | ||
33 | struct ip_vs_proto_data *proto_data_table[IP_VS_PROTO_TAB_SIZE]; | ||
31 | 34 | ||
32 | /* ip_vs_lblc */ | 35 | /* ip_vs_lblc */ |
33 | int sysctl_lblc_expiration; | 36 | int sysctl_lblc_expiration; |
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 45392942d0e7..576e29648c53 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c | |||
@@ -60,6 +60,31 @@ static int __used __init register_ip_vs_protocol(struct ip_vs_protocol *pp) | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | /* | ||
64 | * register an ipvs protocols netns related data | ||
65 | */ | ||
66 | static int | ||
67 | register_ip_vs_proto_netns(struct net *net, struct ip_vs_protocol *pp) | ||
68 | { | ||
69 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
70 | unsigned hash = IP_VS_PROTO_HASH(pp->protocol); | ||
71 | struct ip_vs_proto_data *pd = | ||
72 | kzalloc(sizeof(struct ip_vs_proto_data), GFP_ATOMIC); | ||
73 | |||
74 | if (!pd) { | ||
75 | pr_err("%s(): no memory.\n", __func__); | ||
76 | return -ENOMEM; | ||
77 | } | ||
78 | pd->pp = pp; /* For speed issues */ | ||
79 | pd->next = ipvs->proto_data_table[hash]; | ||
80 | ipvs->proto_data_table[hash] = pd; | ||
81 | atomic_set(&pd->appcnt, 0); /* Init app counter */ | ||
82 | |||
83 | if (pp->init_netns != NULL) | ||
84 | pp->init_netns(net, pd); | ||
85 | |||
86 | return 0; | ||
87 | } | ||
63 | 88 | ||
64 | /* | 89 | /* |
65 | * unregister an ipvs protocol | 90 | * unregister an ipvs protocol |
@@ -82,6 +107,29 @@ static int unregister_ip_vs_protocol(struct ip_vs_protocol *pp) | |||
82 | return -ESRCH; | 107 | return -ESRCH; |
83 | } | 108 | } |
84 | 109 | ||
110 | /* | ||
111 | * unregister an ipvs protocols netns data | ||
112 | */ | ||
113 | static int | ||
114 | unregister_ip_vs_proto_netns(struct net *net, struct ip_vs_proto_data *pd) | ||
115 | { | ||
116 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
117 | struct ip_vs_proto_data **pd_p; | ||
118 | unsigned hash = IP_VS_PROTO_HASH(pd->pp->protocol); | ||
119 | |||
120 | pd_p = &ipvs->proto_data_table[hash]; | ||
121 | for (; *pd_p; pd_p = &(*pd_p)->next) { | ||
122 | if (*pd_p == pd) { | ||
123 | *pd_p = pd->next; | ||
124 | if (pd->pp->exit_netns != NULL) | ||
125 | pd->pp->exit_netns(net, pd); | ||
126 | kfree(pd); | ||
127 | return 0; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return -ESRCH; | ||
132 | } | ||
85 | 133 | ||
86 | /* | 134 | /* |
87 | * get ip_vs_protocol object by its proto. | 135 | * get ip_vs_protocol object by its proto. |
@@ -100,6 +148,24 @@ struct ip_vs_protocol * ip_vs_proto_get(unsigned short proto) | |||
100 | } | 148 | } |
101 | EXPORT_SYMBOL(ip_vs_proto_get); | 149 | EXPORT_SYMBOL(ip_vs_proto_get); |
102 | 150 | ||
151 | /* | ||
152 | * get ip_vs_protocol object data by netns and proto | ||
153 | */ | ||
154 | struct ip_vs_proto_data * | ||
155 | ip_vs_proto_data_get(struct net *net, unsigned short proto) | ||
156 | { | ||
157 | struct netns_ipvs *ipvs = net_ipvs(net); | ||
158 | struct ip_vs_proto_data *pd; | ||
159 | unsigned hash = IP_VS_PROTO_HASH(proto); | ||
160 | |||
161 | for (pd = ipvs->proto_data_table[hash]; pd; pd = pd->next) { | ||
162 | if (pd->pp->protocol == proto) | ||
163 | return pd; | ||
164 | } | ||
165 | |||
166 | return NULL; | ||
167 | } | ||
168 | EXPORT_SYMBOL(ip_vs_proto_data_get); | ||
103 | 169 | ||
104 | /* | 170 | /* |
105 | * Propagate event for state change to all protocols | 171 | * Propagate event for state change to all protocols |