Re: [ovs-dev] [PATCH RFC v2 3/3] ovn: add SLAAC support for IPv6

2016-08-09 Thread Dustin Lundquist
On Mon, Aug 1, 2016 at 7:16 PM, Zong Kai LI  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,
> +  

Re: [ovs-dev] [PATCH RFC v2 2/3] ovn: add SLAAC support for IPv6

2016-08-09 Thread Dustin Lundquist
+
> +struct ofputil_packet_out po = {
> +.packet = dp_packet_data(&packet),
> +.packet_len = dp_packet_size(&packet),
> +.buffer_id = UINT32_MAX,
> +.in_port = OFPP_CONTROLLER,
> +.ofpacts = ofpacts.data,
> +.ofpacts_len = ofpacts.size,
> +};
> +
> +queue_msg(ofputil_encode_packet_out(&po, proto));
> +
> +exit:
> +dp_packet_uninit(&packet);
> +ofpbuf_uninit(&ofpacts);
> +}
> diff --git a/ovn/ovn-sb.xml b/ovn/ovn-sb.xml
> index 13c9526..66a9009 100644
> --- a/ovn/ovn-sb.xml
> +++ b/ovn/ovn-sb.xml
> @@ -1151,8 +1151,38 @@
>
>  
>
> -get_nd(P, A);
> +
> +  nd_ra { slaac(...); action;
> ... };
> +
> +
> +
> +  
> +Generate an IPv6 Router Advertisement (RA) packet per inner
> action
> +'slaac' ordered parameters, and eth.src and ip6.src from
> Router
> +Solicitation (RS) packet being processed.
> +Parameters: One or more IPv6 prefixes, 16-bit MUT,
> 48-bit
>
MTU?

> +mac address.
> +Then executes each nested action on the RA packet.
> +Actions following the ra action, if any, apply to
> the
> +    original, unmodified packet.
> +The composed RA packet will use RS packet eth.src as eth.dst,
> use
> +RS packet ip6.src as ip6.dst, and use 'slaac' action
> parameter mac
> +address and its lla as eth.src and ip6.src.
> +  
> +
> +  
> +The RA packet has the same VLAN header, if any, as the IPv6
> packet
> +it replaces.
> +  
>
> +  
> +Prerequisite: nd_rs
> +  
> +
> +
> +get_arp(P, A);
> +
> +get_nd(P, A);
>  
>
>  Parameters: logical port string field P,
> 128-bit
>
> Is there a reason for specifying the prefixes as the first arguments to
slaac()? Usually variable number arguments are passed last after any fixed
arguments, I would recommend `slacc(sll, mtu, prefix1, ...)` instead.

Other packet in handlers like pinctrl_handle_arp() only accept the
flow_metadata rather than the entire packet, any reason for this change
since only the metadata is used?

Finally tests/test-ovn.c and tests/ovn.at didn't apply cleanly.


Thanks,


Dustin Lundquist
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH RFC v2 1/3] ovn: add SLAAC support for IPv6

2016-08-09 Thread Dustin Lundquist
On Mon, Aug 1, 2016 at 7:16 PM, Zong Kai LI  wrote:

> This patch introduces methods to compose a Router Advertisement (RA)
> packet,
> introduces flags for RA, renames ovs_nd_opt to ovs_nd_lla_opt to specify
> it's
> Source/Target Link-layer Address option.
>
> Signed-off-by: Zong Kai LI 
> ---
>  lib/flow.c|  26 -
>  lib/odp-execute.c |  20 +++
>  lib/packets.c | 168 ++
> +++-
>  lib/packets.h |  86 
>  4 files changed, 239 insertions(+), 61 deletions(-)
>

Reviewed packet structures against specification in RFC4861.

Acked-by: Dustin Lundquist 
___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH] ovs : Implementation to add meter in ovs flows

2016-07-18 Thread Dustin Lundquist
On 7/15/16 12:32 AM, deepanshu.saxen...@gmail.com wrote:
> From: Deepanshu Saxena 
> 
> This commit implements ovs meters in kernel space using the traffic
> control (tc) module of Linux kernel. TC  is  used  to configure Traffic
> Control features like Policing, Shaping etc. Ovs meters are analogous to
> traffic control policing feature. The details from the meter command are
> fetched and mapped to the corresponding fields of tc qdisc,class,filter
> commands.
Great idea. Doesn't TC the TC system only perform actions when a frame
is egresses from an interface. Without additional TC hooks within the
kernel datapath, this metering will not affect traffic send of vswitchd
via upcalls. I would like to see a more universal metering solution
which works with all traffic passing through OVS.

> diff --git a/ofproto/meter_tc.c b/ofproto/meter_tc.c
> new file mode 100644
> index 000..fc7fa0b
> --- /dev/null
> +++ b/ofproto/meter_tc.c
> @@ -0,0 +1,74 @@
> +#include 
> +#include "meter_tc.h"
> +
> +VLOG_DEFINE_THIS_MODULE(meter_tc);
> +
> +enum ofperr flow_mod_to_tc(struct ofproto *ofproto,
> +   struct ofputil_flow_mod ofm) {
> +FILE *fp;
> +ovs_be32 nw_src,nw_dst;
> +struct ofpact *a;
> +struct ofpact_meter *m_act;
> +struct ofport *ofport;
> +struct meter *meter;
> +uint32_t id,rate,rate_in_bytesps,burst_size,default_id;
> +char buffer[1024];
> +ofp_port_t port=0;
> +default_id=65535;
> +id=0;
> +struct ds nw_src_string = DS_EMPTY_INITIALIZER;
> +struct ds nw_dst_string = DS_EMPTY_INITIALIZER;
> +nw_src = ofm.match.flow.nw_src;
> +nw_dst = ofm.match.flow.nw_dst;
> +ds_put_format(&nw_src_string, IP_FMT, IP_ARGS(nw_src));
> +ds_put_format(&nw_dst_string, IP_FMT, IP_ARGS(nw_dst));
> +VLOG_INFO("Source IP : %s , Destination IP : %s",nw_src_string.string,
> +  nw_dst_string.string);
> +OFPACT_FOR_EACH_FLATTENED (a, ofm.ofpacts, ofm.ofpacts_len) {
> +if (a->type == OFPACT_METER) {
> +m_act=ofpact_get_METER(a);
> +id=m_act->meter_id;
> +}
> +if(a->type == OFPACT_OUTPUT) {
> +port=ofpact_get_OUTPUT(a)->port; 
> +}
> +}
> +VLOG_INFO("Output Port Number : %d",port);
> +ofport=ofproto_get_port(ofproto,port);
> +if(ofport==NULL) {
> +VLOG_INFO("The port numbers defined in the flow donot correspond to "
> +  "any datapath port. try using ovs-ofctl show  to "
> +  "get the list of ports. Add ports to the bridge first");
> +return OFPERR_OFPBRC_BAD_PORT;
> +}
> +VLOG_INFO("Output Port Name : %s",ofport->pp.name);
> +VLOG_INFO("Meter id : %d",id);
> +meter = ofproto->meters[id];
> +rate=meter->bands->rate;
> +rate_in_bytesps=(uint32_t)((float)(meter->bands->rate/8)*1000);
> +burst_size=meter->bands->burst_size;
> +VLOG_INFO("Rate in kbitsps : %d, burst size in kbits  %d",rate,
> +  burst_size);
> +snprintf(buffer,sizeof(buffer),"tc qdisc add dev %s root " 
> + "handle 1: htb default %x",ofport->pp.name,default_id);
> +fp=popen(buffer,"r");
> +snprintf(buffer,sizeof(buffer),"tc class add dev %s parent 1:0 " 
> + "classid 1:%x htb rate 20kbps ceil 100kbps prio 2",
> + ofport->pp.name,default_id);
> +fp = popen(buffer,"r");
> +pclose(fp);
We should check the exit code to ensure the tc command completed
successfully.
> +snprintf(buffer,sizeof(buffer),"tc class add dev %s parent 1:0 classid " 
> + "1:%x htb rate %dkbit ceil %dkbit prio 1 mtu %d000 ",
> + ofport->pp.name,id,rate,rate,burst_size);
> +fp = popen(buffer,"r");
> +pclose(fp);
Ditto.
> +snprintf(buffer,sizeof(buffer),"tc filter add dev %s protocol ip parent 
> " 
> + "1: prio 1 u32 match ip src %s match ip dst %s flowid 1:%x " 
> + "police rate %dbps burst %d000 mpu 0 conform-exceed drop/ok",
> + ofport->pp.name,nw_src_string.string,nw_dst_string.string,
> + id,rate_in_bytesps,burst_size);
> +fp = popen(buffer,"r");
> +VLOG_INFO("Meter attached successfully to the flow");
> +pclose(fp);
> +return 0;
> +}

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] [ovs-dev, v2][PATCH] ovn-northd: Restrict use of unspecified source addresses

2016-05-20 Thread Dustin Lundquist
Restrict use of the unspecified source addresses (:: and 0.0.0.0) to
traffic necessary to obtain an IP address. DHCP discovery messages for
the IPv4 case, and ICMP6 types necessary for duplicate address detection
for IPv6.

This breaks the existing ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV
test since it tests sourcing IPv6 packets from the unspecified address
with and invalid ICMPv6 type (0). Modified this test should be extended
to verify ICMPv6 types for DAD are permitted, and other IPv6 traffic
sourced from the unspecified address are dropped.

Signed-off-by: Dustin Lundquist 
---
 ovn/northd/ovn-northd.8.xml | 16 
 ovn/northd/ovn-northd.c | 38 ++
 tests/ovn.at| 24 +++-
 3 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml
index 970c352..2665ed5 100644
--- a/ovn/northd/ovn-northd.8.xml
+++ b/ovn/northd/ovn-northd.8.xml
@@ -160,12 +160,28 @@
   

   
+Priority 90 flow to allow IPv4 DHCP discovery traffic if it has a
+valid eth.src. This is necessary since DHCP discovery
+messages are sent from the unspecified IPv4 address (0.0.0.0) since
+the IPv4 address has not yet been assigned.
+  
+
+  
 Priority 90 flow to allow IPv6 traffic if it has IPv6 addresses
 which match the inport, valid eth.src and
 valid ip6.src address(es).
   

   
+Priority 90 flow to allow IPv6 DAD (Duplicate Address Detection)
+traffic if it has a valid eth.src. This is is
+necessary since DAD include requires joining an multicast group and
+sending neighbor solicitations for the newly assigned address. 
Since
+no address is yet assigned, these are sent from the unspecified
+IPv6 address (::).
+  
+
+  
 Priority 80 flow to drop IP (both IPv4 and IPv6) traffic which
 match the inport and valid eth.src.
   
diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 44e9430..ad1f381 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1033,12 +1033,17 @@ build_port_security_ipv6_flow(
 ipv6_string_mapped(ip6_str, &lla);
 ds_put_format(match, "%s, ", ip6_str);

-/* Allow ip6.src=:: and ip6.dst=ff00::/8 for ND packets */
-ds_put_cstr(match, pipeline == P_IN ? "::" : "ff00::/8");
+/* Allow ip6.dst=ff00::/8 for multicast packets */
+if (pipeline == P_OUT) {
+ds_put_cstr(match, "ff00::/8, ");
+}
 for(int i = 0; i < n_ipv6_addrs; i++) {
 ipv6_string_mapped(ip6_str, &ipv6_addrs[i].addr);
-ds_put_format(match, ", %s", ip6_str);
+ds_put_format(match, "%s, ", ip6_str);
 }
+/* Replace ", " by "}". */
+ds_chomp(match, ' ');
+ds_chomp(match, ',');
 ds_put_cstr(match, "}");
 }

@@ -1174,8 +1179,19 @@ build_port_security_ip(enum ovn_pipeline pipeline, 
struct ovn_port *op,
 if (ps.n_ipv4_addrs) {
 struct ds match = DS_EMPTY_INITIALIZER;
 if (pipeline == P_IN) {
+/* Permit use of the unspecified address for DHCP discovery */
+struct ds dhcp_match = DS_EMPTY_INITIALIZER;
+ds_put_format(&dhcp_match, "inport == %s"
+  " && eth.src == "ETH_ADDR_FMT
+  " && ip4.src == 0.0.0.0"
+  " && ip4.dst == 255.255.255.255"
+  " && udp.src == 68 && udp.dst == 67", 
op->json_key,
+  ETH_ADDR_ARGS(ps.ea));
+ovn_lflow_add(lflows, op->od, stage, 90,
+  ds_cstr(&dhcp_match), "next;");
+ds_destroy(&dhcp_match);
 ds_put_format(&match, "inport == %s && eth.src == "ETH_ADDR_FMT
-  " && ip4.src == {0.0.0.0, ", op->json_key,
+  " && ip4.src == {", op->json_key,
   ETH_ADDR_ARGS(ps.ea));
 } else {
 ds_put_format(&match, "outport == %s && eth.dst == 
"ETH_ADDR_FMT
@@ -1219,6 +1235,20 @@ build_port_security_ip(enum ovn_pipeline pipeline, 
struct ovn_port *op,

 if (ps.n_ipv6_addrs) {
 struct ds match = DS_EMPTY_INITIALIZER;
+if (pipeline == P_IN) {
+/* Permit use of unspecified address for duplicate address
+ * detection */
+struct ds dad_match = DS_EMP

[ovs-dev] [PATCH] Restrict use of unspecified source addresses

2016-05-18 Thread Dustin Lundquist
Restrict use of the unspecified source addresses (:: and 0.0.0.0) to
traffic necessary to obtain an IP address. DHCP discovery messages for
the IPv4 case, and ICMP6 types necessary for duplicate address detection
for IPv6.

This breaks the existing ovn -- portsecurity : 3 HVs, 1 LS, 3 lports/HV
test since it tests sourcing IPv6 packets from the unspecified address
with and invalid ICMPv6 type (0). Modified this test should be extended
to verify ICMPv6 types for DAD are permitted, and other IPv6 traffic
sourced from the unspecified address are dropped.
---
 ovn/northd/ovn-northd.c | 37 +
 tests/ovn.at| 22 +-
 2 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c
index 44e9430..f59faa2 100644
--- a/ovn/northd/ovn-northd.c
+++ b/ovn/northd/ovn-northd.c
@@ -1033,12 +1033,16 @@ build_port_security_ipv6_flow(
 ipv6_string_mapped(ip6_str, &lla);
 ds_put_format(match, "%s, ", ip6_str);
 
-/* Allow ip6.src=:: and ip6.dst=ff00::/8 for ND packets */
-ds_put_cstr(match, pipeline == P_IN ? "::" : "ff00::/8");
+/* Allow ip6.dst=ff00::/8 for multicast packets */
+if (pipeline == P_OUT)
+ds_put_cstr(match, "ff00::/8, ");
 for(int i = 0; i < n_ipv6_addrs; i++) {
 ipv6_string_mapped(ip6_str, &ipv6_addrs[i].addr);
-ds_put_format(match, ", %s", ip6_str);
+ds_put_format(match, "%s, ", ip6_str);
 }
+/* Replace ", " by "}". */
+ds_chomp(match, ' ');
+ds_chomp(match, ',');
 ds_put_cstr(match, "}");
 }
 
@@ -1174,8 +1178,19 @@ build_port_security_ip(enum ovn_pipeline pipeline, 
struct ovn_port *op,
 if (ps.n_ipv4_addrs) {
 struct ds match = DS_EMPTY_INITIALIZER;
 if (pipeline == P_IN) {
+/* Permit use of the unspecified address for DHCP discovery */
+struct ds dhcp_match = DS_EMPTY_INITIALIZER;
+ds_put_format(&dhcp_match, "inport == %s"
+  " && eth.src == "ETH_ADDR_FMT
+  " && ip4.src == 0.0.0.0"
+  " && ip4.dst == 255.255.255.255"
+  " && udp.src == 68 && udp.dst == 67", 
op->json_key,
+  ETH_ADDR_ARGS(ps.ea));
+ovn_lflow_add(lflows, op->od, stage, 90,
+  ds_cstr(&dhcp_match), "next;");
+ds_destroy(&dhcp_match);
 ds_put_format(&match, "inport == %s && eth.src == "ETH_ADDR_FMT
-  " && ip4.src == {0.0.0.0, ", op->json_key,
+  " && ip4.src == {", op->json_key,
   ETH_ADDR_ARGS(ps.ea));
 } else {
 ds_put_format(&match, "outport == %s && eth.dst == 
"ETH_ADDR_FMT
@@ -1219,6 +1234,20 @@ build_port_security_ip(enum ovn_pipeline pipeline, 
struct ovn_port *op,
 
 if (ps.n_ipv6_addrs) {
 struct ds match = DS_EMPTY_INITIALIZER;
+if (pipeline == P_IN) {
+/* Permit use of unspecified address for duplicate address
+ * detection */
+struct ds dad_match = DS_EMPTY_INITIALIZER;
+ds_put_format(&dad_match, "inport == %s"
+  " && eth.src == "ETH_ADDR_FMT
+  " && ip6.src == ::"
+  " && ip6.dst == ff02::/16"
+  " && icmp6.type == {131, 135, 143}", 
op->json_key,
+  ETH_ADDR_ARGS(ps.ea));
+ovn_lflow_add(lflows, op->od, stage, 90,
+  ds_cstr(&dad_match), "next;");
+ds_destroy(&dad_match);
+}
 ds_put_format(&match, "%s == %s && %s == "ETH_ADDR_FMT"",
   port_direction, op->json_key,
   pipeline == P_IN ? "eth.src" : "eth.dst",
diff --git a/tests/ovn.at b/tests/ovn.at
index cc5c468..011472c 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -1786,6 +1786,19 @@ test_ipv6() {
 done
 }
 
+# ipv6 icmp packet
+test_icmpv6() {
+local inport=$1 src_mac=$2 dst_mac=$3 src_ip=$4 dst_ip=$5 icmp_type=$6
+local 
packet=${dst_mac}${src_mac}86dd60083aff${src_ip}${dst_ip}${icmp_type}00
+shift; shift; shift; shift; shift; shift
+hv=`vif_to_hv $inport`
+as $hv ovs-appctl netdev-dummy/receive vif$inport $packet
+#as $hv ovs-appctl ofproto/trace br-int in_port=$inport $packet
+for outport; do
+echo $packet | trim_zeros >> $outport.expected
+done
+}
+
 ip_to_hex() {
 printf "%02x%02x%02x%02x" "$@"
 }
@@ -1923,8 +1936,15 @@ for i in 1 2 3; do
 sip=fe80ea2aeafffe2800${i}3
 test_ipv6 ${i}3 f${i}${i}3 f021 $sip $tip 21
 
+# Test ICMPv6 MLD reports (v1 and v2) and NS for DAD
 sip=

Re: [ovs-dev] [PATCH V1 1/1] Support for Flooding ARP Probes in Provider Network

2016-04-08 Thread Dustin Lundquist
On 4/8/16 10:00 AM, Gangadhar R Vegesana wrote:
> HI Dustin,
>  
> *Case 1)* External Gateway or External Host have IP and now VM is
> assigned the same IP,
> VM should decline or not use that IP (ie. Send DCHP Decline in case of
> DHCP). The ARP probe that is sent by VM should reach the External
> Gateway/Host to get response back. I added that new entry to flood that
> ARP Probe. Without this entry, the OVN ARP res-ponder, responds back to
> the VM and there is no way VM knowing that there exists some conflict.
> Once the conflict is known, either CMS or DHCP Server have to fix this,
> by assigning a new IP to the VM.
>  
> *Case 2)* VM have IP and External Gateway or External Host is assigned
> the same IP :
> This issue should be resolved by Gateway or External Host Admin, as
> he/she is the one who is configuring the conflicting IP in the second place.
>  
> I agree with you, that this is job of CMS to not allocate this IP
> address, but this ARP probe is one such way to know that there exists
> some conflict. From my understanding, i assume that OVN ARP responder
> table won't have External Gateway ARP entry in its table. If we start
> learning provider network (localnet) ARP entries, they can be huge
> number (i assume) and OVN won't have control on these external entries.
> Please let me know your thoughts. 

Let me try to break this into two separate topics: cost/benefit analysis
of permitting ARP probes and learning provider network addresses for ARP
responder.

Regarding permitting ARP probes, my initial thought is that there is a
higher than normal cost to broadcast/multicast traffic in OVN since
traffic must be replicated and sent via unicast through each tunnel. I
know there is work in progress to change this, but as I understand it
this is the reasoning behind filtering ARP probes. But this is not the
case in provider networks, since there is not a increased normal cost in
handling broadcast and multicast traffic; this traffic is simply
forwarded to the provider network interface and traffic is this
replicated on the upstream network device. So performance impact of
permitting ARP probes is not significant.

Unfortunately the benefit of permitting ARP probes is rather low. Since
ports in OVN are programmed with their L2 and L3 addresses and flows are
created before an VM is connected to this port _the damage is already
done_ (atleast to all the hosts connected via OVN) before the VM could
perform an ARP probe to find out if its IP is in use. For this work as
desired OVN would need to perform the ARP probe before creating the
flows for the new IP address ARP responder. This would add a significant
delay in flow creation.

A learning ARP responder provides another option for managing duplicate
IP addresses. While the number of address may be large, in conventional
deployments it is only a small number of addresses with less churn than
other OVN ports. With a mechanism to receive ARP responses from provider
network devices and add them to the northbound database, OVN could
return an error when a CMS attempts to provision a port with a duplicate
address. This would not work well, if for example a user deployed a
provider network connected to a campus wireless network or similar large
L2 network with a high degree of address churn, but I don't think this
is a use case we should design for.


-Dustin


___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


Re: [ovs-dev] [PATCH V1 1/1] Support for Flooding ARP Probes in Provider Network

2016-04-07 Thread Dustin Lundquist
On 4/7/16 11:43 AM, Gangadhar Vegesana wrote:
> Clients that supports RFC 5227, probes the the newly received IP address
> from DHCP server. These probes should be received by all the VM's on
> the provider network(localnet). I added any entry in ARP response table
> to do that broadcast with higher priority value than that of ARP response
> entries. The ARP probe packets with src=0.0.0.0 should not be dropped.
> As of now there is check in ARP spoofing table to drop these packets.
> Added another check to allow these packets

I don't see the value in enabling RFC 5227 on an OVN provider networks.
The most common use of a provider network is to connect with an external
gateway, and this this case the gateway would not want to yield that IP.
The CMS using OVN should not allocate addresses in conflict a provider
network gateway. While without these ARP probes the provider network
gateway would not learn of the potential address conflicts, allowing an
address conflict. The ARP responder within OVN would override the
provider network gateway ARP entry with the one for the new conflicting
port configured by the CMS. In either case it is an error, and enabling
ARP probes does not solve the problem of a CMS which erroneously
configures a port with a conflicting IP to a provider network gateway.
Perhaps it would be better if OVN could learn provider network gateway
ARP entries and include them in its ARP responder?


-Dustin Lundquist

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev


[ovs-dev] upcall fairness

2016-03-03 Thread Dustin Lundquist
I have some concerns about the fairness of upcalls and flow cache
evictions in the kernel dataplane. My motivation for investigating this
is based on my experience operating a hardware vendor's solution which
use a similar method: caching routing decisions as flows after the first
packet was punted to software. Operating a network using such hardware,
we found a single host could generate traffic which would force cache
evictions adversely effecting other hosts' traffic.

As OVS uses a similar approach, I wanted to test how well it handles a
malicious or compromised host connected to one of its ports. To test
this I used Devstack with networking-ovn and created three neutron probe
namespaces on a single network. Within one of the namespaces I used the
Linux pktgen[1] kernel module to generate a large number of MAC
flows[2]. I found ovs-vswitchd exhibited high CPU utilization, evidence
of datapath flow evictions in latencies of a single ping test:

> ubuntu@devstack-ovn:~$ sudo ip netns exec 
> qprobe-1739b61e-4085-43b5-bd4e-05051a11d996 ping -c 10 10.0.0.2
> PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
>
> 64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=11.1 ms
>
> 64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.091 ms   
>
> 64 bytes from 10.0.0.2: icmp_seq=3 ttl=64 time=2.28 ms
>
> 64 bytes from 10.0.0.2: icmp_seq=4 ttl=64 time=2.69 ms
>
> 64 bytes from 10.0.0.2: icmp_seq=5 ttl=64 time=0.086 ms   
>
> 64 bytes from 10.0.0.2: icmp_seq=6 ttl=64 time=0.081 ms   
>
> 64 bytes from 10.0.0.2: icmp_seq=7 ttl=64 time=0.086 ms   
>
> 64 bytes from 10.0.0.2: icmp_seq=8 ttl=64 time=0.085 ms   
>
> 64 bytes from 10.0.0.2: icmp_seq=9 ttl=64 time=0.085 ms   
>
> 64 bytes from 10.0.0.2: icmp_seq=10 ttl=64 time=0.084 ms  
>
>   
>
> --- 10.0.0.2 ping statistics ---  
>
> 10 packets transmitted, 10 received, 0% packet loss, time 9004ms  
>
> rtt min/avg/max/mdev = 0.081/1.671/11.134/3.295 ms
>

Are their any existing or planned methods to ensure traffic from tenant
ports is handled fairly, preventing traffic received on a single port
from evicting flows from all other ports? Obviously uplink ports would
need to be permitted a larger portion of flows.


-Dustin


[1] https://www.kernel.org/doc/Documentation/networking/pktgen.txt
[2]
https://github.com/dlundquist/openstack-scripts/blob/master/scripts/dp_test.sh

___
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev