From patchwork Mon Nov 12 06:27:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mary Manohar X-Patchwork-Id: 996278 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=nutanix.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=nutanix.com header.i=@nutanix.com header.b="0x9oG/eY"; 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 42tgnv43zDz9s7h for ; Mon, 12 Nov 2018 17:29:07 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 3D17D89C; Mon, 12 Nov 2018 06:27:57 +0000 (UTC) X-Original-To: ovs-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 8FB4A87A for ; Mon, 12 Nov 2018 06:27:54 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mx0b-002c1b01.pphosted.com (mx0b-002c1b01.pphosted.com [148.163.155.12]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 9DE7A7FC for ; Mon, 12 Nov 2018 06:27:53 +0000 (UTC) Received: from pps.filterd (m0127841.ppops.net [127.0.0.1]) by mx0b-002c1b01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id wAC6KeAh002997 for ; Sun, 11 Nov 2018 22:27:52 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nutanix.com; h=from : to : cc : subject : date : message-id : references : in-reply-to : content-type : content-id : content-transfer-encoding : mime-version; s=proofpoint20171006; bh=UfX341H3jQrEgMH0fltqJGJF1xn6BcBIyo1OLds+64E=; b=0x9oG/eYqqqSDHQCW7DGjnOh0w8Xzw5+v4LqTQX8kt5rLJ2waj6LvdWd2PfRmWfyKsR7 H3EhKBxuSlBD5koSksLHiZ4kR7E8mIfCruXCpnBwr9/byt7CkIFXFm0GodDxFMDYVXFf +90t7nbnvewVZzT7VVrIH25ISdZNG+joflKwR71e/Ixpp0rXuoYZShUBoRNnJ05+NxwT 6+WLVG+bzu3G9VV9C8tL9NVUPI0JgG3tO6/qGvInNeKD0wF33fWvqYfQnrqKSqvSXvxb 52WTPRT4nef1YtVIv1Mfbub46x6sfO8gWyvM+BznGrJZEgn20zUpQv495KlXrtVWhfBH kg== Received: from nam05-co1-obe.outbound.protection.outlook.com (mail-co1nam05lp0087.outbound.protection.outlook.com [216.32.181.87]) by mx0b-002c1b01.pphosted.com with ESMTP id 2nnwrbjtmk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Sun, 11 Nov 2018 22:27:52 -0800 Received: from SN6PR02MB3933.namprd02.prod.outlook.com (52.135.69.14) by SN6PR02MB5710.namprd02.prod.outlook.com (20.177.252.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1294.38; Mon, 12 Nov 2018 06:27:50 +0000 Received: from SN6PR02MB3933.namprd02.prod.outlook.com ([fe80::8915:9e5a:ea49:f4b3]) by SN6PR02MB3933.namprd02.prod.outlook.com ([fe80::8915:9e5a:ea49:f4b3%4]) with mapi id 15.20.1294.044; Mon, 12 Nov 2018 06:27:50 +0000 From: Mary Manohar To: "ovs-dev@openvswitch.org" Thread-Topic: [PATCH v2 3/3] Routing policies, ovn-northd changes to handle routing policy commands. Thread-Index: AQHUelDWiETZC1ApUESEV2fIWBfAqw== Date: Mon, 12 Nov 2018 06:27:50 +0000 Message-ID: <1542004180-202310-3-git-send-email-mary.manohar@nutanix.com> References: <1542004180-202310-1-git-send-email-mary.manohar@nutanix.com> In-Reply-To: <1542004180-202310-1-git-send-email-mary.manohar@nutanix.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: BYAPR07CA0031.namprd07.prod.outlook.com (2603:10b6:a02:bc::44) To SN6PR02MB3933.namprd02.prod.outlook.com (2603:10b6:805:2b::14) x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [205.209.132.11] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; SN6PR02MB5710; 6:4v4YUhYT2xXsu8zfCvAP0T1Q1bqI+va/jAYejyielOF6O6ZlE5fUz5juSmqIdodyGNRwOuniyeoMUHYziu17+km/G8OB5QuDV7GicqY4o5AjaDzt6/NkNZrLOR+e0tYtcxgLG81MUSeIjpQpymrkWBv2NN0z4KL+TnfPgPdeDIH7nzhZmlKTxaQh/bMkq8CEBD0vSHJ36bP6DUfBLcfO9oZyebh2/Slp/eWEIHuBQ50JR6ZbYDyz8cZYogsIfyQiN7Q+StgS/hkOSWXPCbrxKqn3GpsbJPUQvY0YdsnaI2Pk3fZakBCMnss+lvnLojEgFQH15oxuByo/EG9lYuP8Qse7GWAu7b4RKjHvaM44xDUTevq1mT9o4cUbIPATbXVokTc1KDHTOfdB9Bw1N6dTI+cVhIef0XmwKM8N4Gsofz90x2grJnpucmfaD47Hd8VtakglL8Gkx6rxguSurcVOog==; 5:ZJAajhU2Ixr/FTByFiPAns6A1gIetMctRooHACJCSKd0J72rAGdxQa9bvHSthJV6bO6mUMUHC6Me3vqr2c/4hJk6Pe6dc9x/FGz6FvDA3ELTkgsloKhqozuwbRQshB/iQ3pSB3WdlXBoV73m2MjP/QH+6w2xGoxzsIc2ff7XLlE=; 7:2jZXMvsGd4ziLJxl+505OpJLTLbtAkCMFJhuWy5cQsGgQO6qtSmbPi6E3jmOw5uyw5+ERAYKlW8FIpV9mluBzNC1RdG0bevRfa61vsByB4BfZI37F3W23vWQmfCikW/u3mjv1I92SoAV9hsHnXRFKg== x-ms-office365-filtering-correlation-id: a99bb803-79b6-45ed-e14f-08d64867f853 x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390040)(7020095)(4652040)(8989299)(4534185)(7168020)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(2017052603328)(7167020)(7153060)(7193020); SRVR:SN6PR02MB5710; x-ms-traffictypediagnostic: SN6PR02MB5710: x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(52384705835673)(228109839391802); x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(6040522)(2401047)(8121501046)(5005006)(10201501046)(3231402)(944501410)(52105112)(93006095)(93001095)(3002001)(148016)(149066)(150057)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(20161123560045)(20161123564045)(20161123562045)(201708071742011)(7699051)(76991095); SRVR:SN6PR02MB5710; BCL:0; PCL:0; RULEID:; SRVR:SN6PR02MB5710; x-forefront-prvs: 0854128AF0 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(396003)(366004)(39850400004)(136003)(346002)(376002)(189003)(199004)(2501003)(8936002)(81156014)(6436002)(256004)(2906002)(7736002)(14444005)(5660300001)(6116002)(97736004)(3846002)(6486002)(25786009)(81166006)(316002)(478600001)(6916009)(68736007)(66066001)(305945005)(8676002)(2900100001)(26005)(53936002)(107886003)(102836004)(44832011)(186003)(106356001)(36756003)(55236004)(99286004)(446003)(386003)(486006)(6506007)(476003)(11346002)(2351001)(52116002)(86362001)(6512007)(105586002)(14454004)(71190400001)(5640700003)(76176011)(2616005)(71200400001)(4326008)(64030200001)(21314003); DIR:OUT; SFP:1102; SCL:1; SRVR:SN6PR02MB5710; H:SN6PR02MB3933.namprd02.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; received-spf: None (protection.outlook.com: nutanix.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: xHlbO4HZu2m8kh8PkeBdFQ0eEeFeU62kFGkLj1ZtItXpdyY1HgfNNAMv2N0gmb5R0zsAEd7Z3KodQVRHBmkPU69fnd9z9FlintCLdkE5KZj0pCiH/PGwdg+CUDbjMqn2CiVEFjByjrSNlCb2fh1siypW/JQig3N37thhitbp730lGMzUMgI1YrhMa7fJi/vXVWywXebYyeqoBU77tt6qszkO4M2afZhHbEKbERpjTF6/+X2YTf7mteiR3/dAPoDe7S45ymYjD3iahWPVh4jC5KeLtzOM3X8hE7Q7FGwrHpm5bh/FTZ73YJ6xaaI8w3Cp2jvd4wtMcxGE8ubIpVsChImKrpF8PxQdyUzntS36nwc= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: MIME-Version: 1.0 X-OriginatorOrg: nutanix.com X-MS-Exchange-CrossTenant-Network-Message-Id: a99bb803-79b6-45ed-e14f-08d64867f853 X-MS-Exchange-CrossTenant-originalarrivaltime: 12 Nov 2018 06:27:50.7394 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: bb047546-786f-4de1-bd75-24e5b6f79043 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN6PR02MB5710 X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-11-12_04:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1807170000 definitions=main-1811120059 X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Cc: Mary Manohar Subject: [ovs-dev] [PATCH v2 3/3] Routing policies, ovn-northd changes to handle routing policy commands. 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: , Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org Policy-based routing (PBR) provides a mechanism to configure permit/deny and reroute policies on the router. Permit/deny policies are similar to OVN ACLs, but exist on the logical-router. Reroute policies are needed for service-insertion and service-chaining. Currently, we support only stateless policies. To achieve this, a new table is introduced in the ingress pipeline of the Logical-router. The new table is between the ‘IP Routing’ and the ‘ARP/ND resolution’ table. This way, PBR can override routing decisions and provide a different next-hop. This Series: a. Changes in OVN NB Schema to introduce a new table in the Logical router. b. Add commands to ovn-nbctl to add/delete/list routing policies. c. Changes in ovn-northd to process routing-policy configurations. This Patch: ovn-northd changes to get routing-policies from northbound database and populate the same as logical flows in the southbound database. A new table called 'POLICY' is introduced in the Logical router's ingress pipeline. Each routing-policy configured in the northbound database translates into a single logical flow in the new table. The columns from the Logical_Router_Policy table are used as follows: The priority column is used as priority in the logical-flow. The match column is used as the 'match' string in the logical-flow. The action column is used to determine the action of the logical-flow. When the 'action' is reroute, if the nexthop ip-address is a connected router port or the IP address of a logical port, the logical-flow is constructed to route the packet to the nexthop ip-address. Signed-off-by: Mary Manohar --- ovn/northd/ovn-northd.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 6 deletions(-) diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 58bef7d..5cc9256 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -142,9 +142,10 @@ enum ovn_stage { PIPELINE_STAGE(ROUTER, IN, ND_RA_OPTIONS, 5, "lr_in_nd_ra_options") \ PIPELINE_STAGE(ROUTER, IN, ND_RA_RESPONSE, 6, "lr_in_nd_ra_response") \ PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 7, "lr_in_ip_routing") \ - PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 8, "lr_in_arp_resolve") \ - PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 9, "lr_in_gw_redirect") \ - PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 10, "lr_in_arp_request") \ + PIPELINE_STAGE(ROUTER, IN, POLICY, 8, "lr_in_policy") \ + PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 9, "lr_in_arp_resolve") \ + PIPELINE_STAGE(ROUTER, IN, GW_REDIRECT, 10, "lr_in_gw_redirect") \ + PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 11, "lr_in_arp_request") \ \ /* Logical router egress stages. */ \ PIPELINE_STAGE(ROUTER, OUT, UNDNAT, 0, "lr_out_undnat") \ @@ -4633,6 +4634,111 @@ find_lrp_member_ip(const struct ovn_port *op, const char *ip_s) return NULL; } +static struct ovn_port* +get_outport_for_routing_policy_nexthop(struct ovn_datapath *od, + struct hmap *ports, + int priority, const char *nexthop) +{ + if (nexthop == NULL) + return NULL; + + unsigned int plen = 0; + ovs_be32 nexthop_be32; + /* Verify that the next hop is an IP address with an all-ones mask. */ + char *error = ip_parse_cidr(nexthop, &nexthop_be32, &plen); + if (!error) { + if (plen != 32) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "bad next hop ip %s for routing policy " + "with priority %d, error: %s ", + nexthop, priority, error); + return NULL; + } + } else { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "Failed to parse cidr %s for routing policy " + "with priority %d ", + nexthop, priority); + free(error); + return NULL; + } + + /* find the router port matching the next hop. */ + int i; + struct ovn_port *out_port = NULL; + const char *lrp_addr_s = NULL; + for (i = 0; i < od->nbr->n_ports; i++) { + struct nbrec_logical_router_port *lrp = od->nbr->ports[i]; + out_port = ovn_port_find(ports, lrp->name); + if (!out_port) { + /* This should not happen. */ + continue; + } + lrp_addr_s = find_lrp_member_ip(out_port, nexthop); + if (lrp_addr_s) { + break; + } else { + out_port = NULL; + } + } + if (!out_port) { + /* There is no matched out port. */ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "No path for routing policy priority %d; next hop %s", + priority, nexthop); + return NULL; + } + return out_port; +} + +static void +build_routing_policy_flow(struct hmap *lflows, struct ovn_datapath *od, + struct hmap *ports, + const struct nbrec_logical_router_policy *rule) +{ + struct ds match = DS_EMPTY_INITIALIZER; + struct ds actions = DS_EMPTY_INITIALIZER; + + if (!strcmp(rule->action, "reroute")) { + struct ovn_port *out_port = NULL; + const char *lrp_addr_s = NULL; + out_port = get_outport_for_routing_policy_nexthop( + od, ports, rule->priority, rule->nexthop); + if (out_port == NULL) { + return; + } else { + lrp_addr_s = find_lrp_member_ip(out_port, rule->nexthop); + if (!lrp_addr_s) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); + VLOG_WARN_RL(&rl, "lrp_addr not found for routing policy " + " priority %d nexthop %s", + rule->priority, rule->nexthop); + return; + } else { + ds_put_format(&actions, "reg0 = %s; " + "reg1 = %s; " + "eth.src = %s; " + "outport = %s; " + "flags.loopback = 1; " + "next;", + rule->nexthop, + lrp_addr_s, + out_port->lrp_networks.ea_s, + out_port->json_key); + } + } + } else if (!strcmp(rule->action, "drop")) { + ds_put_cstr(&actions, "drop;"); + } else if (!strcmp(rule->action, "allow")) { + ds_put_cstr(&actions, "next;"); + } + ds_put_format(&match, "%s", rule->match); + ovn_lflow_add(lflows, od, S_ROUTER_IN_POLICY, rule->priority, + ds_cstr(&match), ds_cstr(&actions)); + ds_destroy(&match); + ds_destroy(&actions); +} + static void add_route(struct hmap *lflows, const struct ovn_port *op, const char *lrp_addr_s, const char *network_s, int plen, @@ -6332,9 +6438,35 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, } } + /* Logical router ingress table 8: Policy. + * + * A packet that arrives at this table is an IP packet that should be + * permitted/denied/rerouted to the address in the rule's nexthop. + * This table sets outport to the correct out_port, + * eth.src to the output port's MAC address, + * and '[xx]reg0' to the next-hop IP address (leaving + * 'ip[46].dst', the packet’s final destination, unchanged), and + * advances to the next table for ARP/ND resolution. */ + HMAP_FOR_EACH (od, key_node, datapaths) { + if (!od->nbr) { + continue; + } + /* This is a catch-all rule. It has the lowest priority (0) + * does a match-all("1") and pass-through (next) */ + ovn_lflow_add(lflows, od, S_ROUTER_IN_POLICY, 0, "1", "next;"); + + /* Convert routing policies to flows. */ + for (int i = 0; i < od->nbr->n_policies; i++) { + const struct nbrec_logical_router_policy *rule; + rule = od->nbr->policies[i]; + build_routing_policy_flow(lflows, od, ports, rule); + } + } + + /* XXX destination unreachable */ - /* Local router ingress table 8: ARP Resolution. + /* Local router ingress table 9: ARP Resolution. * * Any packet that reaches this table is an IP packet whose next-hop IP * address is in reg0. (ip4.dst is the final destination.) This table @@ -6533,7 +6665,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, "get_nd(outport, xxreg0); next;"); } - /* Logical router ingress table 9: Gateway redirect. + /* Logical router ingress table 10: Gateway redirect. * * For traffic with outport equal to the l3dgw_port * on a distributed router, this table redirects a subset @@ -6573,7 +6705,7 @@ build_lrouter_flows(struct hmap *datapaths, struct hmap *ports, ovn_lflow_add(lflows, od, S_ROUTER_IN_GW_REDIRECT, 0, "1", "next;"); } - /* Local router ingress table 10: ARP request. + /* Local router ingress table 11: ARP request. * * In the common case where the Ethernet destination has been resolved, * this table outputs the packet (priority 0). Otherwise, it composes