These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / netfilter / ipvs / ip_vs_proto_udp.c
index b62a3c0..e494e9a 100644 (file)
 #include <net/ip6_checksum.h>
 
 static int
-udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
+udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
+                 struct ip_vs_proto_data *pd,
                  int *verdict, struct ip_vs_conn **cpp,
                  struct ip_vs_iphdr *iph)
 {
-       struct net *net;
        struct ip_vs_service *svc;
        struct udphdr _udph, *uh;
+       __be16 _ports[2], *ports = NULL;
 
-       /* IPv6 fragments, only first fragment will hit this */
-       uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
-       if (uh == NULL) {
+       if (likely(!ip_vs_iph_icmp(iph))) {
+               /* IPv6 fragments, only first fragment will hit this */
+               uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
+               if (uh)
+                       ports = &uh->source;
+       } else {
+               ports = skb_header_pointer(
+                       skb, iph->len, sizeof(_ports), &_ports);
+       }
+
+       if (!ports) {
                *verdict = NF_DROP;
                return 0;
        }
-       net = skb_net(skb);
+
        rcu_read_lock();
-       svc = ip_vs_service_find(net, af, skb->mark, iph->protocol,
-                                &iph->daddr, uh->dest);
+       if (likely(!ip_vs_iph_inverse(iph)))
+               svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
+                                        &iph->daddr, ports[1]);
+       else
+               svc = ip_vs_service_find(ipvs, af, skb->mark, iph->protocol,
+                                        &iph->saddr, ports[0]);
+
        if (svc) {
                int ignored;
 
-               if (ip_vs_todrop(net_ipvs(net))) {
+               if (ip_vs_todrop(ipvs)) {
                        /*
                         * It seems that we are very loaded.
                         * We have to drop this packet :(
@@ -348,14 +362,13 @@ static inline __u16 udp_app_hashkey(__be16 port)
 }
 
 
-static int udp_register_app(struct net *net, struct ip_vs_app *inc)
+static int udp_register_app(struct netns_ipvs *ipvs, struct ip_vs_app *inc)
 {
        struct ip_vs_app *i;
        __u16 hash;
        __be16 port = inc->port;
        int ret = 0;
-       struct netns_ipvs *ipvs = net_ipvs(net);
-       struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
+       struct ip_vs_proto_data *pd = ip_vs_proto_data_get(ipvs, IPPROTO_UDP);
 
        hash = udp_app_hashkey(port);
 
@@ -374,9 +387,9 @@ static int udp_register_app(struct net *net, struct ip_vs_app *inc)
 
 
 static void
-udp_unregister_app(struct net *net, struct ip_vs_app *inc)
+udp_unregister_app(struct netns_ipvs *ipvs, struct ip_vs_app *inc)
 {
-       struct ip_vs_proto_data *pd = ip_vs_proto_data_get(net, IPPROTO_UDP);
+       struct ip_vs_proto_data *pd = ip_vs_proto_data_get(ipvs, IPPROTO_UDP);
 
        atomic_dec(&pd->appcnt);
        list_del_rcu(&inc->p_list);
@@ -385,7 +398,7 @@ udp_unregister_app(struct net *net, struct ip_vs_app *inc)
 
 static int udp_app_conn_bind(struct ip_vs_conn *cp)
 {
-       struct netns_ipvs *ipvs = net_ipvs(ip_vs_conn_net(cp));
+       struct netns_ipvs *ipvs = cp->ipvs;
        int hash;
        struct ip_vs_app *inc;
        int result = 0;
@@ -456,10 +469,8 @@ udp_state_transition(struct ip_vs_conn *cp, int direction,
        cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
 }
 
-static int __udp_init(struct net *net, struct ip_vs_proto_data *pd)
+static int __udp_init(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd)
 {
-       struct netns_ipvs *ipvs = net_ipvs(net);
-
        ip_vs_init_hash_table(ipvs->udp_apps, UDP_APP_TAB_SIZE);
        pd->timeout_table = ip_vs_create_timeout_table((int *)udp_timeouts,
                                                        sizeof(udp_timeouts));
@@ -468,7 +479,7 @@ static int __udp_init(struct net *net, struct ip_vs_proto_data *pd)
        return 0;
 }
 
-static void __udp_exit(struct net *net, struct ip_vs_proto_data *pd)
+static void __udp_exit(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd)
 {
        kfree(pd->timeout_table);
 }