Thanks, and sorry for contributing to the problem.
On Thu, Jan 15, 2015 at 12:20:00PM -0800, Gurucharan Shetty wrote: > I sent a patch which I think is one/easy way to fix this. > http://openvswitch.org/pipermail/dev/2015-January/050492.html > > On Thu, Jan 15, 2015 at 9:28 AM, Gurucharan Shetty <shet...@nicira.com> wrote: > > On Tue, Dec 23, 2014 at 3:42 PM, Sharo, Randall A CIV > > SPAWARSYSCEN-ATLANTIC, 55200 <randall.sh...@navy.mil> wrote: > >> This patch adds set-field operations for nd_target, nd_sll, and nd_tll > >> fields, with and without masks, using Nicira extensions and OpenFlow 1.2 > >> protocol. > >> > >> This version defines protocol structures in packets.h to support messages > >> aligned on 16-bit boundaries. It eliminates the clang alignment warning, > >> removes extraneous typecasting and adds a unit test that verifies checksum > >> recalculation and ND header modification. > >> > >> > >> Signed-off-by: Randall A Sharo <randall.sharo at navy.mil> > >> > >> > >> > >> --- > >> > >> diff --git a/lib/csum.c b/lib/csum.c > >> index a9334fe..155ae85 100644 > >> --- a/lib/csum.c > >> +++ b/lib/csum.c > >> @@ -113,6 +113,26 @@ recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, > >> ovs_be32 new_u32) > >> } > >> > >> /* Returns the new checksum for a packet in which the checksum field > >> previously > >> + * contained 'old_csum' and in which a field that contained the 6 bytes at > >> + * 'old_bytes' was changed to contain the 6 bytes at 'new_bytes'. */ > >> +ovs_be16 > >> +recalc_csum48(ovs_be16 old_csum, const void *old_bytes, > >> + const void *new_bytes) > >> +{ > >> + ovs_be16 new_csum = old_csum; > >> + const uint16_t *p16_old = old_bytes, > >> + *p16_new = new_bytes; > >> + int i; > >> + > >> + for (i = 0; i < 3; ++i) { > >> + new_csum = recalc_csum16(new_csum, > >> get_unaligned_be16(&p16_old[i]), > >> + get_unaligned_be16(&p16_new[i])); > >> + } > >> + > >> + return new_csum; > >> +} > >> + > >> +/* Returns the new checksum for a packet in which the checksum field > >> previously > >> * contained 'old_csum' and in which a field that contained 'old_u32[4]' > >> was > >> * changed to contain 'new_u32[4]'. */ > >> ovs_be16 > >> diff --git a/lib/csum.h b/lib/csum.h > >> index df4b19d..ceff001 100644 > >> --- a/lib/csum.h > >> +++ b/lib/csum.h > >> @@ -28,6 +28,8 @@ uint32_t csum_continue(uint32_t partial, const void *, > >> size_t); > >> ovs_be16 csum_finish(uint32_t partial); > >> ovs_be16 recalc_csum16(ovs_be16 old_csum, ovs_be16 old_u16, ovs_be16 > >> new_u16); > >> ovs_be16 recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 > >> new_u32); > >> +ovs_be16 recalc_csum48(ovs_be16 old_csum, const void *old_bytes, > >> + const void *new_bytes); > >> ovs_be16 recalc_csum128(ovs_be16 old_csum, ovs_16aligned_be32 old_u32[4], > >> const ovs_be32 new_u32[4]); > >> > >> diff --git a/lib/meta-flow.h b/lib/meta-flow.h > >> index 62e9c79..c0fd75e 100644 > >> --- a/lib/meta-flow.h > >> +++ b/lib/meta-flow.h > >> @@ -1329,7 +1329,7 @@ enum OVS_PACKED_ENUM mf_field_id { > >> * Maskable: bitwise. > >> * Formatting: IPv6. > >> * Prerequisites: ND. > >> - * Access: read-only. > >> + * Access: read/write. > >> * NXM: NXM_NX_ND_TARGET(23) since v1.1. > >> * OXM: OXM_OF_IPV6_ND_TARGET(31) since OF1.2 and v1.7. > >> */ > >> @@ -1343,7 +1343,7 @@ enum OVS_PACKED_ENUM mf_field_id { > >> * Maskable: bitwise. > >> * Formatting: Ethernet. > >> * Prerequisites: ND solicit. > >> - * Access: read-only. > >> + * Access: read/write. > >> * NXM: NXM_NX_ND_SLL(24) since v1.1. > >> * OXM: OXM_OF_IPV6_ND_SLL(32) since OF1.2 and v1.7. > >> */ > >> @@ -1357,7 +1357,7 @@ enum OVS_PACKED_ENUM mf_field_id { > >> * Maskable: bitwise. > >> * Formatting: Ethernet. > >> * Prerequisites: ND advert. > >> - * Access: read-only. > >> + * Access: read/write. > >> * NXM: NXM_NX_ND_TLL(25) since v1.1. > >> * OXM: OXM_OF_IPV6_ND_TLL(33) since OF1.2 and v1.7. > >> */ > >> diff --git a/lib/odp-execute.c b/lib/odp-execute.c > >> index 720d24e..0edd3a8 100644 > >> --- a/lib/odp-execute.c > >> +++ b/lib/odp-execute.c > >> @@ -19,6 +19,7 @@ > >> #include "odp-execute.h" > >> #include <arpa/inet.h> > >> #include <netinet/ip6.h> > >> +#include <netinet/icmp6.h> > >> #include <stdlib.h> > >> #include <string.h> > >> > >> @@ -181,6 +182,48 @@ set_arp(struct ofpbuf *packet, const struct > >> ovs_key_arp *key, > >> } > >> > >> static void > >> +odp_set_nd(struct ofpbuf *packet, const struct ovs_key_nd *key, > >> + const struct ovs_key_nd *mask) > >> +{ > >> + const struct ovs_nd_msg *ns = ofpbuf_l4(packet); > >> + const struct ovs_nd_opt *nd_opt = ofpbuf_get_nd_payload(packet); > >> + > >> + if (OVS_LIKELY(ns && nd_opt)) { > >> + int bytes_remain = ofpbuf_l4_size(packet) - sizeof(*ns); > >> + ovs_be32 tgt_buf[4]; > >> + uint8_t sll_buf[ETH_ADDR_LEN] = {0}; > >> + uint8_t tll_buf[ETH_ADDR_LEN] = {0}; > >> + > >> + while (bytes_remain >= ND_OPT_LEN && nd_opt->nd_opt_len != 0) { > >> + if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LINKADDR > >> + && nd_opt->nd_opt_len == 1) { > >> + memcpy(sll_buf, nd_opt->nd_opt_data, ETH_ADDR_LEN); > >> + ether_addr_copy_masked(sll_buf, key->nd_sll, > >> mask->nd_sll); > >> + > >> + /* A packet can only contain one SLL or TLL option */ > >> + break; > >> + } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LINKADDR > >> + && nd_opt->nd_opt_len == 1) { > >> + memcpy(tll_buf, nd_opt->nd_opt_data, ETH_ADDR_LEN); > >> + ether_addr_copy_masked(tll_buf, key->nd_tll, > >> mask->nd_tll); > >> + > >> + /* A packet can only contain one SLL or TLL option */ > >> + break; > >> + } > >> + > >> + nd_opt += nd_opt->nd_opt_len; > >> + bytes_remain -= nd_opt->nd_opt_len * ND_OPT_LEN; > >> + } > >> + > >> + packet_set_nd(packet, > >> + mask_ipv6_addr(ns->target.be32, > >> + key->nd_target, mask->nd_target, > >> tgt_buf), > >> + sll_buf, > >> + tll_buf); > >> + } > >> +} > >> + > >> +static void > >> odp_execute_set_action(struct dpif_packet *packet, const struct nlattr *a) > >> { > >> enum ovs_key_attr type = nl_attr_type(a); > >> @@ -258,6 +301,15 @@ odp_execute_set_action(struct dpif_packet *packet, > >> const struct nlattr *a) > >> set_arp(&packet->ofpbuf, nl_attr_get(a), NULL); > >> break; > >> > >> + case OVS_KEY_ATTR_ND: > >> + if (OVS_LIKELY(ofpbuf_get_nd_payload(&packet->ofpbuf))) { > >> + const struct ovs_key_nd *nd_key > >> + = nl_attr_get_unspec(a, sizeof(struct ovs_key_nd)); > >> + packet_set_nd(&packet->ofpbuf, nd_key->nd_target, > >> + nd_key->nd_sll, nd_key->nd_tll); > >> + } > >> + break; > >> + > >> case OVS_KEY_ATTR_DP_HASH: > >> md->dp_hash = nl_attr_get_u32(a); > >> dpif_packet_set_dp_hash(packet, md->dp_hash); > >> @@ -274,7 +326,6 @@ odp_execute_set_action(struct dpif_packet *packet, > >> const struct nlattr *a) > >> case OVS_KEY_ATTR_VLAN: > >> case OVS_KEY_ATTR_ICMP: > >> case OVS_KEY_ATTR_ICMPV6: > >> - case OVS_KEY_ATTR_ND: > >> case OVS_KEY_ATTR_TCP_FLAGS: > >> case __OVS_KEY_ATTR_MAX: > >> default: > >> @@ -347,6 +398,11 @@ odp_execute_masked_set_action(struct dpif_packet > >> *packet, > >> get_mask(a, struct ovs_key_arp)); > >> break; > >> > >> + case OVS_KEY_ATTR_ND: > >> + odp_set_nd(&packet->ofpbuf, nl_attr_get(a), > >> + get_mask(a, struct ovs_key_nd)); > >> + break; > >> + > >> case OVS_KEY_ATTR_DP_HASH: > >> md->dp_hash = nl_attr_get_u32(a) > >> | (dpif_packet_get_dp_hash(packet) & ~*get_mask(a, uint32_t)); > >> @@ -366,7 +422,6 @@ odp_execute_masked_set_action(struct dpif_packet > >> *packet, > >> case OVS_KEY_ATTR_VLAN: > >> case OVS_KEY_ATTR_ICMP: > >> case OVS_KEY_ATTR_ICMPV6: > >> - case OVS_KEY_ATTR_ND: > >> case OVS_KEY_ATTR_TCP_FLAGS: > >> case __OVS_KEY_ATTR_MAX: > >> default: > >> diff --git a/lib/odp-util.c b/lib/odp-util.c > >> index b8fda49..a8fbafe 100644 > >> --- a/lib/odp-util.c > >> +++ b/lib/odp-util.c > >> @@ -2813,6 +2813,8 @@ static void put_ipv6_key(const struct ovs_key_ipv6 > >> *, struct flow *, > >> bool is_mask); > >> static void get_arp_key(const struct flow *, struct ovs_key_arp *); > >> static void put_arp_key(const struct ovs_key_arp *, struct flow *); > >> +static void get_nd_key(const struct flow *, struct ovs_key_nd *); > >> +static void put_nd_key(const struct ovs_key_nd *, struct flow *); > >> > >> /* These share the same layout. */ > >> union ovs_key_tp { > >> @@ -4156,6 +4158,45 @@ commit_set_arp_action(const struct flow *flow, > >> struct flow *base_flow, > >> return 0; > >> } > >> > >> +static void > >> +get_nd_key(const struct flow *flow, struct ovs_key_nd *nd) > >> +{ > >> + memcpy(nd->nd_target, &flow->nd_target, sizeof flow->nd_target); > >> + /* nd_sll and nd_tll are stored in arp_sha and arp_tha, respectively > >> */ > >> + memcpy(nd->nd_sll, flow->arp_sha, ETH_ADDR_LEN); > >> + memcpy(nd->nd_tll, flow->arp_tha, ETH_ADDR_LEN); > >> +} > >> + > >> +static void > >> +put_nd_key(const struct ovs_key_nd *nd, struct flow *flow) > >> +{ > >> + memcpy(&flow->nd_target, &flow->nd_target, sizeof flow->nd_target); > >> + /* nd_sll and nd_tll are stored in arp_sha and arp_tha, respectively > >> */ > >> + memcpy(flow->arp_sha, nd->nd_sll, ETH_ADDR_LEN); > >> + memcpy(flow->arp_tha, nd->nd_tll, ETH_ADDR_LEN); > >> +} > >> + > >> +static enum slow_path_reason > >> +commit_set_nd_action(const struct flow *flow, struct flow *base_flow, > >> + struct ofpbuf *odp_actions, > >> + struct flow_wildcards *wc, bool use_masked) > >> +{ > >> + struct ovs_key_nd key, mask, base; > >> + > >> + get_nd_key(flow, &key); > >> + get_nd_key(base_flow, &base); > >> + get_nd_key(&wc->masks, &mask); > >> + > >> + if (commit(OVS_KEY_ATTR_ND, use_masked, &key, &base, &mask, sizeof > >> key, > >> + odp_actions)) { > >> + put_nd_key(&base, base_flow); > >> + put_nd_key(&mask, &wc->masks); > >> + return SLOW_ACTION; > >> + } > >> + > >> + return 0; > >> +} > >> + > >> static enum slow_path_reason > >> commit_set_nw_action(const struct flow *flow, struct flow *base, > >> struct ofpbuf *odp_actions, struct flow_wildcards > >> *wc, > >> @@ -4173,7 +4214,7 @@ commit_set_nw_action(const struct flow *flow, struct > >> flow *base, > >> > >> case ETH_TYPE_IPV6: > >> commit_set_ipv6_action(flow, base, odp_actions, wc, use_masked); > >> - break; > >> + return commit_set_nd_action(flow, base, odp_actions, wc, > >> use_masked); > >> > >> case ETH_TYPE_ARP: > >> return commit_set_arp_action(flow, base, odp_actions, wc); > >> diff --git a/lib/ofp-print.c b/lib/ofp-print.c > >> index d15a385..f4c5bc6 100644 > >> --- a/lib/ofp-print.c > >> +++ b/lib/ofp-print.c > >> @@ -82,6 +82,14 @@ ofp_packet_to_string(const void *data, size_t len) > >> struct sctp_header *sh = ofpbuf_l4(&buf); > >> ds_put_format(&ds, " sctp_csum:%"PRIx32, > >> ntohl(get_16aligned_be32(&sh->sctp_csum))); > >> + } else if (flow.nw_proto == IPPROTO_ICMP && l4_size >= > >> ICMP_HEADER_LEN) { > >> + struct icmp_header *icmph = ofpbuf_l4(&buf); > >> + ds_put_format(&ds, " icmp_csum:%"PRIx16, > >> + ntohs(icmph->icmp_csum)); > >> + } else if (flow.nw_proto == IPPROTO_ICMPV6 && l4_size >= > >> ICMP6_HEADER_LEN) { > >> + struct icmp6_header *icmp6h = ofpbuf_l4(&buf); > >> + ds_put_format(&ds, " icmp6_csum:%"PRIx16, > >> + ntohs(icmp6h->icmp6_cksum)); > >> } > >> > >> ds_put_char(&ds, '\n'); > >> diff --git a/lib/ofpbuf.h b/lib/ofpbuf.h > >> index 4c0f7ea..4e7038d 100644 > >> --- a/lib/ofpbuf.h > >> +++ b/lib/ofpbuf.h > >> @@ -104,6 +104,7 @@ static inline const void *ofpbuf_get_tcp_payload(const > >> struct ofpbuf *); > >> static inline const void *ofpbuf_get_udp_payload(const struct ofpbuf *); > >> static inline const void *ofpbuf_get_sctp_payload(const struct ofpbuf *); > >> static inline const void *ofpbuf_get_icmp_payload(const struct ofpbuf *); > >> +static inline const void *ofpbuf_get_nd_payload(const struct ofpbuf *); > >> > >> void ofpbuf_use(struct ofpbuf *, void *, size_t); > >> void ofpbuf_use_stack(struct ofpbuf *, void *, size_t); > >> @@ -374,6 +375,12 @@ static inline const void > >> *ofpbuf_get_icmp_payload(const struct ofpbuf *b) > >> ? (const char *)ofpbuf_l4(b) + ICMP_HEADER_LEN : NULL; > >> } > >> > >> +static inline const void *ofpbuf_get_nd_payload(const struct ofpbuf *b) > >> +{ > >> + return OVS_LIKELY(ofpbuf_l4_size(b) >= ND_MSG_LEN) > >> + ? (const char *)ofpbuf_l4(b) + ND_MSG_LEN : NULL; > >> +} > >> + > >> #ifdef DPDK_NETDEV > >> BUILD_ASSERT_DECL(offsetof(struct ofpbuf, mbuf) == 0); > >> > >> diff --git a/lib/packets.c b/lib/packets.c > >> index af99e3b..4d8aca9 100644 > >> --- a/lib/packets.c > >> +++ b/lib/packets.c > >> @@ -875,6 +875,58 @@ packet_set_sctp_port(struct ofpbuf *packet, ovs_be16 > >> src, ovs_be16 dst) > >> put_16aligned_be32(&sh->sctp_csum, old_csum ^ old_correct_csum ^ > >> new_csum); > >> } > >> > >> +void > >> +packet_set_nd(struct ofpbuf *packet, const ovs_be32 target[4], > >> + const uint8_t sll[ETH_ADDR_LEN], > >> + const uint8_t tll[ETH_ADDR_LEN]) { > >> + struct ovs_nd_msg *ns; > >> + struct ovs_nd_opt *nd_opt; > >> + int bytes_remain = ofpbuf_l4_size(packet); > >> + > >> + if (OVS_UNLIKELY(bytes_remain < sizeof(*ns))) { > >> + return; > >> + } > >> + > >> + ns = ofpbuf_l4(packet); > >> + nd_opt = &ns->options[0]; > >> + bytes_remain -= sizeof(*ns); > >> + > >> + if (memcmp(&ns->target, target, sizeof(ovs_be32[4]))) { > >> + packet_set_ipv6_addr(packet, IPPROTO_ICMPV6, > >> + ns->target.be32, > >> + target, true); > >> + } > >> + > >> + while (bytes_remain >= ND_OPT_LEN && nd_opt->nd_opt_len != 0) { > >> + if (nd_opt->nd_opt_type == ND_OPT_SOURCE_LINKADDR > >> + && nd_opt->nd_opt_len == 1) { > >> + if (memcmp(nd_opt->nd_opt_data, sll, ETH_ADDR_LEN)) { > >> + ovs_be16 *csum = &(ns->icmph.icmp6_cksum); > >> + > >> + *csum = recalc_csum48(*csum, nd_opt->nd_opt_data, sll); > >> + memcpy(nd_opt->nd_opt_data, sll, ETH_ADDR_LEN); > >> + } > >> + > >> + /* A packet can only contain one SLL or TLL option */ > >> + break; > >> + } else if (nd_opt->nd_opt_type == ND_OPT_TARGET_LINKADDR > >> + && nd_opt->nd_opt_len == 1) { > >> + if (memcmp(nd_opt->nd_opt_data, tll, ETH_ADDR_LEN)) { > >> + ovs_be16 *csum = &(ns->icmph.icmp6_cksum); > >> + > >> + *csum = recalc_csum48(*csum, nd_opt->nd_opt_data, tll); > >> + memcpy(nd_opt->nd_opt_data, tll, ETH_ADDR_LEN); > >> + } > >> + > >> + /* A packet can only contain one SLL or TLL option */ > >> + break; > >> + } > >> + > >> + nd_opt += nd_opt->nd_opt_len; > >> + bytes_remain -= nd_opt->nd_opt_len * ND_OPT_LEN; > >> + } > >> +} > >> + > >> const char * > >> packet_tcp_flag_to_string(uint32_t flag) > >> { > >> diff --git a/lib/packets.h b/lib/packets.h > >> index 65d2274..1c74d73 100644 > >> --- a/lib/packets.h > >> +++ b/lib/packets.h > >> @@ -647,6 +647,27 @@ struct icmp6_header { > >> }; > >> BUILD_ASSERT_DECL(ICMP6_HEADER_LEN == sizeof(struct icmp6_header)); > >> > >> +/* Neighbor Discovery option field. > >> + * ND options are always a multiple of 8 bytes in size. */ > >> +#define ND_OPT_LEN 8 > >> +struct ovs_nd_opt { > >> + uint8_t nd_opt_type; /* Values defined in icmp6.h */ > >> + uint8_t nd_opt_len; /* in units of 8 octets (the size of this > >> struct) */ > >> + uint8_t nd_opt_data[6]; /* Ethernet address in the case of SLL or > >> TLL options */ > >> +}; > >> +BUILD_ASSERT_DECL(ND_OPT_LEN == sizeof(struct ovs_nd_opt)); > >> + > >> +/* Like struct nd_msg (from ndisc.h), but whereas that struct requires > >> 32-bit > >> + * alignment, this one only requires 16-bit alignment. */ > >> +#define ND_MSG_LEN 24 > >> +struct ovs_nd_msg { > >> + struct icmp6_header icmph; > > MSVC does not support including a structure with zero-sized array in > > another structure when it is not the last member. > > (See: http://msdn.microsoft.com/en-us/library/0scy7z2d.aspx) > > For e.g., icmp6_header has a zero sized array and it is now included > > as part of ovs_nd_msg structure causing a compilation error. > > Can we work the patch to fix it? > > > > > > > > > >> + ovs_16aligned_be32 rco_flags; > >> + union ovs_16aligned_in6_addr target; > >> + struct ovs_nd_opt options[0]; > >> +}; > >> +BUILD_ASSERT_DECL(ND_MSG_LEN == sizeof(struct ovs_nd_msg)); > >> + > >> /* The IPv6 flow label is in the lower 20 bits of the first 32-bit word. > >> */ > >> #define IPV6_LABEL_MASK 0x000fffff > >> > >> @@ -758,6 +779,8 @@ void packet_set_ipv6(struct ofpbuf *, uint8_t proto, > >> const ovs_be32 src[4], > >> void packet_set_tcp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst); > >> void packet_set_udp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst); > >> void packet_set_sctp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst); > >> +void packet_set_nd(struct ofpbuf *, const ovs_be32 target[4], > >> + const uint8_t sll[6], const uint8_t tll[6]); > >> > >> void packet_format_tcp_flags(struct ds *, uint16_t); > >> const char *packet_tcp_flag_to_string(uint32_t flag); > >> diff --git a/tests/ofp-print.at b/tests/ofp-print.at > >> index c58ab7d..f25ce4b 100644 > >> --- a/tests/ofp-print.at > >> +++ b/tests/ofp-print.at > >> @@ -934,6 +934,23 @@ OFPT_FLOW_MOD (OF1.2) (xid=0x52334507): ADD > >> priority=255,dp_hash=0x1234567/0xfff > >> ]) > >> AT_CLEANUP > >> > >> +AT_SETUP([OFPT_FLOW_MOD - OF1.2 - set-field nd_target, nd_sll]) > >> +AT_KEYWORDS([ofp-print]) > >> +AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\ > >> +03 0e 00 78 00 00 00 02 00 00 00 00 00 00 00 00 \ > >> +00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff \ > >> +ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00 \ > >> +00 01 00 14 80 00 0a 02 86 dd 80 00 14 01 3a 80 \ > >> +00 3a 01 87 00 00 00 00 00 04 00 30 00 00 00 00 \ > >> +00 19 00 18 80 00 3e 10 00 00 00 00 00 00 00 00 \ > >> +00 00 00 00 00 00 00 01 00 19 00 10 80 00 40 06 \ > >> +aa aa aa aa aa aa 00 00 > >> +" 2], [0], [dnl > >> +OFPT_FLOW_MOD (OF1.2) (xid=0x2): ADD priority=255,icmp6,icmp_type=135 > >> actions=set_field:::1->nd_target,set_field:aa:aa:aa:aa:aa:aa->nd_sll > >> +], [dnl > >> +]) > >> +AT_CLEANUP > >> + > >> dnl This triggered a buggy "instructions out of order" message earlier. > >> AT_SETUP([OFPT_FLOW_MOD - OF1.3 - meter]) > >> AT_KEYWORDS([ofp-print]) > >> diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at > >> index baa942f..8f19e80 100644 > >> --- a/tests/ofproto-dpif.at > >> +++ b/tests/ofproto-dpif.at > >> @@ -198,6 +198,25 @@ Datapath actions: > >> 10,set(ipv4(src=192.168.3.91)),11,set(ipv4(src=192.168.3.90)), > >> OVS_VSWITCHD_STOP > >> AT_CLEANUP > >> > >> +AT_SETUP([ofproto-dpif - modify IPv6 Neighbor Solitication (ND)]) > >> +OVS_VSWITCHD_START > >> +ADD_OF_PORTS([br0], [1], [10], [11], [12], [13]) > >> +AT_DATA([flows.txt], [dnl > >> +table=0 in_port=1,icmp6,icmpv6_type=135 > >> actions=output(10),write_actions(set_field:fe80::3->nd_target,set_field:aa:aa:aa:aa:aa:aa->nd_sll,output(12)),goto_table(1) > >> +table=1 icmp6 actions=write_actions(output(13)),goto_table(2) > >> +table=2 in_port=1,icmp6,icmpv6_type=135 > >> actions=set_field:fe80::4->nd_target,set_field:cc:cc:cc:cc:cc:cc->nd_sll,output(11) > >> +]) > >> +AT_CHECK([ovs-ofctl -O OpenFlow12 add-flows br0 flows.txt]) > >> +AT_CHECK([ovs-appctl ofproto/trace br0 > >> 'in_port=1,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,icmp6,ipv6_src=fe80::1,ipv6_dst=fe80::2,nw_tos=0,nw_ttl=128,icmpv6_type=135,nd_target=fe80::2020,nd_sll=66:55:44:33:22:11'], > >> [0], [stdout]) > >> +AT_CHECK([tail -4 stdout], [0], > >> + [Megaflow: > >> recirc_id=0,icmp6,in_port=1,nw_frag=no,icmp_type=135,icmp_code=0x0/0xff,nd_target=fe80::2020,nd_sll=66:55:44:33:22:11 > >> +Datapath actions: > >> 10,set(nd(target=fe80::4,sll=cc:cc:cc:cc:cc:cc)),11,set(nd(target=fe80::3,sll=aa:aa:aa:aa:aa:aa)),13 > >> +This flow is handled by the userspace slow path because it: > >> + - Uses action(s) not supported by datapath. > >> +]) > >> +OVS_VSWITCHD_STOP > >> +AT_CLEANUP > >> + > >> AT_SETUP([ofproto-dpif - clear actions]) > >> OVS_VSWITCHD_START > >> ADD_OF_PORTS([br0], [1], [10], [11], [12]) > >> @@ -6280,8 +6299,30 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) > >> > >> AT_CHECK([cat ofctl_monitor.log], [0], [dnl > >> NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via no_match) > >> data_len=86 (unbuffered) > >> -icmp6,in_port=0,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::260:97ff:fe07:69ea,nd_sll=00:00:86:05:80:da,nd_tll=00:00:00:00:00:00 > >> +icmp6,in_port=0,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::260:97ff:fe07:69ea,nd_sll=00:00:86:05:80:da,nd_tll=00:00:00:00:00:00 > >> icmp6_csum:68bd > >> ]) > >> > >> OVS_VSWITCHD_STOP > >> AT_CLEANUP > >> + > >> +AT_SETUP([ofproto-dpif - Neighbor Discovery set-field with checksum > >> update]) > >> +OVS_VSWITCHD_START > >> +ADD_OF_PORTS([br0], 1) > >> +AT_CHECK([ovs-ofctl add-flow br0 > >> icmp6,icmpv6_type=135,action=set_field:fe80::1-\>nd_target,set_field:32:21:14:86:11:74-\>nd_sll,output:controller]) > >> + > >> +AT_CAPTURE_FILE([ofctl_monitor.log]) > >> + > >> +AT_CHECK([ovs-ofctl monitor br0 65534 --detach --no-chdir --pidfile 2> > >> ofctl_monitor.log]) > >> + > >> +ovs-appctl netdev-dummy/receive p1 > >> '0060970769ea0000860580da86dd6000000000203afffe80000000000000020086fffe0580dafe80000000000000026097fffe0769ea870068bd00000000fe80000000000000026097fffe0769ea01010000860580da' > >> + > >> +OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit]) > >> + > >> +AT_CHECK([cat ofctl_monitor.log], [0], [dnl > >> +NXT_PACKET_IN (xid=0x0): cookie=0x0 total_len=86 in_port=1 (via action) > >> data_len=86 (unbuffered) > >> +icmp6,in_port=0,vlan_tci=0x0000,dl_src=00:00:86:05:80:da,dl_dst=00:60:97:07:69:ea,ipv6_src=fe80::200:86ff:fe05:80da,ipv6_dst=fe80::260:97ff:fe07:69ea,ipv6_label=0x00000,nw_tos=0,nw_ecn=0,nw_ttl=255,icmp_type=135,icmp_code=0,nd_target=fe80::1,nd_sll=32:21:14:86:11:74,nd_tll=00:00:00:00:00:00 > >> icmp6_csum:19d3 > >> +]) > >> + > >> +OVS_VSWITCHD_STOP > >> +AT_CLEANUP > >> + > >> diff --git a/tests/ofproto.at b/tests/ofproto.at > >> index 8cfecc6..ad47d6d 100644 > >> --- a/tests/ofproto.at > >> +++ b/tests/ofproto.at > >> @@ -844,7 +844,9 @@ AT_SETUP([ofproto - set-field flow_mod commands (NXM)]) > >> OVS_VSWITCHD_START > >> AT_CHECK([ovs-ofctl add-flow br0 ipv6,table=1,in_port=3,actions=drop]) > >> AT_CHECK([ovs-ofctl add-flow br0 > >> ipv6,table=1,in_port=3,actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa-\>ipv6_src]) > >> +AT_CHECK([ovs-ofctl add-flow br0 > >> icmp6,icmp_type=136,table=1,in_port=3,actions=set_field:fe80:8675:3097:890a:a6ba:dbff:f00d:59fa-\>nd_target,set_field:cc:dd:ee:ff:00:11-\>nd_tll]) > >> AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl > >> + table=1, icmp6,in_port=3,icmp_type=136 > >> actions=load:0xa6badbfff00d59fa->NXM_NX_ND_TARGET[[0..63]],load:0xfe8086753097890a->NXM_NX_ND_TARGET[[64..127]],load:0xccddeeff0011->NXM_NX_ND_TLL[[]] > >> table=1, ipv6,in_port=3 > >> actions=load:0xa6badbfffefe59fa->NXM_NX_IPV6_SRC[[0..63]],load:0xfe8001234567890a->NXM_NX_IPV6_SRC[[64..127]] > >> NXST_FLOW reply: > >> ]) > >> @@ -870,6 +872,19 @@ AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | > >> ofctl_strip], [0], [OFPST_FLO > >> OVS_VSWITCHD_STOP > >> AT_CLEANUP > >> > >> +AT_SETUP([ofproto - set-field flow_mod commands (OF1.2)]) > >> +OVS_VSWITCHD_START > >> +AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 > >> ipv6,table=1,in_port=3,actions=drop]) > >> +AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 > >> ipv6,table=1,in_port=3,actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa-\>ipv6_src]) > >> +AT_CHECK([ovs-ofctl -O OpenFlow12 add-flow br0 > >> icmp6,icmp_type=136,table=1,in_port=3,actions=set_field:fe80:8675:3097:890a:a6ba:dbff:f00d:59fa-\>nd_target,set_field:cc:dd:ee:ff:00:11-\>nd_tll]) > >> +AT_CHECK([ovs-ofctl -O OpenFlow12 dump-flows br0 | ofctl_strip | sort], > >> [0], [dnl > >> + table=1, icmp6,in_port=3,icmp_type=136 > >> actions=set_field:fe80:8675:3097:890a:a6ba:dbff:f00d:59fa->nd_target,set_field:cc:dd:ee:ff:00:11->nd_tll > >> + table=1, ipv6,in_port=3 > >> actions=set_field:fe80:123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src > >> +OFPST_FLOW reply (OF1.2): > >> +]) > >> +OVS_VSWITCHD_STOP > >> +AT_CLEANUP > >> + > >> AT_SETUP([ofproto - dump flows with cookie]) > >> OVS_VSWITCHD_START > >> AT_CHECK([ovs-ofctl add-flow br0 cookie=0x1,in_port=1,actions=1]) > >> @@ -1323,7 +1338,7 @@ OVS_VSWITCHD_START > >> instructions: > >> apply_actions,clear_actions,write_actions,write_metadata,goto_table > >> Write-Actions and Apply-Actions features: > >> actions: output group set_field strip_vlan push_vlan mod_nw_ttl > >> dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue > >> - supported on Set-Field: metadata in_port_oxm eth_src eth_dst > >> vlan_vid vlan_pcp mpls_label mpls_tc ip_src ip_dst ipv6_src ipv6_dst > >> ip_dscp nw_ecn arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst > >> udp_src udp_dst sctp_src sctp_dst > >> + supported on Set-Field: metadata in_port_oxm eth_src eth_dst > >> vlan_vid vlan_pcp mpls_label mpls_tc ip_src ip_dst ipv6_src ipv6_dst > >> ip_dscp nw_ecn arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst > >> udp_src udp_dst sctp_src sctp_dst nd_target nd_sll nd_tll > >> matching: > >> metadata: exact match or wildcard > >> in_port_oxm: exact match or wildcard > >> @@ -1401,7 +1416,7 @@ OVS_VSWITCHD_START > >> instructions: > >> meter,apply_actions,clear_actions,write_actions,write_metadata,goto_table > >> Write-Actions and Apply-Actions features: > >> actions: output group set_field strip_vlan push_vlan mod_nw_ttl > >> dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue > >> - supported on Set-Field: tun_id tun_src tun_dst metadata in_port > >> in_port_oxm pkt_mark reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 > >> xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc > >> ip_src ip_dst ipv6_src ipv6_dst nw_tos ip_dscp nw_ecn nw_ttl arp_op > >> arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src > >> sctp_dst > >> + supported on Set-Field: tun_id tun_src tun_dst metadata in_port > >> in_port_oxm pkt_mark reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 > >> xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc > >> ip_src ip_dst ipv6_src ipv6_dst nw_tos ip_dscp nw_ecn nw_ttl arp_op > >> arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src > >> sctp_dst nd_target nd_sll nd_tll > >> matching: > >> dp_hash: arbitrary mask > >> recirc_id: exact match or wildcard > >> _______________________________________________ > >> dev mailing list > >> dev@openvswitch.org > >> http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev