From patchwork Mon Oct 12 09:05:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 1380747 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.138; helo=whitealder.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Z5LW4/VI; dkim-atps=neutral Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C8t8C46kRz9sSs for ; Mon, 12 Oct 2020 20:06:19 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 08314869E2; Mon, 12 Oct 2020 09:06:16 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 92aX1MiqZv1X; Mon, 12 Oct 2020 09:06:12 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 37FD5869D7; Mon, 12 Oct 2020 09:06:12 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1BC8FC07FF; Mon, 12 Oct 2020 09:06:12 +0000 (UTC) X-Original-To: ovs-dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id D8590C0051 for ; Mon, 12 Oct 2020 09:06:10 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id B0F47204EC for ; Mon, 12 Oct 2020 09:06:10 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ZdNLd29Y4SYR for ; Mon, 12 Oct 2020 09:06:08 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by silver.osuosl.org (Postfix) with ESMTPS id 093E1204EA for ; Mon, 12 Oct 2020 09:06:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1602493566; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=BMioO9BN5Qm2gzCDZW7ORbNIeMywoULCP4TMhga1rQY=; b=Z5LW4/VIuGDDV08mWAf6vaTzrE7NPMD08PK5hq94XLA469x6WT6+1TQqu8e9AYJMEUqF7o qk3qkah4Ir9bbEAqFt8/s0JlXa8nH+bq+J7Zqo8lGLZ7FqiIwXH+OS3JxtFkhC9i51N0sx snXvRl9ZQyvoqjnWEq649nED5XBuRCY= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-581-k0N-e1teNNu2zd5VTgRFMQ-1; Mon, 12 Oct 2020 05:06:03 -0400 X-MC-Unique: k0N-e1teNNu2zd5VTgRFMQ-1 Received: by mail-wm1-f69.google.com with SMTP id s25so5478591wmj.7 for ; Mon, 12 Oct 2020 02:06:03 -0700 (PDT) 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:mime-version :content-transfer-encoding; bh=BMioO9BN5Qm2gzCDZW7ORbNIeMywoULCP4TMhga1rQY=; b=t68SvcCpu57+xpXDss/ctmbDWYXh+Xm5pA6vboNrd9pQz1YGhPD48dVPwafcRHrNTD KpZgKuEWWojCG5y3B4cAGg6ajXlrvPBtpioNJjHUHAjwMppizjI+SZlJ9O+A0O1JIpaG MPD0x6IfAPfyiJJRa3/7DthHuTDzhVS4/pAvJkqsOn/qd4SsNNqU+D9loSI/q2QEGWLt gv/bBlu3fY4vxPbNBpEyxdK6iJzqH3lC1hJmUyYKSwvdh518+P06Lca32QCiJGVutvml zDZDuh/o+e+voBzpVZLrTqCgpRn8m8z7Yv9iTpCPv3rxqJktuycxiLb3/DGCvvaTOQvm H62A== X-Gm-Message-State: AOAM530UrMDhJo2ghsigrXTf8SG/fDbJx6OD1IdwIBXCAhHeiAIw/IP8 BaIuwj0hHsk2hc58X4kPPYVDyrw1xXdR+QYxd4mtXlf7V+VFH7zlR3hVpPxDjhJGL2GvlkoHT1y ViCOmW6tbjpywdZDt/w== X-Received: by 2002:a05:600c:2707:: with SMTP id 7mr10125768wmm.147.1602493561681; Mon, 12 Oct 2020 02:06:01 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz46blNkJkmywC54xEiCiuFydAXVFGArjp+v749vFU7MbdkSA9L5lRrp4G4hGb1b3JjHQrfQg== X-Received: by 2002:a05:600c:2707:: with SMTP id 7mr10125730wmm.147.1602493561345; Mon, 12 Oct 2020 02:06:01 -0700 (PDT) Received: from lore-desk.redhat.com ([176.207.245.61]) by smtp.gmail.com with ESMTPSA id l1sm3375914wrb.1.2020.10.12.02.06.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Oct 2020 02:06:00 -0700 (PDT) From: Lorenzo Bianconi To: ovs-dev@openvswitch.org Date: Mon, 12 Oct 2020 11:05:54 +0200 Message-Id: <96c5d020bee86dbe24d862fea5e8175c50754de2.1602492524.git.lorenzo.bianconi@redhat.com> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=lorenzo.bianconi@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: [ovs-dev] [PATCH v2 ovn] controller: IPv6 Prefix-Delegation: introduce RENEW/REBIND msg support X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Introduce RENEW/REBIND message support to OVN IPv6 PD support according to RFC-3633 [0] in order to renew IPv6 prefixes when T1/T2 are elapsed [0] https://tools.ietf.org/html/rfc3633 Acked-by: Mark Michelson Signed-off-by: Lorenzo Bianconi --- Changes since v1: - fixed compilation warning --- controller/pinctrl.c | 131 +++++++++++++++++++++++++++++++++---------- lib/ovn-l7.h | 3 + tests/system-ovn.at | 18 ++++-- 3 files changed, 118 insertions(+), 34 deletions(-) diff --git a/controller/pinctrl.c b/controller/pinctrl.c index 0a7020533..c1ef1610f 100644 --- a/controller/pinctrl.c +++ b/controller/pinctrl.c @@ -573,11 +573,22 @@ enum { PREFIX_REQUEST, PREFIX_PENDING, PREFIX_DONE, + PREFIX_RENEW, + PREFIX_REBIND, }; struct ipv6_prefixd_state { long long int next_announce; + long long int last_complete; long long int last_used; + /* IPv6 PD server info */ + struct in6_addr server_addr; + struct eth_addr sa; + /* server_id_info */ + struct { + uint8_t *data; + uint8_t len; + } uuid; struct in6_addr ipv6_addr; struct eth_addr ea; struct eth_addr cmac; @@ -781,20 +792,26 @@ out: static void pinctrl_prefixd_state_handler(const struct flow *ip_flow, struct in6_addr addr, unsigned aid, + struct eth_addr sa, struct in6_addr server_addr, char prefix_len, unsigned t1, unsigned t2, - unsigned plife_time, unsigned vlife_time) + unsigned plife_time, unsigned vlife_time, + uint8_t *uuid, uint8_t uuid_len) { struct ipv6_prefixd_state *pfd; pfd = pinctrl_find_prefixd_state(ip_flow, aid); if (pfd) { pfd->state = PREFIX_PENDING; - pfd->plife_time = plife_time; - pfd->vlife_time = vlife_time; + pfd->server_addr = server_addr; + pfd->sa = sa; + pfd->uuid.data = uuid; + pfd->uuid.len = uuid_len; + pfd->plife_time = plife_time * 1000; + pfd->vlife_time = vlife_time * 1000; pfd->plen = prefix_len; pfd->prefix = addr; - pfd->t1 = t1; - pfd->t2 = t2; + pfd->t1 = t1 * 1000; + pfd->t2 = t2 * 1000; notify_pinctrl_main(); } } @@ -804,19 +821,21 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in, const struct flow *ip_flow) OVS_REQUIRES(pinctrl_mutex) { + struct eth_header *eth = dp_packet_eth(pkt_in); + struct ip6_hdr *in_ip = dp_packet_l3(pkt_in); struct udp_header *udp_in = dp_packet_l4(pkt_in); unsigned char *in_dhcpv6_data = (unsigned char *)(udp_in + 1); size_t dlen = MIN(ntohs(udp_in->udp_len), dp_packet_l4_size(pkt_in)); unsigned t1 = 0, t2 = 0, vlife_time = 0, plife_time = 0; - uint8_t *end = (uint8_t *)udp_in + dlen; - uint8_t prefix_len = 0; - struct in6_addr ipv6; + uint8_t *end = (uint8_t *)udp_in + dlen, *uuid = NULL; + uint8_t prefix_len = 0, uuid_len = 0; + struct in6_addr ipv6 = in6addr_any; bool status = false; unsigned aid = 0; - memset(&ipv6, 0, sizeof (struct in6_addr)); /* skip DHCPv6 common header */ in_dhcpv6_data += 4; + while (in_dhcpv6_data < end) { struct dhcpv6_opt_header *in_opt = (struct dhcpv6_opt_header *)in_dhcpv6_data; @@ -867,14 +886,20 @@ pinctrl_parse_dhcpv6_reply(struct dp_packet *pkt_in, } break; } + case DHCPV6_OPT_SERVER_ID_CODE: + uuid_len = ntohs(in_opt->len); + uuid = xmalloc(uuid_len); + memcpy(uuid, in_opt + 1, uuid_len); + break; default: break; } in_dhcpv6_data += opt_len; } if (status) { - pinctrl_prefixd_state_handler(ip_flow, ipv6, aid, prefix_len, - t1, t2, plife_time, vlife_time); + pinctrl_prefixd_state_handler(ip_flow, ipv6, aid, eth->eth_src, + in_ip->ip6_src, prefix_len, t1, t2, + plife_time, vlife_time, uuid, uuid_len); } } @@ -904,27 +929,42 @@ pinctrl_handle_dhcp6_server(struct rconn *swconn, const struct flow *ip_flow, } static void -compose_prefixd_solicit(struct dp_packet *b, - struct ipv6_prefixd_state *pfd, - const struct eth_addr eth_dst, - const struct in6_addr *ipv6_dst) +compose_prefixd_packet(struct dp_packet *b, struct ipv6_prefixd_state *pfd) { - eth_compose(b, eth_dst, pfd->ea, ETH_TYPE_IPV6, IPV6_HEADER_LEN); + struct in6_addr ipv6_dst; + struct eth_addr eth_dst; int payload = sizeof(struct dhcpv6_opt_server_id) + sizeof(struct dhcpv6_opt_ia_na); + if (pfd->uuid.len) { + payload += pfd->uuid.len + sizeof(struct dhcpv6_opt_header); + ipv6_dst = pfd->server_addr; + eth_dst = pfd->sa; + } else { + eth_dst = (struct eth_addr) ETH_ADDR_C(33,33,00,01,00,02); + ipv6_parse("ff02::1:2", &ipv6_dst); + } if (ipv6_addr_is_set(&pfd->prefix)) { payload += sizeof(struct dhcpv6_opt_ia_prefix); } + + eth_compose(b, eth_dst, pfd->ea, ETH_TYPE_IPV6, IPV6_HEADER_LEN); + int len = UDP_HEADER_LEN + 4 + payload; struct udp_header *udp_h = compose_ipv6(b, IPPROTO_UDP, &pfd->ipv6_addr, - ipv6_dst, 0, 0, 255, len); + &ipv6_dst, 0, 0, 255, len); udp_h->udp_len = htons(len); udp_h->udp_csum = 0; packet_set_udp_port(b, htons(546), htons(547)); unsigned char *dhcp_hdr = (unsigned char *)(udp_h + 1); - *dhcp_hdr = DHCPV6_MSG_TYPE_SOLICIT; + if (pfd->state == PREFIX_RENEW) { + *dhcp_hdr = DHCPV6_MSG_TYPE_RENEW; + } else if (pfd->state == PREFIX_REBIND) { + *dhcp_hdr = DHCPV6_MSG_TYPE_REBIND; + } else { + *dhcp_hdr = DHCPV6_MSG_TYPE_SOLICIT; + } struct dhcpv6_opt_server_id *opt_client_id = (struct dhcpv6_opt_server_id *)(dhcp_hdr + 4); @@ -935,11 +975,21 @@ compose_prefixd_solicit(struct dp_packet *b, opt_client_id->hw_type = htons(DHCPV6_HW_TYPE_ETH); opt_client_id->mac = pfd->cmac; + unsigned char *ptr = (unsigned char *)(opt_client_id + 1); + if (pfd->uuid.len) { + struct dhcpv6_opt_header *in_opt = (struct dhcpv6_opt_header *)ptr; + in_opt->code = htons(DHCPV6_OPT_SERVER_ID_CODE); + in_opt->len = htons(pfd->uuid.len); + + ptr += sizeof *in_opt; + memcpy(ptr, pfd->uuid.data, pfd->uuid.len); + ptr += pfd->uuid.len; + } + if (!ipv6_addr_is_set(&pfd->prefix)) { pfd->aid = random_uint16(); } - struct dhcpv6_opt_ia_na *ia_pd = - (struct dhcpv6_opt_ia_na *)(opt_client_id + 1); + struct dhcpv6_opt_ia_na *ia_pd = (struct dhcpv6_opt_ia_na *)ptr; ia_pd->opt.code = htons(DHCPV6_OPT_IA_PD); int opt_len = sizeof(struct dhcpv6_opt_ia_na) - sizeof(struct dhcpv6_opt_header); @@ -981,16 +1031,15 @@ ipv6_prefixd_send(struct rconn *swconn, struct ipv6_prefixd_state *pfd) return pfd->next_announce; } + if (pfd->state == PREFIX_DONE) { + goto out; + } + uint64_t packet_stub[256 / 8]; struct dp_packet packet; - struct eth_addr eth_dst; - eth_dst = (struct eth_addr) ETH_ADDR_C(33,33,00,01,00,02); - struct in6_addr ipv6_dst; - ipv6_parse("ff02::1:2", &ipv6_dst); - dp_packet_use_stub(&packet, packet_stub, sizeof packet_stub); - compose_prefixd_solicit(&packet, pfd, eth_dst, &ipv6_dst); + compose_prefixd_packet(&packet, pfd); uint64_t ofpacts_stub[4096 / 8]; struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub); @@ -1019,8 +1068,9 @@ ipv6_prefixd_send(struct rconn *swconn, struct ipv6_prefixd_state *pfd) queue_msg(swconn, ofputil_encode_packet_out(&po, proto)); dp_packet_uninit(&packet); ofpbuf_uninit(&ofpacts); + +out: pfd->next_announce = cur_time + random_range(IPV6_PREFIXD_TIMEOUT); - pfd->state = PREFIX_SOLICIT; return pfd->next_announce; } @@ -1031,10 +1081,28 @@ static bool ipv6_prefixd_should_inject(void) SHASH_FOR_EACH (iter, &ipv6_prefixd) { struct ipv6_prefixd_state *pfd = iter->data; + long long int cur_time = time_msec(); + if (pfd->state == PREFIX_SOLICIT) { return true; } - if (pfd->state && pfd->next_announce < time_msec()) { + if (pfd->state == PREFIX_DONE && + cur_time > pfd->last_complete + pfd->t1) { + pfd->state = PREFIX_RENEW; + return true; + } + if (pfd->state == PREFIX_RENEW && + cur_time > pfd->last_complete + pfd->t2) { + pfd->state = PREFIX_REBIND; + if (pfd->uuid.len) { + free(pfd->uuid.data); + pfd->uuid.len = 0; + } + return true; + } + if (pfd->state == PREFIX_REBIND && + cur_time > pfd->last_complete + pfd->vlife_time) { + pfd->state = PREFIX_SOLICIT; return true; } } @@ -1120,7 +1188,8 @@ fill_ipv6_prefix_state(struct ovsdb_idl_txn *ovnsb_idl_txn, struct smap options; pfd->state = PREFIX_DONE; - pfd->next_announce = time_msec() + pfd->t1 * 1000; + pfd->last_complete = time_msec(); + pfd->next_announce = pfd->last_complete + pfd->t1; ipv6_string_mapped(prefix_str, &pfd->prefix); smap_clone(&options, &pb->options); smap_add_format(&options, "ipv6_ra_pd_list", "%d:%s/%d", @@ -1219,6 +1288,10 @@ prepare_ipv6_prefixd(struct ovsdb_idl_txn *ovnsb_idl_txn, SHASH_FOR_EACH_SAFE (iter, next, &ipv6_prefixd) { struct ipv6_prefixd_state *pfd = iter->data; if (pfd->last_used + IPV6_PREFIXD_STALE_TIMEOUT < time_msec()) { + if (pfd->uuid.len) { + free(pfd->uuid.data); + pfd->uuid.len = 0; + } free(pfd); shash_delete(&ipv6_prefixd, iter); } diff --git a/lib/ovn-l7.h b/lib/ovn-l7.h index 18c59896d..30a795531 100644 --- a/lib/ovn-l7.h +++ b/lib/ovn-l7.h @@ -189,6 +189,9 @@ struct dhcp_opt6_header { #define DHCPV6_MSG_TYPE_ADVT 2 #define DHCPV6_MSG_TYPE_REQUEST 3 #define DHCPV6_MSG_TYPE_CONFIRM 4 +#define DHCPV6_MSG_TYPE_RENEW 5 +#define DHCPV6_MSG_TYPE_REBIND 6 + #define DHCPV6_MSG_TYPE_REPLY 7 #define DHCPV6_MSG_TYPE_DECLINE 9 #define DHCPV6_MSG_TYPE_INFO_REQ 11 diff --git a/tests/system-ovn.at b/tests/system-ovn.at index 420610f89..60bd20fd4 100644 --- a/tests/system-ovn.at +++ b/tests/system-ovn.at @@ -4768,19 +4768,28 @@ AT_CHECK([ovn-nbctl get logical_router_port rp-sw1 ipv6_prefix | cut -c3-16], [0 [2001:1db8:3333] ]) -kill $(pidof dibbler-server) - prefix=$(ovn-nbctl list logical_router_port rp-public | awk -F/ '/ipv6_prefix/{print substr($1,25,9)}' | sed 's/://g') ovn-nbctl set logical_router_port rp-sw0 options:prefix=false ovn-nbctl set logical_router_port rp-sw1 options:prefix=false -NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[95:4]]=0x${prefix} > public.pcap &]) +# Renew message +NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x05 and ip6[[113:4]]=0x${prefix} > renew.pcap &]) +# Reply message with Status OK +NS_CHECK_EXEC([server], [tcpdump -c 1 -nni s1 ip6[[48:1]]=0x07 and ip6[[81:4]]=0x${prefix} and ip6[[98:1]]=0x0d and ip6[[101:2]]=0x0000 > reply.pcap &]) + +OVS_WAIT_UNTIL([ + total_pkts=$(cat renew.pcap | wc -l) + test "${total_pkts}" = "1" +]) OVS_WAIT_UNTIL([ - total_pkts=$(cat public.pcap | wc -l) + total_pkts=$(cat reply.pcap | wc -l) test "${total_pkts}" = "1" ]) +kill $(pidof dibbler-server) +kill $(pidof tcpdump) + ovn-nbctl set logical_router_port rp-sw0 options:prefix=false ovn-nbctl clear logical_router_port rp-sw0 ipv6_prefix OVS_WAIT_WHILE([test "$(ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16)" = "[2001:1db8:3333]"]) @@ -4788,7 +4797,6 @@ AT_CHECK([ovn-nbctl get logical_router_port rp-sw0 ipv6_prefix | cut -c3-16], [0 [] ]) -kill $(pidof tcpdump) kill $(pidof ovn-controller) as ovn-sb