aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gartrell <agartrell@fb.com>2014-09-09 19:40:20 -0400
committerSimon Horman <horms@verge.net.au>2014-09-15 20:03:33 -0400
commit6cff339bbd5f9eda7a5e8a521f91a88d046e6d0c (patch)
tree7098d7f00a946c526aa5a7b564c586af00065584
parent616a9be25cb9516e546c0de55d61e1e46e54ade9 (diff)
ipvs: Add destination address family to netlink interface
This is necessary to support heterogeneous pools. For example, if you have an ipv6 addressed network, you'll want to be able to forward ipv4 traffic into it. This patch enforces that destination address family is the same as service family, as none of the forwarding mechanisms support anything else. For the old setsockopt mechanism, we simply set the dest address family to AF_INET as we do with the service. Signed-off-by: Alex Gartrell <agartrell@fb.com> Acked-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: Simon Horman <horms@verge.net.au>
-rw-r--r--include/net/ip_vs.h3
-rw-r--r--include/uapi/linux/ip_vs.h3
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c45
3 files changed, 44 insertions, 7 deletions
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 624a8a54806d..b7e2b624d58e 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -648,6 +648,9 @@ struct ip_vs_dest_user_kern {
648 /* thresholds for active connections */ 648 /* thresholds for active connections */
649 u32 u_threshold; /* upper threshold */ 649 u32 u_threshold; /* upper threshold */
650 u32 l_threshold; /* lower threshold */ 650 u32 l_threshold; /* lower threshold */
651
652 /* Address family of addr */
653 u16 af;
651}; 654};
652 655
653 656
diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h
index fbcffe8041f7..cabe95d5b461 100644
--- a/include/uapi/linux/ip_vs.h
+++ b/include/uapi/linux/ip_vs.h
@@ -384,6 +384,9 @@ enum {
384 IPVS_DEST_ATTR_PERSIST_CONNS, /* persistent connections */ 384 IPVS_DEST_ATTR_PERSIST_CONNS, /* persistent connections */
385 385
386 IPVS_DEST_ATTR_STATS, /* nested attribute for dest stats */ 386 IPVS_DEST_ATTR_STATS, /* nested attribute for dest stats */
387
388 IPVS_DEST_ATTR_ADDR_FAMILY, /* Address family of address */
389
387 __IPVS_DEST_ATTR_MAX, 390 __IPVS_DEST_ATTR_MAX,
388}; 391};
389 392
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index bd2b208ba56c..594cec7ebc43 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -816,6 +816,8 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
816 dest->u_threshold = udest->u_threshold; 816 dest->u_threshold = udest->u_threshold;
817 dest->l_threshold = udest->l_threshold; 817 dest->l_threshold = udest->l_threshold;
818 818
819 dest->af = udest->af;
820
819 spin_lock_bh(&dest->dst_lock); 821 spin_lock_bh(&dest->dst_lock);
820 __ip_vs_dst_cache_reset(dest); 822 __ip_vs_dst_cache_reset(dest);
821 spin_unlock_bh(&dest->dst_lock); 823 spin_unlock_bh(&dest->dst_lock);
@@ -846,8 +848,12 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
846 848
847 EnterFunction(2); 849 EnterFunction(2);
848 850
851 /* Temporary for consistency */
852 if (udest->af != svc->af)
853 return -EINVAL;
854
849#ifdef CONFIG_IP_VS_IPV6 855#ifdef CONFIG_IP_VS_IPV6
850 if (svc->af == AF_INET6) { 856 if (udest->af == AF_INET6) {
851 atype = ipv6_addr_type(&udest->addr.in6); 857 atype = ipv6_addr_type(&udest->addr.in6);
852 if ((!(atype & IPV6_ADDR_UNICAST) || 858 if ((!(atype & IPV6_ADDR_UNICAST) ||
853 atype & IPV6_ADDR_LINKLOCAL) && 859 atype & IPV6_ADDR_LINKLOCAL) &&
@@ -875,12 +881,12 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
875 u64_stats_init(&ip_vs_dest_stats->syncp); 881 u64_stats_init(&ip_vs_dest_stats->syncp);
876 } 882 }
877 883
878 dest->af = svc->af; 884 dest->af = udest->af;
879 dest->protocol = svc->protocol; 885 dest->protocol = svc->protocol;
880 dest->vaddr = svc->addr; 886 dest->vaddr = svc->addr;
881 dest->vport = svc->port; 887 dest->vport = svc->port;
882 dest->vfwmark = svc->fwmark; 888 dest->vfwmark = svc->fwmark;
883 ip_vs_addr_copy(svc->af, &dest->addr, &udest->addr); 889 ip_vs_addr_copy(udest->af, &dest->addr, &udest->addr);
884 dest->port = udest->port; 890 dest->port = udest->port;
885 891
886 atomic_set(&dest->activeconns, 0); 892 atomic_set(&dest->activeconns, 0);
@@ -928,7 +934,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
928 return -ERANGE; 934 return -ERANGE;
929 } 935 }
930 936
931 ip_vs_addr_copy(svc->af, &daddr, &udest->addr); 937 ip_vs_addr_copy(udest->af, &daddr, &udest->addr);
932 938
933 /* We use function that requires RCU lock */ 939 /* We use function that requires RCU lock */
934 rcu_read_lock(); 940 rcu_read_lock();
@@ -949,7 +955,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
949 if (dest != NULL) { 955 if (dest != NULL) {
950 IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, " 956 IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, "
951 "dest->refcnt=%d, service %u/%s:%u\n", 957 "dest->refcnt=%d, service %u/%s:%u\n",
952 IP_VS_DBG_ADDR(svc->af, &daddr), ntohs(dport), 958 IP_VS_DBG_ADDR(udest->af, &daddr), ntohs(dport),
953 atomic_read(&dest->refcnt), 959 atomic_read(&dest->refcnt),
954 dest->vfwmark, 960 dest->vfwmark,
955 IP_VS_DBG_ADDR(svc->af, &dest->vaddr), 961 IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
@@ -992,7 +998,7 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
992 return -ERANGE; 998 return -ERANGE;
993 } 999 }
994 1000
995 ip_vs_addr_copy(svc->af, &daddr, &udest->addr); 1001 ip_vs_addr_copy(udest->af, &daddr, &udest->addr);
996 1002
997 /* We use function that requires RCU lock */ 1003 /* We use function that requires RCU lock */
998 rcu_read_lock(); 1004 rcu_read_lock();
@@ -2244,6 +2250,7 @@ static void ip_vs_copy_udest_compat(struct ip_vs_dest_user_kern *udest,
2244 udest->weight = udest_compat->weight; 2250 udest->weight = udest_compat->weight;
2245 udest->u_threshold = udest_compat->u_threshold; 2251 udest->u_threshold = udest_compat->u_threshold;
2246 udest->l_threshold = udest_compat->l_threshold; 2252 udest->l_threshold = udest_compat->l_threshold;
2253 udest->af = AF_INET;
2247} 2254}
2248 2255
2249static int 2256static int
@@ -2480,6 +2487,12 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
2480 if (count >= get->num_dests) 2487 if (count >= get->num_dests)
2481 break; 2488 break;
2482 2489
2490 /* Cannot expose heterogeneous members via sockopt
2491 * interface
2492 */
2493 if (dest->af != svc->af)
2494 continue;
2495
2483 entry.addr = dest->addr.ip; 2496 entry.addr = dest->addr.ip;
2484 entry.port = dest->port; 2497 entry.port = dest->port;
2485 entry.conn_flags = atomic_read(&dest->conn_flags); 2498 entry.conn_flags = atomic_read(&dest->conn_flags);
@@ -2777,6 +2790,7 @@ static const struct nla_policy ip_vs_dest_policy[IPVS_DEST_ATTR_MAX + 1] = {
2777 [IPVS_DEST_ATTR_INACT_CONNS] = { .type = NLA_U32 }, 2790 [IPVS_DEST_ATTR_INACT_CONNS] = { .type = NLA_U32 },
2778 [IPVS_DEST_ATTR_PERSIST_CONNS] = { .type = NLA_U32 }, 2791 [IPVS_DEST_ATTR_PERSIST_CONNS] = { .type = NLA_U32 },
2779 [IPVS_DEST_ATTR_STATS] = { .type = NLA_NESTED }, 2792 [IPVS_DEST_ATTR_STATS] = { .type = NLA_NESTED },
2793 [IPVS_DEST_ATTR_ADDR_FAMILY] = { .type = NLA_U16 },
2780}; 2794};
2781 2795
2782static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, 2796static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type,
@@ -3032,7 +3046,8 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
3032 nla_put_u32(skb, IPVS_DEST_ATTR_INACT_CONNS, 3046 nla_put_u32(skb, IPVS_DEST_ATTR_INACT_CONNS,
3033 atomic_read(&dest->inactconns)) || 3047 atomic_read(&dest->inactconns)) ||
3034 nla_put_u32(skb, IPVS_DEST_ATTR_PERSIST_CONNS, 3048 nla_put_u32(skb, IPVS_DEST_ATTR_PERSIST_CONNS,
3035 atomic_read(&dest->persistconns))) 3049 atomic_read(&dest->persistconns)) ||
3050 nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af))
3036 goto nla_put_failure; 3051 goto nla_put_failure;
3037 if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats)) 3052 if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats))
3038 goto nla_put_failure; 3053 goto nla_put_failure;
@@ -3113,6 +3128,7 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
3113{ 3128{
3114 struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1]; 3129 struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1];
3115 struct nlattr *nla_addr, *nla_port; 3130 struct nlattr *nla_addr, *nla_port;
3131 struct nlattr *nla_addr_family;
3116 3132
3117 /* Parse mandatory identifying destination fields first */ 3133 /* Parse mandatory identifying destination fields first */
3118 if (nla == NULL || 3134 if (nla == NULL ||
@@ -3121,6 +3137,7 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
3121 3137
3122 nla_addr = attrs[IPVS_DEST_ATTR_ADDR]; 3138 nla_addr = attrs[IPVS_DEST_ATTR_ADDR];
3123 nla_port = attrs[IPVS_DEST_ATTR_PORT]; 3139 nla_port = attrs[IPVS_DEST_ATTR_PORT];
3140 nla_addr_family = attrs[IPVS_DEST_ATTR_ADDR_FAMILY];
3124 3141
3125 if (!(nla_addr && nla_port)) 3142 if (!(nla_addr &&