Re: [ovs-dev] [PATCH v2 ovn 1/2] controller: add ipv6 prefix delegation state machine

2019-11-28 Thread Numan Siddique
On Thu, Nov 28, 2019 at 3:53 PM Numan Siddique  wrote:
>
> On Tue, Nov 26, 2019 at 5:21 PM Lorenzo Bianconi
>  wrote:
> >
> > Introduce IPv6 Prefix delegation state machine according to RFC 3633
> > https://tools.ietf.org/html/rfc3633.
> > Add handle_dhcpv6_reply controller action to parse advertise/reply from
> > IPv6 delegation server. Advertise/reply are parsed running respectively:
> > - pinctrl_parse_dhcv6_advt
> > - pinctrl_parse_dhcv6_reply
> > The IPv6 requesting router starts sending dhcpv6 solicit through the logical
> > router port marked with ipv6_prefix_delegation set to true.
> > An IPv6 prefix will be requested for each logical router port marked
> > with "prefix" set to true in option column of logical router port table.
> > Save IPv6 prefix received by IPv6 delegation router in the options column of
> > SB port binding table in order to be reused by Router Advertisement 
> > framework
> > run by ovn logical router pipeline.
> > IPv6 Prefix delegation state machine is enabled on Gateway Router or on
> > a Gateway Router Port
> >
> > Signed-off-by: Lorenzo Bianconi 
>
> Thanks Lorenzo for the patches.
>
> The patch LGTM. A couple of comments
>
>  1. Can you please change the option name in the OVN NB DB from "prf"
> to "router_preference"
>  Using "ipv6_ra_prf" in south db is fine with me.
>
> 2. Can you please enhance the IPv6 RA test case and this option as well.
>
> Thanks
> Numan

Oops.  Please ignore this. I meant to reply to your patches related to RFC 4191.

Thanks
Numan

>
> > ---
> >  controller/pinctrl.c  | 607 ++
> >  include/ovn/actions.h |   8 +-
> >  lib/actions.c |  22 ++
> >  lib/ovn-l7.h  |  19 ++
> >  ovn-sb.xml|   8 +
> >  tests/ovn.at  |   6 +
> >  utilities/ovn-trace.c |   3 +
> >  7 files changed, 672 insertions(+), 1 deletion(-)
> >
> > diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> > index 8fc31d38a..a51fdaaca 100644
> > --- a/controller/pinctrl.c
> > +++ b/controller/pinctrl.c
> > @@ -270,6 +270,19 @@ static void pinctrl_ip_mcast_handle_igmp(
> >  const struct match *md,
> >  struct ofpbuf *userdata);
> >
> > +static void init_ipv6_prefixd(void);
> > +static void destroy_ipv6_prefixd(void);
> > +static void ipv6_prefixd_wait(long long int timeout);
> > +static void
> > +prepare_ipv6_prefix_req(struct ovsdb_idl_index 
> > *sbrec_port_binding_by_datapath,
> > +struct ovsdb_idl_index *sbrec_port_binding_by_name,
> > +const struct hmap *local_datapaths,
> > +const struct sbrec_chassis *chassis,
> > +const struct sset *active_tunnels)
> > +OVS_REQUIRES(pinctrl_mutex);
> > +static void
> > +send_ipv6_prefix_msg(struct rconn *swconn, long long int 
> > *send_prefixd_time)
> > +OVS_REQUIRES(pinctrl_mutex);
> >  static bool may_inject_pkts(void);
> >
> >  static void init_put_vport_bindings(void);
> > @@ -457,6 +470,7 @@ pinctrl_init(void)
> >  init_put_mac_bindings();
> >  init_send_garps_rarps();
> >  init_ipv6_ras();
> > +init_ipv6_prefixd();
> >  init_buffered_packets_map();
> >  init_event_table();
> >  ip_mcast_snoop_init();
> > @@ -544,6 +558,57 @@ set_actions_and_enqueue_msg(struct rconn *swconn,
> >  ofpbuf_uninit();
> >  }
> >
> > +static struct shash ipv6_prefixd;
> > +
> > +enum {
> > +PREFIX_SOLICIT,
> > +PREFIX_PENDING,
> > +PREFIX_DONE,
> > +};
> > +
> > +struct ipv6_prefixd_state {
> > +long long int next_announce;
> > +struct in6_addr ipv6_addr;
> > +struct eth_addr ea;
> > +struct eth_addr cmac;
> > +int64_t port_key;
> > +int64_t metadata;
> > +struct in6_addr prefix;
> > +unsigned plife_time;
> > +unsigned vlife_time;
> > +unsigned aid;
> > +unsigned t1;
> > +unsigned t2;
> > +int8_t plen;
> > +int state;
> > +};
> > +
> > +static void
> > +init_ipv6_prefixd(void)
> > +{
> > +shash_init(_prefixd);
> > +}
> > +
> > +static void
> > +ipv6_prefixd_delete(struct ipv6_prefixd_state *pfd)
> > +{
> > +if (pfd) {
> > +free(pfd);
> > +}
> > +}
> > +
> > +static void
> > +destroy_ipv6_prefixd(void)
> > +{
> > +struct shash_node *iter, *next;
> > +SHASH_FOR_EACH_SAFE (iter, next, _prefixd) {
> > +struct ipv6_prefixd_state *pfd = iter->data;
> > +ipv6_prefixd_delete(pfd);
> > +shash_delete(_prefixd, iter);
> > +}
> > +shash_destroy(_prefixd);
> > +}
> > +
> >  struct buffer_info {
> >  struct ofpbuf ofpacts;
> >  struct dp_packet *p;
> > @@ -967,6 +1032,254 @@ pinctrl_handle_tcp_reset(struct rconn *swconn, const 
> > struct flow *ip_flow,
> >  dp_packet_uninit();
> >  }
> >
> > +static void
> > +pinctrl_parse_dhcv6_advt(struct rconn *swconn, const struct flow *ip_flow,
> > + struct dp_packet *pkt_in, const struct match *md,
> > + struct ofpbuf 

Re: [ovs-dev] [PATCH v2 ovn 1/2] controller: add ipv6 prefix delegation state machine

2019-11-28 Thread Numan Siddique
On Tue, Nov 26, 2019 at 5:21 PM Lorenzo Bianconi
 wrote:
>
> Introduce IPv6 Prefix delegation state machine according to RFC 3633
> https://tools.ietf.org/html/rfc3633.
> Add handle_dhcpv6_reply controller action to parse advertise/reply from
> IPv6 delegation server. Advertise/reply are parsed running respectively:
> - pinctrl_parse_dhcv6_advt
> - pinctrl_parse_dhcv6_reply
> The IPv6 requesting router starts sending dhcpv6 solicit through the logical
> router port marked with ipv6_prefix_delegation set to true.
> An IPv6 prefix will be requested for each logical router port marked
> with "prefix" set to true in option column of logical router port table.
> Save IPv6 prefix received by IPv6 delegation router in the options column of
> SB port binding table in order to be reused by Router Advertisement framework
> run by ovn logical router pipeline.
> IPv6 Prefix delegation state machine is enabled on Gateway Router or on
> a Gateway Router Port
>
> Signed-off-by: Lorenzo Bianconi 

Thanks Lorenzo for the patches.

The patch LGTM. A couple of comments

 1. Can you please change the option name in the OVN NB DB from "prf"
to "router_preference"
 Using "ipv6_ra_prf" in south db is fine with me.

2. Can you please enhance the IPv6 RA test case and this option as well.

Thanks
Numan

> ---
>  controller/pinctrl.c  | 607 ++
>  include/ovn/actions.h |   8 +-
>  lib/actions.c |  22 ++
>  lib/ovn-l7.h  |  19 ++
>  ovn-sb.xml|   8 +
>  tests/ovn.at  |   6 +
>  utilities/ovn-trace.c |   3 +
>  7 files changed, 672 insertions(+), 1 deletion(-)
>
> diff --git a/controller/pinctrl.c b/controller/pinctrl.c
> index 8fc31d38a..a51fdaaca 100644
> --- a/controller/pinctrl.c
> +++ b/controller/pinctrl.c
> @@ -270,6 +270,19 @@ static void pinctrl_ip_mcast_handle_igmp(
>  const struct match *md,
>  struct ofpbuf *userdata);
>
> +static void init_ipv6_prefixd(void);
> +static void destroy_ipv6_prefixd(void);
> +static void ipv6_prefixd_wait(long long int timeout);
> +static void
> +prepare_ipv6_prefix_req(struct ovsdb_idl_index 
> *sbrec_port_binding_by_datapath,
> +struct ovsdb_idl_index *sbrec_port_binding_by_name,
> +const struct hmap *local_datapaths,
> +const struct sbrec_chassis *chassis,
> +const struct sset *active_tunnels)
> +OVS_REQUIRES(pinctrl_mutex);
> +static void
> +send_ipv6_prefix_msg(struct rconn *swconn, long long int *send_prefixd_time)
> +OVS_REQUIRES(pinctrl_mutex);
>  static bool may_inject_pkts(void);
>
>  static void init_put_vport_bindings(void);
> @@ -457,6 +470,7 @@ pinctrl_init(void)
>  init_put_mac_bindings();
>  init_send_garps_rarps();
>  init_ipv6_ras();
> +init_ipv6_prefixd();
>  init_buffered_packets_map();
>  init_event_table();
>  ip_mcast_snoop_init();
> @@ -544,6 +558,57 @@ set_actions_and_enqueue_msg(struct rconn *swconn,
>  ofpbuf_uninit();
>  }
>
> +static struct shash ipv6_prefixd;
> +
> +enum {
> +PREFIX_SOLICIT,
> +PREFIX_PENDING,
> +PREFIX_DONE,
> +};
> +
> +struct ipv6_prefixd_state {
> +long long int next_announce;
> +struct in6_addr ipv6_addr;
> +struct eth_addr ea;
> +struct eth_addr cmac;
> +int64_t port_key;
> +int64_t metadata;
> +struct in6_addr prefix;
> +unsigned plife_time;
> +unsigned vlife_time;
> +unsigned aid;
> +unsigned t1;
> +unsigned t2;
> +int8_t plen;
> +int state;
> +};
> +
> +static void
> +init_ipv6_prefixd(void)
> +{
> +shash_init(_prefixd);
> +}
> +
> +static void
> +ipv6_prefixd_delete(struct ipv6_prefixd_state *pfd)
> +{
> +if (pfd) {
> +free(pfd);
> +}
> +}
> +
> +static void
> +destroy_ipv6_prefixd(void)
> +{
> +struct shash_node *iter, *next;
> +SHASH_FOR_EACH_SAFE (iter, next, _prefixd) {
> +struct ipv6_prefixd_state *pfd = iter->data;
> +ipv6_prefixd_delete(pfd);
> +shash_delete(_prefixd, iter);
> +}
> +shash_destroy(_prefixd);
> +}
> +
>  struct buffer_info {
>  struct ofpbuf ofpacts;
>  struct dp_packet *p;
> @@ -967,6 +1032,254 @@ pinctrl_handle_tcp_reset(struct rconn *swconn, const 
> struct flow *ip_flow,
>  dp_packet_uninit();
>  }
>
> +static void
> +pinctrl_parse_dhcv6_advt(struct rconn *swconn, const struct flow *ip_flow,
> + struct dp_packet *pkt_in, const struct match *md,
> + struct ofpbuf *userdata)
> +{
> +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));
> +uint8_t *data, *end = (uint8_t *)udp_in + dlen;
> +int len = 0;
> +
> +data = xmalloc(dlen);
> +if (!data) {
> +return;
> +}
> +
> +in_dhcpv6_data += 4;
> +
> +while (in_dhcpv6_data < end) {
> + 

[ovs-dev] [PATCH v2 ovn 1/2] controller: add ipv6 prefix delegation state machine

2019-11-26 Thread Lorenzo Bianconi
Introduce IPv6 Prefix delegation state machine according to RFC 3633
https://tools.ietf.org/html/rfc3633.
Add handle_dhcpv6_reply controller action to parse advertise/reply from
IPv6 delegation server. Advertise/reply are parsed running respectively:
- pinctrl_parse_dhcv6_advt
- pinctrl_parse_dhcv6_reply
The IPv6 requesting router starts sending dhcpv6 solicit through the logical
router port marked with ipv6_prefix_delegation set to true.
An IPv6 prefix will be requested for each logical router port marked
with "prefix" set to true in option column of logical router port table.
Save IPv6 prefix received by IPv6 delegation router in the options column of
SB port binding table in order to be reused by Router Advertisement framework
run by ovn logical router pipeline.
IPv6 Prefix delegation state machine is enabled on Gateway Router or on
a Gateway Router Port

Signed-off-by: Lorenzo Bianconi 
---
 controller/pinctrl.c  | 607 ++
 include/ovn/actions.h |   8 +-
 lib/actions.c |  22 ++
 lib/ovn-l7.h  |  19 ++
 ovn-sb.xml|   8 +
 tests/ovn.at  |   6 +
 utilities/ovn-trace.c |   3 +
 7 files changed, 672 insertions(+), 1 deletion(-)

diff --git a/controller/pinctrl.c b/controller/pinctrl.c
index 8fc31d38a..a51fdaaca 100644
--- a/controller/pinctrl.c
+++ b/controller/pinctrl.c
@@ -270,6 +270,19 @@ static void pinctrl_ip_mcast_handle_igmp(
 const struct match *md,
 struct ofpbuf *userdata);
 
+static void init_ipv6_prefixd(void);
+static void destroy_ipv6_prefixd(void);
+static void ipv6_prefixd_wait(long long int timeout);
+static void
+prepare_ipv6_prefix_req(struct ovsdb_idl_index *sbrec_port_binding_by_datapath,
+struct ovsdb_idl_index *sbrec_port_binding_by_name,
+const struct hmap *local_datapaths,
+const struct sbrec_chassis *chassis,
+const struct sset *active_tunnels)
+OVS_REQUIRES(pinctrl_mutex);
+static void
+send_ipv6_prefix_msg(struct rconn *swconn, long long int *send_prefixd_time)
+OVS_REQUIRES(pinctrl_mutex);
 static bool may_inject_pkts(void);
 
 static void init_put_vport_bindings(void);
@@ -457,6 +470,7 @@ pinctrl_init(void)
 init_put_mac_bindings();
 init_send_garps_rarps();
 init_ipv6_ras();
+init_ipv6_prefixd();
 init_buffered_packets_map();
 init_event_table();
 ip_mcast_snoop_init();
@@ -544,6 +558,57 @@ set_actions_and_enqueue_msg(struct rconn *swconn,
 ofpbuf_uninit();
 }
 
+static struct shash ipv6_prefixd;
+
+enum {
+PREFIX_SOLICIT,
+PREFIX_PENDING,
+PREFIX_DONE,
+};
+
+struct ipv6_prefixd_state {
+long long int next_announce;
+struct in6_addr ipv6_addr;
+struct eth_addr ea;
+struct eth_addr cmac;
+int64_t port_key;
+int64_t metadata;
+struct in6_addr prefix;
+unsigned plife_time;
+unsigned vlife_time;
+unsigned aid;
+unsigned t1;
+unsigned t2;
+int8_t plen;
+int state;
+};
+
+static void
+init_ipv6_prefixd(void)
+{
+shash_init(_prefixd);
+}
+
+static void
+ipv6_prefixd_delete(struct ipv6_prefixd_state *pfd)
+{
+if (pfd) {
+free(pfd);
+}
+}
+
+static void
+destroy_ipv6_prefixd(void)
+{
+struct shash_node *iter, *next;
+SHASH_FOR_EACH_SAFE (iter, next, _prefixd) {
+struct ipv6_prefixd_state *pfd = iter->data;
+ipv6_prefixd_delete(pfd);
+shash_delete(_prefixd, iter);
+}
+shash_destroy(_prefixd);
+}
+
 struct buffer_info {
 struct ofpbuf ofpacts;
 struct dp_packet *p;
@@ -967,6 +1032,254 @@ pinctrl_handle_tcp_reset(struct rconn *swconn, const 
struct flow *ip_flow,
 dp_packet_uninit();
 }
 
+static void
+pinctrl_parse_dhcv6_advt(struct rconn *swconn, const struct flow *ip_flow,
+ struct dp_packet *pkt_in, const struct match *md,
+ struct ofpbuf *userdata)
+{
+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));
+uint8_t *data, *end = (uint8_t *)udp_in + dlen;
+int len = 0;
+
+data = xmalloc(dlen);
+if (!data) {
+return;
+}
+
+in_dhcpv6_data += 4;
+
+while (in_dhcpv6_data < end) {
+struct dhcpv6_opt_header *in_opt =
+ (struct dhcpv6_opt_header *)in_dhcpv6_data;
+int opt_len = sizeof *in_opt + ntohs(in_opt->len);
+
+if (dlen < opt_len + len) {
+goto out;
+}
+
+switch (ntohs(in_opt->code)) {
+case DHCPV6_OPT_IA_PD: {
+int orig_len = len, hdr_len = 0, size = sizeof *in_opt + 12;
+
+memcpy([len], in_opt, size);
+in_opt = (struct dhcpv6_opt_header *)(in_dhcpv6_data + size);
+len += size;
+
+while (size < opt_len) {
+int flen = sizeof *in_opt + ntohs(in_opt->len);
+
+