From patchwork Thu Aug 2 00:35:53 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 952496 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="MjUueAN2"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41grzV2rkvz9s3q for ; Thu, 2 Aug 2018 10:44:38 +1000 (AEST) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4180AE62; Thu, 2 Aug 2018 00:41:16 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 60A3EE59 for ; Thu, 2 Aug 2018 00:41:15 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg1-f196.google.com (mail-pg1-f196.google.com [209.85.215.196]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id B1BD97C1 for ; Thu, 2 Aug 2018 00:41:14 +0000 (UTC) Received: by mail-pg1-f196.google.com with SMTP id r1-v6so226374pgp.11 for ; Wed, 01 Aug 2018 17:41:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=OA6Ru4mMr8+HwpeRp7Nd3wYeH/aDFkCAJB/93TStOaE=; b=MjUueAN2ICAd1bVO2pVHE+fCVC7bMM+2Z2lC32bvEz725yRI1ZtBPRXjtDnaKvDuD3 ym6Mse87f5Rl6DkHwodsbWnbp0Jd8kKi/l7WL1q3GYz8Xv+noJnvlNc0F8AGb0eFIjZO btuyaUGunN7xxqWYXFWYlAQ56oEyMrSILuByptHTJ96Eg2QtZ8wJbDI/XNYWckH9mrib AFptSjW2ptKHcRmdDwLwYJ8l23eDuYPt00k2y2VDsjNCbzK8/ujYgAOahSlH3t4gDjYu JKdL0HeE7/bI9MXBakTCamIoLuYo3dNYR149OPG7MRHBEuF8oeY8pnm3MG4zjf3HNHYn cGkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=OA6Ru4mMr8+HwpeRp7Nd3wYeH/aDFkCAJB/93TStOaE=; b=ETKGNOTJt1t0KkPLb5F2JjwaDLptWgjlck559NC1nFcqZJhMABk66ipXO06RIZU0Io 8KnvkUWSz2NdxyU9fBjRA1kbR9FwTyRr1FYnq5Nm4y64nGYcE4QX6lyMSObiycQsw9k4 jRzVJEErQiOJ5rwys1E8eGtIczOt78sL7sHwPT/KRhktrrfuUrPKt1GaYMkoBR0vmgh4 VkvB0CUwhhCgbgaAYK2RG3zGdGEByq9yKS0ggFYqSqKSMPmpxCP83utFWBhi0ufH4dyf 9/gJkn8lCEoQE7khdDvsYOnfUpVSsXVqA/Ov5nWfUWXYDdfvg5nBN7cQkJAjlBROCFtJ 9ztQ== X-Gm-Message-State: AOUpUlGjFklWO1FJ6kzZSAERxxQXFsvx8KHaiXgxcEzvqFjmUEDGVmZc By7tMStkx1miDFRI2vggZvvQHA+W X-Google-Smtp-Source: AAOMgpcgHLKO3l7+ZLaaDjo9YGnM1aY72r8z4yT9WtAzf1A7JJfS4ZPMA/8tB2pyZInf5gtabiFVCA== X-Received: by 2002:a62:c98e:: with SMTP id l14-v6mr610253pfk.10.1533170473853; Wed, 01 Aug 2018 17:41:13 -0700 (PDT) Received: from Husky.eng.vmware.com ([66.170.99.1]) by smtp.gmail.com with ESMTPSA id s73-v6sm328627pfi.154.2018.08.01.17.41.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 01 Aug 2018 17:41:12 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Wed, 1 Aug 2018 17:35:53 -0700 Message-Id: <1533170156-769-9-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1533170156-769-1-git-send-email-yihung.wei@gmail.com> References: <1533170156-769-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH v2 08/11] dpif-netlink: Implement conntrack zone limiit X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org This patch provides the implementation of conntrack zone limit in dpif-netlink. It basically utilizes the netlink API to communicate with OVS kernel module to set, delete, and get conntrack zone limit. Signed-off-by: Yi-Hung Wei --- lib/dpif-netlink.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 199 insertions(+), 3 deletions(-) diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index ee98a3b7d8b6..365b38047fe1 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -213,6 +213,7 @@ static int ovs_vport_family; static int ovs_flow_family; static int ovs_packet_family; static int ovs_meter_family; +static int ovs_ct_limit_family; /* Generic Netlink multicast groups for OVS. * @@ -2919,6 +2920,195 @@ dpif_netlink_ct_flush(struct dpif *dpif OVS_UNUSED, const uint16_t *zone, } } +static int +dpif_netlink_set_limits(struct dpif *dpif OVS_UNUSED, + const uint32_t *default_limits, + const struct ovs_list *zone_limits) +{ + struct ofpbuf *request; + struct ovs_header *ovs_header; + size_t opt_offset; + int err; + struct ovs_zone_limit req_zone_limit; + + if (ovs_ct_limit_family < 0) { + return EOPNOTSUPP; + } + + request = ofpbuf_new(NL_DUMP_BUFSIZE); + nl_msg_put_genlmsghdr(request, 0, ovs_ct_limit_family, + NLM_F_REQUEST | NLM_F_ECHO, OVS_CT_LIMIT_CMD_SET, + OVS_CT_LIMIT_VERSION); + + ovs_header = ofpbuf_put_uninit(request, sizeof *ovs_header); + ovs_header->dp_ifindex = 0; + + opt_offset = nl_msg_start_nested(request, OVS_CT_LIMIT_ATTR_ZONE_LIMIT); + if (default_limits) { + req_zone_limit.zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE; + req_zone_limit.limit = *default_limits; + nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit); + } + + if (!ovs_list_is_empty(zone_limits)) { + struct ct_dpif_zone_limit *zone_limit; + + LIST_FOR_EACH (zone_limit, node, zone_limits) { + req_zone_limit.zone_id = zone_limit->zone; + req_zone_limit.limit = zone_limit->limit; + nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit); + } + } + nl_msg_end_nested(request, opt_offset); + + err = nl_transact(NETLINK_GENERIC, request, NULL); + ofpbuf_uninit(request); + return err; +} + +static int +dpif_netlink_zone_limits_from_ofpbuf(const struct ofpbuf *buf, + uint32_t *default_limit, + struct ovs_list *zone_limits) +{ + static const struct nl_policy ovs_ct_limit_policy[] = { + [OVS_CT_LIMIT_ATTR_ZONE_LIMIT] = { .type = NL_A_NESTED, + .optional = true }, + }; + + struct ofpbuf b = ofpbuf_const_initializer(buf->data, buf->size); + struct nlmsghdr *nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg); + struct genlmsghdr *genl = ofpbuf_try_pull(&b, sizeof *genl); + struct ovs_header *ovs_header = ofpbuf_try_pull(&b, sizeof *ovs_header); + + struct nlattr *attr[ARRAY_SIZE(ovs_ct_limit_policy)]; + + if (!nlmsg || !genl || !ovs_header + || nlmsg->nlmsg_type != ovs_ct_limit_family + || !nl_policy_parse(&b, 0, ovs_ct_limit_policy, attr, + ARRAY_SIZE(ovs_ct_limit_policy))) { + return EINVAL; + } + + + if (!attr[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]) { + return EINVAL; + } + + int rem = NLA_ALIGN( + nl_attr_get_size(attr[OVS_CT_LIMIT_ATTR_ZONE_LIMIT])); + const struct ovs_zone_limit *zone_limit = + nl_attr_get(attr[OVS_CT_LIMIT_ATTR_ZONE_LIMIT]); + + while (rem >= sizeof *zone_limit) { + if (zone_limit->zone_id == OVS_ZONE_LIMIT_DEFAULT_ZONE) { + *default_limit = zone_limit->limit; + } else if (zone_limit->zone_id < OVS_ZONE_LIMIT_DEFAULT_ZONE || + zone_limit->zone_id > UINT16_MAX) { + } else { + ct_dpif_push_zone_limit(zone_limits, zone_limit->zone_id, + zone_limit->limit, zone_limit->count); + } + rem -= NLA_ALIGN(sizeof *zone_limit); + zone_limit = ALIGNED_CAST(struct ovs_zone_limit *, + (unsigned char *) zone_limit + NLA_ALIGN(sizeof *zone_limit)); + } + return 0; +} + +static int +dpif_netlink_get_limits(struct dpif *dpif OVS_UNUSED, uint32_t *default_limit, + const struct ovs_list *zone_limits_request, + struct ovs_list *zone_limits_reply) +{ + struct ofpbuf *request, *reply; + struct ovs_header *ovs_header; + struct ovs_zone_limit req_zone_limit; + struct ct_dpif_zone_limit *zone_limit; + size_t opt_offset; + int err; + + if (ovs_ct_limit_family < 0) { + return EOPNOTSUPP; + } + + request = ofpbuf_new(NL_DUMP_BUFSIZE); + nl_msg_put_genlmsghdr(request, 0, ovs_ct_limit_family, + NLM_F_REQUEST | NLM_F_ECHO, OVS_CT_LIMIT_CMD_GET, + OVS_CT_LIMIT_VERSION); + + ovs_header = ofpbuf_put_uninit(request, sizeof *ovs_header); + ovs_header->dp_ifindex = 0; + + if (!ovs_list_is_empty(zone_limits_request)) { + opt_offset = nl_msg_start_nested(request, + OVS_CT_LIMIT_ATTR_ZONE_LIMIT); + + req_zone_limit.zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE; + nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit); + + LIST_FOR_EACH (zone_limit, node, zone_limits_request) { + req_zone_limit.zone_id = zone_limit->zone; + nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit); + } + + nl_msg_end_nested(request, opt_offset); + } + + err = nl_transact(NETLINK_GENERIC, request, &reply); + if (err) { + goto out; + } + + err = dpif_netlink_zone_limits_from_ofpbuf(reply, default_limit, + zone_limits_reply); + +out: + ofpbuf_uninit(request); + ofpbuf_uninit(reply); + return err; +} + +static int +dpif_netlink_del_limits(struct dpif *dpif OVS_UNUSED, + const struct ovs_list *zone_limits) +{ + struct ovs_zone_limit req_zone_limit; + struct ofpbuf *request; + struct ovs_header *ovs_header; + size_t opt_offset; + int err; + + if (ovs_ct_limit_family < 0) { + return EOPNOTSUPP; + } + + request = ofpbuf_new(NL_DUMP_BUFSIZE); + nl_msg_put_genlmsghdr(request, 0, ovs_ct_limit_family, + NLM_F_REQUEST | NLM_F_ECHO, OVS_CT_LIMIT_CMD_DEL, + OVS_CT_LIMIT_VERSION); + + ovs_header = ofpbuf_put_uninit(request, sizeof *ovs_header); + ovs_header->dp_ifindex = 0; + + if (!ovs_list_is_empty(zone_limits)) { + struct ct_dpif_zone_limit *zone_limit; + + opt_offset = + nl_msg_start_nested(request, OVS_CT_LIMIT_ATTR_ZONE_LIMIT); + + LIST_FOR_EACH (zone_limit, node, zone_limits) { + req_zone_limit.zone_id = zone_limit->zone; + nl_msg_put(request, &req_zone_limit, sizeof req_zone_limit); + } + nl_msg_end_nested(request, opt_offset); + } + + err = nl_transact(NETLINK_GENERIC, request, NULL); + + ofpbuf_uninit(request); + return err; +} /* Meters */ @@ -3252,9 +3442,9 @@ const struct dpif_class dpif_netlink_class = { NULL, /* ct_set_maxconns */ NULL, /* ct_get_maxconns */ NULL, /* ct_get_nconns */ - NULL, /* ct_set_limits */ - NULL, /* ct_get_limits */ - NULL, /* ct_del_limits */ + dpif_netlink_set_limits, + dpif_netlink_get_limits, + dpif_netlink_del_limits, dpif_netlink_meter_get_features, dpif_netlink_meter_set, dpif_netlink_meter_get, @@ -3294,6 +3484,12 @@ dpif_netlink_init(void) VLOG_INFO("The kernel module does not support meters."); } } + if (nl_lookup_genl_family(OVS_CT_LIMIT_FAMILY, + &ovs_ct_limit_family) < 0) { + VLOG_INFO("Generic Netlink family '%s' does not exist. " + "Please update the Open vSwitch kernel module to enable " + "the conntrack limit feature.", OVS_CT_LIMIT_FAMILY); + } ovs_tunnels_out_of_tree = dpif_netlink_rtnl_probe_oot_tunnels();