On Mon, Aug 1, 2016 at 7:16 PM, Zong Kai LI <zealo...@gmail.com> wrote:
> This patch tries to implement Router Advertisement (RA) responder for SLAAC > on ovn-northd side. > > It tries to build lflows per each Logical Router Port, who have IPv6 > networks > and set their 'slaac' column to true. > > The lflows will look like: > match=(inport == "lrp-32a71e0b-8b19-4c52-8cde-058325e4df5d" && > ip6.dst == ff02::2 && nd_rs) > action=(nd_ra{slaac(fd80:a123:b345::/64,1450,fa:16:3e:62:f1:e6); > outport = inport; flags.loopback = 1; output;};) > while: > - nd_rs is a new symbol stands for > "icmp6.type == 133 && icmp6.code == 0 && ttl == 255" > - slaac is a new action which accepts ordered parameter list: > - one or more IPv6 prefixes: such as fd80:a123:b345::/64. > - MTU: logical switch MTU, such as 1450. > - MAC address: router port mac address, such as fa:16:3e:62:f1:e6. > - nd_ra is a new action which stands for RA responder, it will compose a > RA > packet per parameters in slaac, and eth.src and ip6.src from packet > being > processed. > This would be a router solicitation responder, since it responds to router solicitation messages by sending router advertisement messages. > > Logical_Router_Port.slaac column will only tell whether ovn should reply a > RA > packet for Router solicitation packet received from the lrp port. To > respond > a RA packet for other scenario will be a future work. > --- > ovn/northd/ovn-northd.c | 94 ++++++++++++++++++++++++++++++++++++---- > ovn/ovn-nb.ovsschema | 6 ++- > ovn/ovn-nb.xml | 11 +++++ > tests/ovn.at | 111 ++++++++++++++++++++++++++++++ > ++++++++++++++++++ > 4 files changed, 213 insertions(+), 9 deletions(-) > > diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c > index d6c14cf..98db819 100644 > --- a/ovn/northd/ovn-northd.c > +++ b/ovn/northd/ovn-northd.c > @@ -126,9 +126,10 @@ enum ovn_stage { > PIPELINE_STAGE(ROUTER, IN, IP_INPUT, 1, "lr_in_ip_input") \ > PIPELINE_STAGE(ROUTER, IN, UNSNAT, 2, "lr_in_unsnat") \ > PIPELINE_STAGE(ROUTER, IN, DNAT, 3, "lr_in_dnat") \ > - PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 4, "lr_in_ip_routing") \ > - PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 5, "lr_in_arp_resolve") \ > - PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 6, "lr_in_arp_request") \ > + PIPELINE_STAGE(ROUTER, IN, RA_RSP, 4, "lr_in_ra_rsp") \ Since this is responding to router solicitation messages, should this be RS_RSP? > + PIPELINE_STAGE(ROUTER, IN, IP_ROUTING, 5, "lr_in_ip_routing") \ > + PIPELINE_STAGE(ROUTER, IN, ARP_RESOLVE, 6, "lr_in_arp_resolve") \ > + PIPELINE_STAGE(ROUTER, IN, ARP_REQUEST, 7, "lr_in_arp_request") \ > \ > /* Logical router egress stages. */ \ > PIPELINE_STAGE(ROUTER, OUT, SNAT, 0, "lr_out_snat") \ > @@ -3409,7 +3443,51 @@ build_lrouter_flows(struct hmap *datapaths, struct > hmap *ports, > "ip", "flags.loopback = 1; ct_dnat;"); > } > > - /* Logical router ingress table 4: IP Routing. > + /* Logical router ingress table 5: RA responder, by default goto next. > Isn't this table 4 now? > + * (priority 0)*/ > + HMAP_FOR_EACH (od, key_node, datapaths) { > + if (!od->nbr) { > + continue; > + } > + > + ovn_lflow_add(lflows, od, S_ROUTER_IN_RA_RSP, 0, "1", "next;"); > + } > + > + /* Logical router ingress table 5: RA responder, reply for 'slaac' > enabled > + * router port. (priority 50)*/ > + HMAP_FOR_EACH (op, key_node, ports) { > + if (!op->nbrp || op->nbrp->peer > + || !op->peer > + || !op->nbrp->slaac > + || !*op->nbrp->slaac) { > + continue; > + } > + > + ds_clear(&match); > + ds_put_format(&match, "inport == %s", op->json_key); > + ds_put_cstr(&match, " && ip6.dst == ff02::2 && nd_rs"); > + ds_clear(&actions); > + ds_put_format(&actions, "nd_ra{slaac("); > + size_t actions_len = actions.length; > + for (size_t i = 0; i != op->lrp_networks.n_ipv6_addrs; i++) { > + if (in6_is_lla(&op->lrp_networks.ipv6_addrs[i].network)) { > + continue; > + } > + ds_put_format(&actions, "%s/%u,", > + op->lrp_networks.ipv6_addrs[i].network_s, > + op->lrp_networks.ipv6_addrs[i].plen); > + } > + if (actions.length != actions_len) { > + ds_put_format(&actions, "%ld,", op->peer->od->nbs->mtu); > + ds_put_cstr(&actions, op->lrp_networks.ea_s); > + ds_put_cstr(&actions, "); outport = inport; flags.loopback = > 1;" > + " output;};"); > + ovn_lflow_add(lflows, op->od, S_ROUTER_IN_RA_RSP, 50, > + ds_cstr(&match), ds_cstr(&actions)); > + } > + } > + > + /* Logical router ingress table 5: IP Routing. > * > * A packet that arrives at this table is an IP packet that should be > * routed to the address in 'ip[46].dst'. This table sets outport to > diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema > index 660db76..f4d57a1 100644 > --- a/ovn/ovn-nb.ovsschema > +++ b/ovn/ovn-nb.ovsschema > @@ -34,6 +34,9 @@ > "other_config": { > "type": {"key": "string", "value": "string", > "min": 0, "max": "unlimited"}}, > + "mtu": {"type": {"key": {"type": "integer", > + "minInteger": 0, > + "maxInteger": 65535}}}, > IPv6 specifies a minimum MTU of 1280, unless 0 is a sentinel value to not include MTU options in router advertisements (which I didn't see code to implement), we should not permit invalid MTUs in the database schema. > "external_ids": { > "type": {"key": "string", "value": "string", > "min": 0, "max": "unlimited"}}}, > _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev