This is necessary to validate that we're not accidentally enabling heterogeneous pool incompatible features like syncing. Signed-off-by: Alex Gartrell <agartrell@xxxxxx> --- include/net/ip_vs.h | 4 ++++ net/netfilter/ipvs/ip_vs_ctl.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 72698b1..69d8722 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -989,6 +989,10 @@ struct netns_ipvs { char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; /* net name space ptr */ struct net *net; /* Needed by timer routines */ + /* Number of heterogeneous destinations, needed because + * heterogeneous are not supported when synchronization is + * enabled */ + unsigned int mixed_address_family_dests; }; #define DEFAULT_SYNC_THRESHOLD 3 diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 6702cf8..1c0621b 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -778,6 +778,21 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest, struct ip_vs_service *old_svc; struct ip_vs_scheduler *sched; int conn_flags; + u16 old_af, new_af; + + new_af = udest->af; + old_af = dest->af; + + /* If we're adding a new dest or changing from the old one and the + * af has changed */ + if ((add || new_af != old_af) && new_af != svc->af) { + ipvs->mixed_address_family_dests++; + } + /* If we're editing an old dest, the af's have changed, and the af + * is now the same as the service */ + else if (!add && new_af != old_af && new_af == svc->af) { + ipvs->mixed_address_family_dests--; + } /* set the weight and the flags */ atomic_set(&dest->weight, udest->weight); @@ -1061,6 +1076,9 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc, list_del_rcu(&dest->n_list); svc->num_dests--; + if (dest->af != svc->af) + net_ipvs(svc->net)->mixed_address_family_dests--; + if (svcupd) { struct ip_vs_scheduler *sched; @@ -3336,6 +3354,11 @@ static int ip_vs_genl_new_daemon(struct net *net, struct nlattr **attrs) attrs[IPVS_DAEMON_ATTR_SYNC_ID])) return -EINVAL; + /* The synchronization protocol is incompatible with mixed family + * services */ + if (net_ipvs(net)->mixed_address_family_dests > 0) + return -EINVAL; + return start_sync_thread(net, nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]), nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]), @@ -3466,6 +3489,25 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) * this will have the same address family as the service. */ if (udest.af == 0) udest.af = svc->af; + + if (udest.af != svc->af) { + /* The synchronization protocol is incompatible + * with mixed family services */ + if (net_ipvs(net)->sync_state) { + ret = -EINVAL; + goto out; + } + + /* Which connection types do we support? */ + switch (udest.conn_flags) { + case IP_VS_CONN_F_TUNNEL: + /* We are able to forward this */ + break; + default: + ret = -EINVAL; + goto out; + } + } } switch (cmd) { -- 1.8.1 -- To unsubscribe from this list: send the line "unsubscribe lvs-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html