[ovs-dev] [PATCH] IPv6: Add IPv6 extension header support

2022-11-18 Thread Toms Atteka
IPv6 extension headers carry optional internet layer information
and are placed between the fixed header and the upper-layer
protocol header.

This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Tested-at: https://github.com/TomCodeLV/ovs/actions/runs/504185214
Signed-off-by: Toms Atteka 
---
 build-aux/extract-odp-netlink-macros-h |   1 +
 include/linux/openvswitch.h|   6 +
 include/openvswitch/flow.h |   8 +-
 include/openvswitch/match.h|   2 +
 include/openvswitch/meta-flow.h|  18 +++
 lib/dpif-netdev-extract-avx512.c   |   2 +-
 lib/flow.c | 188 +++--
 lib/flow.h |   6 +-
 lib/match.c|  25 +++-
 lib/meta-flow.c|  82 ++-
 lib/meta-flow.xml  |  14 ++
 lib/nx-match.c |  58 ++--
 lib/odp-execute.c  |   2 +
 lib/odp-util.c | 110 ++-
 lib/odp-util.h |  11 +-
 lib/ofp-match.c|   2 +-
 lib/packets.c  |  28 
 lib/packets.h  |  15 ++
 ofproto/ofproto-dpif-rid.h |   2 +-
 ofproto/ofproto-dpif-sflow.c   |   1 +
 ofproto/ofproto-dpif-xlate.c   |   2 +-
 ofproto/ofproto-dpif.c |  47 +++
 python/build/extract_ofp_fields.py |   2 +
 tests/odp.at   |   9 +-
 tests/ofp-actions.at   |   1 +
 tests/ofproto.at   |   2 +-
 tests/oss-fuzz/config/odp.dict |   1 +
 tests/ovs-ofctl.at | 125 
 tests/system-traffic.at|  76 ++
 tests/test-odp.c   |   1 +
 30 files changed, 804 insertions(+), 43 deletions(-)

diff --git a/build-aux/extract-odp-netlink-macros-h 
b/build-aux/extract-odp-netlink-macros-h
index 7152f298c..c5a2d91d2 100755
--- a/build-aux/extract-odp-netlink-macros-h
+++ b/build-aux/extract-odp-netlink-macros-h
@@ -55,6 +55,7 @@ generate_fields_macros "ovs_key_icmpv6"
 generate_fields_macros "ovs_key_arp"
 generate_fields_macros "ovs_key_nd"
 generate_fields_macros "ovs_key_nd_extensions"
+generate_fields_macros "ovs_key_ipv6_exthdrs"
 
 echo
 echo "#endif"
diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h
index 8bb5abdc8..d6c0af74e 100644
--- a/include/linux/openvswitch.h
+++ b/include/linux/openvswitch.h
@@ -401,6 +401,7 @@ enum ovs_key_attr {
OVS_KEY_ATTR_TUNNEL_INFO,   /* struct ip_tunnel_info.
 * For in-kernel use only.
 */
+OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
__OVS_KEY_ATTR_MAX
 };
 
@@ -500,6 +501,11 @@ struct ovs_key_ipv6 {
__u8   ipv6_frag;   /* One of OVS_FRAG_TYPE_*. */
 };
 
+/* separate structure to support backward compatibility with older user space 
*/
+struct ovs_key_ipv6_exthdrs {
+__u16  hdrs;
+};
+
 struct ovs_key_tcp {
__be16 tcp_src;
__be16 tcp_dst;
diff --git a/include/openvswitch/flow.h b/include/openvswitch/flow.h
index df10cf579..1c80a6d45 100644
--- a/include/openvswitch/flow.h
+++ b/include/openvswitch/flow.h
@@ -27,7 +27,7 @@ extern "C" {
 /* This sequence number should be incremented whenever anything involving flows
  * or the wildcarding of flows changes.  This will cause build assertion
  * failures in places which likely need to be updated. */
-#define FLOW_WC_SEQ 42
+#define FLOW_WC_SEQ 43
 
 /* Number of Open vSwitch extension 32-bit registers. */
 #define FLOW_N_REGS 16
@@ -136,6 +136,8 @@ struct flow {
 struct in6_addr ipv6_dst;   /* IPv6 destination address. */
 struct in6_addr ct_ipv6_src; /* CT orig tuple IPv6 source address. */
 struct in6_addr ct_ipv6_dst; /* CT orig tuple IPv6 destination address. */
+uint16_t ipv6_exthdr;   /* IPv6 flow extension headers. */
+ovs_be16 pad4[3];   /* Pad to 64 bits. */
 ovs_be32 ipv6_label;/* IPv6 flow label. */
 uint8_t nw_frag;/* FLOW_FRAG_* flags. */
 uint8_t nw_tos; /* IP ToS (including DSCP and ECN). */
@@ -166,8 +168,8 @@ BUILD_ASSERT_DECL(sizeof(struct ovs_key_nsh) % 
sizeof(uint64_t) == 0);
 
 /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
 BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t)
-  == sizeof(struct flow_tnl) + sizeof(struct ovs_key_nsh) + 300
-  && FLOW_WC_SEQ == 42);
+  == sizeof(struct flow_tnl) + sizeof(struct ovs_key_nsh) + 308
+  && FLOW_WC_SEQ == 43);
 
 /* Incremental points at which flow classification may be performed in
  * segments.
diff --git 

[ovs-dev] [PATCHv2] bfd: Add IPv6 address support to BFD packets

2022-08-02 Thread Toms Atteka
Added config options for source and destination IPv6 addresses to
BFD packets. IPv6 address presence overrides IPv4 address and
packets are crafted as IPv6.

Added IP address values to status to ease setting up IP addresses.

Signed-off-by: Toms Atteka 
---
 lib/bfd.c| 119 ++-
 tests/bfd.at |  30 +++
 vswitchd/vswitch.xml |  10 
 3 files changed, 147 insertions(+), 12 deletions(-)

diff --git a/lib/bfd.c b/lib/bfd.c
index 9698576d0..f9f359e99 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -187,6 +187,9 @@ struct bfd {
 ovs_be32 ip_src;  /* IPv4 source address. */
 ovs_be32 ip_dst;  /* IPv4 destination address. */
 
+struct in6_addr ipv6_src;  /* IPv6 source address. */
+struct in6_addr ipv6_dst;  /* IPv6 destination address. */
+
 uint16_t udp_src; /* UDP source port. */
 
 /* All timers in milliseconds. */
@@ -244,10 +247,14 @@ static struct hmap *const all_bfds OVS_GUARDED_BY(mutex) 
= _bfds__;
 
 static void bfd_lookup_ip(const char *host_name, ovs_be32 def, ovs_be32 *ip)
 OVS_REQUIRES(mutex);
+static void bfd_lookup_ipv6(const char *host_name, struct in6_addr *ipv6)
+OVS_REQUIRES(mutex);
 static bool bfd_forwarding__(struct bfd *) OVS_REQUIRES(mutex);
 static bool bfd_in_poll(const struct bfd *) OVS_REQUIRES(mutex);
 static void bfd_poll(struct bfd *bfd) OVS_REQUIRES(mutex);
 static const char *bfd_diag_str(enum diag) OVS_REQUIRES(mutex);
+static const char *bfd_ip_str(ovs_be32 ip) OVS_REQUIRES(mutex);
+static const char *bfd_ipv6_str(struct in6_addr ipv6) OVS_REQUIRES(mutex);
 static const char *bfd_state_str(enum state) OVS_REQUIRES(mutex);
 static long long int bfd_min_tx(const struct bfd *) OVS_REQUIRES(mutex);
 static long long int bfd_tx_interval(const struct bfd *)
@@ -332,6 +339,18 @@ bfd_get_status(const struct bfd *bfd, struct smap *smap)
 smap_add_format(smap, "flap_count", "%"PRIu64, bfd->flap_count);
 smap_add(smap, "remote_state", bfd_state_str(bfd->rmt_state));
 smap_add(smap, "remote_diagnostic", bfd_diag_str(bfd->rmt_diag));
+if (bfd->ip_src) {
+smap_add(smap, "bfd_src_ip", bfd_ip_str(bfd->ip_src));
+}
+if (bfd->ip_dst) {
+smap_add(smap, "bfd_dst_ip", bfd_ip_str(bfd->ip_dst));
+}
+if (ipv6_addr_is_set(>ipv6_src)) {
+   smap_add(smap, "bfd_src_ipv6", bfd_ipv6_str(bfd->ipv6_src));
+}
+if (ipv6_addr_is_set(>ipv6_dst)) {
+smap_add(smap, "bfd_dst_ipv6", bfd_ipv6_str(bfd->ipv6_dst));
+}
 ovs_mutex_unlock();
 }
 
@@ -465,6 +484,10 @@ bfd_configure(struct bfd *bfd, const char *name, const 
struct smap *cfg,
 bfd_lookup_ip(smap_get_def(cfg, "bfd_dst_ip", ""),
   htonl(BFD_DEFAULT_DST_IP), >ip_dst);
 
+bfd_lookup_ipv6(smap_get_def(cfg, "bfd_src_ipv6", ""), >ipv6_src);
+bfd_lookup_ipv6(smap_get_def(cfg, "bfd_dst_ipv6", ""), >ipv6_dst);
+
+
 forwarding_if_rx = smap_get_bool(cfg, "forwarding_if_rx", false);
 if (bfd->forwarding_if_rx != forwarding_if_rx) {
 bfd->forwarding_if_rx = forwarding_if_rx;
@@ -588,6 +611,7 @@ bfd_put_packet(struct bfd *bfd, struct dp_packet *p,
 struct udp_header *udp;
 struct eth_header *eth;
 struct ip_header *ip;
+struct ovs_16aligned_ip6_hdr *ip6;
 struct msg *msg;
 
 ovs_mutex_lock();
@@ -611,23 +635,40 @@ bfd_put_packet(struct bfd *bfd, struct dp_packet *p,
 ? eth_src : bfd->local_eth_src;
 eth->eth_dst = eth_addr_is_zero(bfd->local_eth_dst)
 ? eth_addr_bfd : bfd->local_eth_dst;
-eth->eth_type = htons(ETH_TYPE_IP);
-
-ip = dp_packet_put_zeros(p, sizeof *ip);
-ip->ip_ihl_ver = IP_IHL_VER(5, 4);
-ip->ip_tot_len = htons(sizeof *ip + sizeof *udp + sizeof *msg);
-ip->ip_ttl = MAXTTL;
-ip->ip_tos = IPTOS_PREC_INTERNETCONTROL;
-ip->ip_proto = IPPROTO_UDP;
-put_16aligned_be32(>ip_src, bfd->ip_src);
-put_16aligned_be32(>ip_dst, bfd->ip_dst);
-/* Checksum has already been zeroed by put_zeros call. */
-ip->ip_csum = csum(ip, sizeof *ip);
+
+if (ipv6_addr_is_set(>ipv6_src)) {
+eth->eth_type = htons(ETH_TYPE_IPV6);
+
+ip6 = dp_packet_put_zeros(p, sizeof *ip6);
+
+ip6->ip6_vfc = 0x60;
+ip6->ip6_hlim = MAXTTL;
+ip6->ip6_nxt = IPPROTO_UDP;
+ip6->ip6_plen = htons(sizeof *udp + sizeof *msg);
+
+memcpy(>ip6_src, >ipv6_src, sizeof(bfd->ipv6_src));
+memcpy(>ip6_dst, >ipv6_dst, sizeof(bfd->ipv6_dst));
+
+} else {
+eth->eth_type = htons(ETH_TYPE_IP);
+
+ip = dp_packet_put_zeros(p, sizeof *ip);
+ip->ip_ihl_ver = IP_IHL_VER(5, 4);
+   

[ovs-dev] [PATCH] bfd: Add IPv6 address support to BFD packets

2022-08-02 Thread Toms Atteka
Added config options for source and destination IPv6 addresses to
BFD packets. IPv6 address presence overrides IPv4 address and
packets are crafted as IPv6.

Added IP address values to status to ease setting up IP addresses.

Signed-off-by: Toms Atteka 
---
 lib/bfd.c| 119 ++-
 tests/bfd.at |  30 +++
 vswitchd/vswitch.xml |  10 
 3 files changed, 147 insertions(+), 12 deletions(-)

diff --git a/lib/bfd.c b/lib/bfd.c
index 9698576d0..f9f359e99 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -187,6 +187,9 @@ struct bfd {
 ovs_be32 ip_src;  /* IPv4 source address. */
 ovs_be32 ip_dst;  /* IPv4 destination address. */
 
+struct in6_addr ipv6_src;  /* IPv6 source address. */
+struct in6_addr ipv6_dst;  /* IPv6 destination address. */
+
 uint16_t udp_src; /* UDP source port. */
 
 /* All timers in milliseconds. */
@@ -244,10 +247,14 @@ static struct hmap *const all_bfds OVS_GUARDED_BY(mutex) 
= _bfds__;
 
 static void bfd_lookup_ip(const char *host_name, ovs_be32 def, ovs_be32 *ip)
 OVS_REQUIRES(mutex);
+static void bfd_lookup_ipv6(const char *host_name, struct in6_addr *ipv6)
+OVS_REQUIRES(mutex);
 static bool bfd_forwarding__(struct bfd *) OVS_REQUIRES(mutex);
 static bool bfd_in_poll(const struct bfd *) OVS_REQUIRES(mutex);
 static void bfd_poll(struct bfd *bfd) OVS_REQUIRES(mutex);
 static const char *bfd_diag_str(enum diag) OVS_REQUIRES(mutex);
+static const char *bfd_ip_str(ovs_be32 ip) OVS_REQUIRES(mutex);
+static const char *bfd_ipv6_str(struct in6_addr ipv6) OVS_REQUIRES(mutex);
 static const char *bfd_state_str(enum state) OVS_REQUIRES(mutex);
 static long long int bfd_min_tx(const struct bfd *) OVS_REQUIRES(mutex);
 static long long int bfd_tx_interval(const struct bfd *)
@@ -332,6 +339,18 @@ bfd_get_status(const struct bfd *bfd, struct smap *smap)
 smap_add_format(smap, "flap_count", "%"PRIu64, bfd->flap_count);
 smap_add(smap, "remote_state", bfd_state_str(bfd->rmt_state));
 smap_add(smap, "remote_diagnostic", bfd_diag_str(bfd->rmt_diag));
+if (bfd->ip_src) {
+smap_add(smap, "bfd_src_ip", bfd_ip_str(bfd->ip_src));
+}
+if (bfd->ip_dst) {
+smap_add(smap, "bfd_dst_ip", bfd_ip_str(bfd->ip_dst));
+}
+if (ipv6_addr_is_set(>ipv6_src)) {
+   smap_add(smap, "bfd_src_ipv6", bfd_ipv6_str(bfd->ipv6_src));
+}
+if (ipv6_addr_is_set(>ipv6_dst)) {
+smap_add(smap, "bfd_dst_ipv6", bfd_ipv6_str(bfd->ipv6_dst));
+}
 ovs_mutex_unlock();
 }
 
@@ -465,6 +484,10 @@ bfd_configure(struct bfd *bfd, const char *name, const 
struct smap *cfg,
 bfd_lookup_ip(smap_get_def(cfg, "bfd_dst_ip", ""),
   htonl(BFD_DEFAULT_DST_IP), >ip_dst);
 
+bfd_lookup_ipv6(smap_get_def(cfg, "bfd_src_ipv6", ""), >ipv6_src);
+bfd_lookup_ipv6(smap_get_def(cfg, "bfd_dst_ipv6", ""), >ipv6_dst);
+
+
 forwarding_if_rx = smap_get_bool(cfg, "forwarding_if_rx", false);
 if (bfd->forwarding_if_rx != forwarding_if_rx) {
 bfd->forwarding_if_rx = forwarding_if_rx;
@@ -588,6 +611,7 @@ bfd_put_packet(struct bfd *bfd, struct dp_packet *p,
 struct udp_header *udp;
 struct eth_header *eth;
 struct ip_header *ip;
+struct ovs_16aligned_ip6_hdr *ip6;
 struct msg *msg;
 
 ovs_mutex_lock();
@@ -611,23 +635,40 @@ bfd_put_packet(struct bfd *bfd, struct dp_packet *p,
 ? eth_src : bfd->local_eth_src;
 eth->eth_dst = eth_addr_is_zero(bfd->local_eth_dst)
 ? eth_addr_bfd : bfd->local_eth_dst;
-eth->eth_type = htons(ETH_TYPE_IP);
-
-ip = dp_packet_put_zeros(p, sizeof *ip);
-ip->ip_ihl_ver = IP_IHL_VER(5, 4);
-ip->ip_tot_len = htons(sizeof *ip + sizeof *udp + sizeof *msg);
-ip->ip_ttl = MAXTTL;
-ip->ip_tos = IPTOS_PREC_INTERNETCONTROL;
-ip->ip_proto = IPPROTO_UDP;
-put_16aligned_be32(>ip_src, bfd->ip_src);
-put_16aligned_be32(>ip_dst, bfd->ip_dst);
-/* Checksum has already been zeroed by put_zeros call. */
-ip->ip_csum = csum(ip, sizeof *ip);
+
+if (ipv6_addr_is_set(>ipv6_src)) {
+eth->eth_type = htons(ETH_TYPE_IPV6);
+
+ip6 = dp_packet_put_zeros(p, sizeof *ip6);
+
+ip6->ip6_vfc = 0x60;
+ip6->ip6_hlim = MAXTTL;
+ip6->ip6_nxt = IPPROTO_UDP;
+ip6->ip6_plen = htons(sizeof *udp + sizeof *msg);
+
+memcpy(>ip6_src, >ipv6_src, sizeof(bfd->ipv6_src));
+memcpy(>ip6_dst, >ipv6_dst, sizeof(bfd->ipv6_dst));
+
+} else {
+eth->eth_type = htons(ETH_TYPE_IP);
+
+ip = dp_packet_put_zeros(p, sizeof *ip);
+ip->ip_ihl_ver = IP_IHL_VER(5, 4);
+   

[ovs-dev] [PATCHv2] IPv6: Add IPv6 extension header support

2022-03-18 Thread Toms Atteka
IPv6 extension headers carry optional internet layer information
and are placed between the fixed header and the upper-layer
protocol header.

This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Some spacing style issues fixed.

Tested-at: https://github.com/TomCodeLV/ovs/actions/runs/504185214
Signed-off-by: Toms Atteka 
---
 build-aux/extract-odp-netlink-macros-h|   1 +
 build-aux/extract-ofp-fields  |   4 +-
 datapath/flow.c   | 192 +++---
 datapath/flow.h   |  14 ++
 datapath/flow_netlink.c   |  25 ++-
 .../linux/compat/include/linux/openvswitch.h  |   6 +
 include/openvswitch/flow.h|   8 +-
 include/openvswitch/match.h   |   2 +
 include/openvswitch/meta-flow.h   |  18 ++
 lib/dpif-netdev-extract-avx512.c  |   2 +-
 lib/flow.c| 188 -
 lib/flow.h|   6 +-
 lib/match.c   |  25 ++-
 lib/meta-flow.c   |  80 +++-
 lib/meta-flow.xml |  14 ++
 lib/nx-match.c|  13 +-
 lib/odp-execute.c |   2 +
 lib/odp-util.c| 111 +-
 lib/odp-util.h|  11 +-
 lib/ofp-match.c   |   2 +-
 lib/packets.c |  28 +++
 lib/packets.h |  12 ++
 ofproto/ofproto-dpif-rid.h|   2 +-
 ofproto/ofproto-dpif-sflow.c  |   1 +
 ofproto/ofproto-dpif-xlate.c  |   2 +-
 ofproto/ofproto-dpif.c|  47 +
 tests/ofproto.at  |   4 +-
 tests/system-traffic.at   |  31 +++
 28 files changed, 789 insertions(+), 62 deletions(-)

diff --git a/build-aux/extract-odp-netlink-macros-h 
b/build-aux/extract-odp-netlink-macros-h
index 7152f298c..c5a2d91d2 100755
--- a/build-aux/extract-odp-netlink-macros-h
+++ b/build-aux/extract-odp-netlink-macros-h
@@ -55,6 +55,7 @@ generate_fields_macros "ovs_key_icmpv6"
 generate_fields_macros "ovs_key_arp"
 generate_fields_macros "ovs_key_nd"
 generate_fields_macros "ovs_key_nd_extensions"
+generate_fields_macros "ovs_key_ipv6_exthdrs"
 
 echo
 echo "#endif"
diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields
index 8766995d9..df71e4dfa 100755
--- a/build-aux/extract-ofp-fields
+++ b/build-aux/extract-ofp-fields
@@ -19,6 +19,7 @@ VERSION = {"1.0": 0x01,
 VERSION_REVERSE = dict((v,k) for k, v in VERSION.items())
 
 TYPES = {"u8":   (1,   False),
+ "u16":  (2,   False),
  "be16": (2,   False),
  "be32": (4,   False),
  "MAC":  (6,   False),
@@ -37,7 +38,8 @@ FORMATTING = {"decimal":("MFS_DECIMAL",  1,   
8),
   "frag":   ("MFS_FRAG", 1,   1),
   "tunnel flags":   ("MFS_TNL_FLAGS",2,   2),
   "TCP flags":  ("MFS_TCP_FLAGS",2,   2),
-  "packet type":("MFS_PACKET_TYPE",  4,   4)}
+  "packet type":("MFS_PACKET_TYPE",  4,   4),
+  "IPV6 ext hdr":   ("MFS_IPV6_EXTHDR",  2,   2)}
 
 PREREQS = {"none": "MFP_NONE",
"Ethernet": "MFP_ETHERNET",
diff --git a/datapath/flow.c b/datapath/flow.c
index 5a00c238c..1247c298a 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -98,17 +98,17 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 
tcp_flags,
 * allocated stats as we have already locked them.
 */
if (likely(flow->stats_last_writer != -1) &&
-   likely(!rcu_access_pointer(flow->stats[cpu]))) {
+   likely(!rcu_access_pointer(flow->stats[cpu]))) {
/* Try to allocate CPU-specific stats. */
struct sw_flow_stats *new_stats;
 
new_stats =
kmem_cache_alloc_node(flow_stats_cache,
-  GFP_NOWAIT |
-  __GFP_THISNODE |
-

[ovs-dev] [PATCH] IPv6: Add IPv6 extension header support

2022-03-18 Thread Toms Atteka
From: Toms Atteka 

IPv6 extension headers carry optional internet layer information
and are placed between the fixed header and the upper-layer
protocol header.

This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Some spacing style issues fixed.

Tested-at: https://github.com/TomCodeLV/ovs/actions/runs/504185214
Signed-off-by: Toms Atteka 
---
 build-aux/extract-odp-netlink-macros-h|   1 +
 build-aux/extract-ofp-fields  |   4 +-
 datapath/flow.c   | 192 +++---
 datapath/flow.h   |  14 ++
 datapath/flow_netlink.c   |  25 ++-
 .../linux/compat/include/linux/openvswitch.h  |   6 +
 include/openvswitch/flow.h|   8 +-
 include/openvswitch/match.h   |   2 +
 include/openvswitch/meta-flow.h   |  18 ++
 lib/dpif-netdev-extract-avx512.c  |   2 +-
 lib/flow.c| 188 -
 lib/flow.h|   6 +-
 lib/match.c   |  25 ++-
 lib/meta-flow.c   |  80 +++-
 lib/meta-flow.xml |  14 ++
 lib/nx-match.c|  13 +-
 lib/odp-execute.c |   2 +
 lib/odp-util.c| 110 +-
 lib/odp-util.h|  11 +-
 lib/ofp-match.c   |   2 +-
 lib/packets.c |  28 +++
 lib/packets.h |  12 ++
 ofproto/ofproto-dpif-rid.h|   2 +-
 ofproto/ofproto-dpif-sflow.c  |   1 +
 ofproto/ofproto-dpif-xlate.c  |   2 +-
 ofproto/ofproto-dpif.c|  47 +
 tests/ofproto.at  |   4 +-
 tests/system-traffic.at   |  31 +++
 28 files changed, 788 insertions(+), 62 deletions(-)

diff --git a/build-aux/extract-odp-netlink-macros-h 
b/build-aux/extract-odp-netlink-macros-h
index 7152f298c..c5a2d91d2 100755
--- a/build-aux/extract-odp-netlink-macros-h
+++ b/build-aux/extract-odp-netlink-macros-h
@@ -55,6 +55,7 @@ generate_fields_macros "ovs_key_icmpv6"
 generate_fields_macros "ovs_key_arp"
 generate_fields_macros "ovs_key_nd"
 generate_fields_macros "ovs_key_nd_extensions"
+generate_fields_macros "ovs_key_ipv6_exthdrs"
 
 echo
 echo "#endif"
diff --git a/build-aux/extract-ofp-fields b/build-aux/extract-ofp-fields
index 8766995d9..df71e4dfa 100755
--- a/build-aux/extract-ofp-fields
+++ b/build-aux/extract-ofp-fields
@@ -19,6 +19,7 @@ VERSION = {"1.0": 0x01,
 VERSION_REVERSE = dict((v,k) for k, v in VERSION.items())
 
 TYPES = {"u8":   (1,   False),
+ "u16":  (2,   False),
  "be16": (2,   False),
  "be32": (4,   False),
  "MAC":  (6,   False),
@@ -37,7 +38,8 @@ FORMATTING = {"decimal":("MFS_DECIMAL",  1,   
8),
   "frag":   ("MFS_FRAG", 1,   1),
   "tunnel flags":   ("MFS_TNL_FLAGS",2,   2),
   "TCP flags":  ("MFS_TCP_FLAGS",2,   2),
-  "packet type":("MFS_PACKET_TYPE",  4,   4)}
+  "packet type":("MFS_PACKET_TYPE",  4,   4),
+  "IPV6 ext hdr":   ("MFS_IPV6_EXTHDR",  2,   2)}
 
 PREREQS = {"none": "MFP_NONE",
"Ethernet": "MFP_ETHERNET",
diff --git a/datapath/flow.c b/datapath/flow.c
index 5a00c238c..1247c298a 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -98,17 +98,17 @@ void ovs_flow_stats_update(struct sw_flow *flow, __be16 
tcp_flags,
 * allocated stats as we have already locked them.
 */
if (likely(flow->stats_last_writer != -1) &&
-   likely(!rcu_access_pointer(flow->stats[cpu]))) {
+   likely(!rcu_access_pointer(flow->stats[cpu]))) {
/* Try to allocate CPU-specific stats. */
struct sw_flow_stats *new_stats;
 
new_stats =
kmem_cache_alloc_node(flow_stats_cache,
-  GFP_NOWAIT |
-  __GFP_THISNODE |
-

[ovs-dev] [PATCH net-next v8] net: openvswitch: IPv6: Add IPv6 extension header support

2022-02-23 Thread Toms Atteka
This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Signed-off-by: Toms Atteka 
Acked-by: Pravin B Shelar 
---
 include/uapi/linux/openvswitch.h |   6 ++
 net/openvswitch/flow.c   | 140 +++
 net/openvswitch/flow.h   |  14 
 net/openvswitch/flow_netlink.c   |  26 +-
 4 files changed, 184 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 150bcff49b1c..9d1710f20505 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -351,6 +351,7 @@ enum ovs_key_attr {
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,   /* struct ovs_key_ct_tuple_ipv4 */
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,   /* struct ovs_key_ct_tuple_ipv6 */
OVS_KEY_ATTR_NSH,   /* Nested set of ovs_nsh_key_* */
+   OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
 
 #ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
@@ -430,6 +431,11 @@ struct ovs_key_ipv6 {
__u8   ipv6_frag;   /* One of OVS_FRAG_TYPE_*. */
 };
 
+/* separate structure to support backward compatibility with older user space 
*/
+struct ovs_key_ipv6_exthdrs {
+   __u16  hdrs;
+};
+
 struct ovs_key_tcp {
__be16 tcp_src;
__be16 tcp_dst;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index f6cd24fd530c..8df73d86b968 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -241,6 +241,144 @@ static bool icmphdr_ok(struct sk_buff *skb)
  sizeof(struct icmphdr));
 }
 
+/**
+ * get_ipv6_ext_hdrs() - Parses packet and sets IPv6 extension header flags.
+ *
+ * @skb: buffer where extension header data starts in packet
+ * @nh: ipv6 header
+ * @ext_hdrs: flags are stored here
+ *
+ * OFPIEH12_UNREP is set if more than one of a given IPv6 extension header
+ * is unexpectedly encountered. (Two destination options headers may be
+ * expected and would not cause this bit to be set.)
+ *
+ * OFPIEH12_UNSEQ is set if IPv6 extension headers were not in the order
+ * preferred (but not required) by RFC 2460:
+ *
+ * When more than one extension header is used in the same packet, it is
+ * recommended that those headers appear in the following order:
+ *  IPv6 header
+ *  Hop-by-Hop Options header
+ *  Destination Options header
+ *  Routing header
+ *  Fragment header
+ *  Authentication header
+ *  Encapsulating Security Payload header
+ *  Destination Options header
+ *  upper-layer header
+ */
+static void get_ipv6_ext_hdrs(struct sk_buff *skb, struct ipv6hdr *nh,
+ u16 *ext_hdrs)
+{
+   u8 next_type = nh->nexthdr;
+   unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+   int dest_options_header_count = 0;
+
+   *ext_hdrs = 0;
+
+   while (ipv6_ext_hdr(next_type)) {
+   struct ipv6_opt_hdr _hdr, *hp;
+
+   switch (next_type) {
+   case IPPROTO_NONE:
+   *ext_hdrs |= OFPIEH12_NONEXT;
+   /* stop parsing */
+   return;
+
+   case IPPROTO_ESP:
+   if (*ext_hdrs & OFPIEH12_ESP)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs & ~(OFPIEH12_HOP | OFPIEH12_DEST |
+  OFPIEH12_ROUTER | IPPROTO_FRAGMENT |
+  OFPIEH12_AUTH | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_ESP;
+   break;
+
+   case IPPROTO_AH:
+   if (*ext_hdrs & OFPIEH12_AUTH)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs &
+~(OFPIEH12_HOP | OFPIEH12_DEST | OFPIEH12_ROUTER |
+  IPPROTO_FRAGMENT | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_AUTH;
+   break;
+
+   case IPPROTO_DSTOPTS:
+   if (dest_options_header_count == 0) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_UNREP))
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   *ext_hdrs |= OFPIEH12_DEST;
+   } else if (dest_options_header_count == 1) {
+   if (*ext_hdrs &
+

[ovs-dev] [PATCH net-next v8] net: openvswitch: IPv6: Add IPv6 extension header support

2021-11-24 Thread Toms Atteka
This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Signed-off-by: Toms Atteka 
---
 include/uapi/linux/openvswitch.h |   6 ++
 net/openvswitch/flow.c   | 140 +++
 net/openvswitch/flow.h   |  14 
 net/openvswitch/flow_netlink.c   |  26 +-
 4 files changed, 184 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index a87b44cd5590..43790f07e4a2 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -342,6 +342,7 @@ enum ovs_key_attr {
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,   /* struct ovs_key_ct_tuple_ipv4 */
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,   /* struct ovs_key_ct_tuple_ipv6 */
OVS_KEY_ATTR_NSH,   /* Nested set of ovs_nsh_key_* */
+   OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
 
 #ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
@@ -421,6 +422,11 @@ struct ovs_key_ipv6 {
__u8   ipv6_frag;   /* One of OVS_FRAG_TYPE_*. */
 };
 
+/* separate structure to support backward compatibility with older user space 
*/
+struct ovs_key_ipv6_exthdrs {
+   __u16  hdrs;
+};
+
 struct ovs_key_tcp {
__be16 tcp_src;
__be16 tcp_dst;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 9d375e74b607..28acb40437ca 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -239,6 +239,144 @@ static bool icmphdr_ok(struct sk_buff *skb)
  sizeof(struct icmphdr));
 }
 
+/**
+ * get_ipv6_ext_hdrs() - Parses packet and sets IPv6 extension header flags.
+ *
+ * @skb: buffer where extension header data starts in packet
+ * @nh: ipv6 header
+ * @ext_hdrs: flags are stored here
+ *
+ * OFPIEH12_UNREP is set if more than one of a given IPv6 extension header
+ * is unexpectedly encountered. (Two destination options headers may be
+ * expected and would not cause this bit to be set.)
+ *
+ * OFPIEH12_UNSEQ is set if IPv6 extension headers were not in the order
+ * preferred (but not required) by RFC 2460:
+ *
+ * When more than one extension header is used in the same packet, it is
+ * recommended that those headers appear in the following order:
+ *  IPv6 header
+ *  Hop-by-Hop Options header
+ *  Destination Options header
+ *  Routing header
+ *  Fragment header
+ *  Authentication header
+ *  Encapsulating Security Payload header
+ *  Destination Options header
+ *  upper-layer header
+ */
+static void get_ipv6_ext_hdrs(struct sk_buff *skb, struct ipv6hdr *nh,
+ u16 *ext_hdrs)
+{
+   u8 next_type = nh->nexthdr;
+   unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+   int dest_options_header_count = 0;
+
+   *ext_hdrs = 0;
+
+   while (ipv6_ext_hdr(next_type)) {
+   struct ipv6_opt_hdr _hdr, *hp;
+
+   switch (next_type) {
+   case IPPROTO_NONE:
+   *ext_hdrs |= OFPIEH12_NONEXT;
+   /* stop parsing */
+   return;
+
+   case IPPROTO_ESP:
+   if (*ext_hdrs & OFPIEH12_ESP)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs & ~(OFPIEH12_HOP | OFPIEH12_DEST |
+  OFPIEH12_ROUTER | IPPROTO_FRAGMENT |
+  OFPIEH12_AUTH | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_ESP;
+   break;
+
+   case IPPROTO_AH:
+   if (*ext_hdrs & OFPIEH12_AUTH)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs &
+~(OFPIEH12_HOP | OFPIEH12_DEST | OFPIEH12_ROUTER |
+  IPPROTO_FRAGMENT | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_AUTH;
+   break;
+
+   case IPPROTO_DSTOPTS:
+   if (dest_options_header_count == 0) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_UNREP))
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   *ext_hdrs |= OFPIEH12_DEST;
+   } else if (dest_options_header_count == 1) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_DEST |
+   

[ovs-dev] [PATCH net-next v8] net: openvswitch: IPv6: Add IPv6 extension header support

2021-10-29 Thread Toms Atteka
This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Signed-off-by: Toms Atteka 
---
 include/uapi/linux/openvswitch.h |   6 ++
 net/openvswitch/flow.c   | 140 +++
 net/openvswitch/flow.h   |  14 
 net/openvswitch/flow_netlink.c   |  26 +-
 4 files changed, 184 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index a87b44cd5590..43790f07e4a2 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -342,6 +342,7 @@ enum ovs_key_attr {
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4,   /* struct ovs_key_ct_tuple_ipv4 */
OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6,   /* struct ovs_key_ct_tuple_ipv6 */
OVS_KEY_ATTR_NSH,   /* Nested set of ovs_nsh_key_* */
+   OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
 
 #ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
@@ -421,6 +422,11 @@ struct ovs_key_ipv6 {
__u8   ipv6_frag;   /* One of OVS_FRAG_TYPE_*. */
 };
 
+/* separate structure to support backward compatibility with older user space 
*/
+struct ovs_key_ipv6_exthdrs {
+   __u16  hdrs;
+};
+
 struct ovs_key_tcp {
__be16 tcp_src;
__be16 tcp_dst;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 9d375e74b607..28acb40437ca 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -239,6 +239,144 @@ static bool icmphdr_ok(struct sk_buff *skb)
  sizeof(struct icmphdr));
 }
 
+/**
+ * get_ipv6_ext_hdrs() - Parses packet and sets IPv6 extension header flags.
+ *
+ * @skb: buffer where extension header data starts in packet
+ * @nh: ipv6 header
+ * @ext_hdrs: flags are stored here
+ *
+ * OFPIEH12_UNREP is set if more than one of a given IPv6 extension header
+ * is unexpectedly encountered. (Two destination options headers may be
+ * expected and would not cause this bit to be set.)
+ *
+ * OFPIEH12_UNSEQ is set if IPv6 extension headers were not in the order
+ * preferred (but not required) by RFC 2460:
+ *
+ * When more than one extension header is used in the same packet, it is
+ * recommended that those headers appear in the following order:
+ *  IPv6 header
+ *  Hop-by-Hop Options header
+ *  Destination Options header
+ *  Routing header
+ *  Fragment header
+ *  Authentication header
+ *  Encapsulating Security Payload header
+ *  Destination Options header
+ *  upper-layer header
+ */
+static void get_ipv6_ext_hdrs(struct sk_buff *skb, struct ipv6hdr *nh,
+ u16 *ext_hdrs)
+{
+   u8 next_type = nh->nexthdr;
+   unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+   int dest_options_header_count = 0;
+
+   *ext_hdrs = 0;
+
+   while (ipv6_ext_hdr(next_type)) {
+   struct ipv6_opt_hdr _hdr, *hp;
+
+   switch (next_type) {
+   case IPPROTO_NONE:
+   *ext_hdrs |= OFPIEH12_NONEXT;
+   /* stop parsing */
+   return;
+
+   case IPPROTO_ESP:
+   if (*ext_hdrs & OFPIEH12_ESP)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs & ~(OFPIEH12_HOP | OFPIEH12_DEST |
+  OFPIEH12_ROUTER | IPPROTO_FRAGMENT |
+  OFPIEH12_AUTH | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_ESP;
+   break;
+
+   case IPPROTO_AH:
+   if (*ext_hdrs & OFPIEH12_AUTH)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs &
+~(OFPIEH12_HOP | OFPIEH12_DEST | OFPIEH12_ROUTER |
+  IPPROTO_FRAGMENT | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_AUTH;
+   break;
+
+   case IPPROTO_DSTOPTS:
+   if (dest_options_header_count == 0) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_UNREP))
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   *ext_hdrs |= OFPIEH12_DEST;
+   } else if (dest_options_header_count == 1) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_DEST |
+   

[ovs-dev] [PATCH net-next v7] net: openvswitch: IPv6: Add IPv6 extension header support

2021-10-14 Thread Toms Atteka
This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Signed-off-by: Toms Atteka 
---
 include/uapi/linux/openvswitch.h |  16 +++-
 net/openvswitch/flow.c   | 140 +++
 net/openvswitch/flow.h   |  14 
 net/openvswitch/flow_netlink.c   |  24 +-
 4 files changed, 192 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index a87b44cd5590..763adf3dce23 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -344,8 +344,17 @@ enum ovs_key_attr {
OVS_KEY_ATTR_NSH,   /* Nested set of ovs_nsh_key_* */
 
 #ifdef __KERNEL__
-   OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
+   OVS_KEY_ATTR_TUNNEL_INFO,/* struct ip_tunnel_info */
+   __OVS_KEY_ATTR_PADDING_1,/* Padding to match field count with ovs */
 #endif
+
+#ifndef __KERNEL__
+   __OVS_KEY_ATTR_PADDING_2,/* Padding to match field count with ovs */
+   __OVS_KEY_ATTR_PADDING_3,/* Padding to match field count with ovs */
+#endif
+
+   OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
+
__OVS_KEY_ATTR_MAX
 };
 
@@ -421,6 +430,11 @@ struct ovs_key_ipv6 {
__u8   ipv6_frag;   /* One of OVS_FRAG_TYPE_*. */
 };
 
+/* separate structure to support backward compatibility with older user space 
*/
+struct ovs_key_ipv6_exthdrs {
+   __u16  hdrs;
+};
+
 struct ovs_key_tcp {
__be16 tcp_src;
__be16 tcp_dst;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 9d375e74b607..28acb40437ca 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -239,6 +239,144 @@ static bool icmphdr_ok(struct sk_buff *skb)
  sizeof(struct icmphdr));
 }
 
+/**
+ * get_ipv6_ext_hdrs() - Parses packet and sets IPv6 extension header flags.
+ *
+ * @skb: buffer where extension header data starts in packet
+ * @nh: ipv6 header
+ * @ext_hdrs: flags are stored here
+ *
+ * OFPIEH12_UNREP is set if more than one of a given IPv6 extension header
+ * is unexpectedly encountered. (Two destination options headers may be
+ * expected and would not cause this bit to be set.)
+ *
+ * OFPIEH12_UNSEQ is set if IPv6 extension headers were not in the order
+ * preferred (but not required) by RFC 2460:
+ *
+ * When more than one extension header is used in the same packet, it is
+ * recommended that those headers appear in the following order:
+ *  IPv6 header
+ *  Hop-by-Hop Options header
+ *  Destination Options header
+ *  Routing header
+ *  Fragment header
+ *  Authentication header
+ *  Encapsulating Security Payload header
+ *  Destination Options header
+ *  upper-layer header
+ */
+static void get_ipv6_ext_hdrs(struct sk_buff *skb, struct ipv6hdr *nh,
+ u16 *ext_hdrs)
+{
+   u8 next_type = nh->nexthdr;
+   unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+   int dest_options_header_count = 0;
+
+   *ext_hdrs = 0;
+
+   while (ipv6_ext_hdr(next_type)) {
+   struct ipv6_opt_hdr _hdr, *hp;
+
+   switch (next_type) {
+   case IPPROTO_NONE:
+   *ext_hdrs |= OFPIEH12_NONEXT;
+   /* stop parsing */
+   return;
+
+   case IPPROTO_ESP:
+   if (*ext_hdrs & OFPIEH12_ESP)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs & ~(OFPIEH12_HOP | OFPIEH12_DEST |
+  OFPIEH12_ROUTER | IPPROTO_FRAGMENT |
+  OFPIEH12_AUTH | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_ESP;
+   break;
+
+   case IPPROTO_AH:
+   if (*ext_hdrs & OFPIEH12_AUTH)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs &
+~(OFPIEH12_HOP | OFPIEH12_DEST | OFPIEH12_ROUTER |
+  IPPROTO_FRAGMENT | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_AUTH;
+   break;
+
+   case IPPROTO_DSTOPTS:
+   if (dest_options_header_count == 0) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_UNREP))
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   *ext_hdrs |= OFPIEH12_DEST;
+

[ovs-dev] [PATCH net-next v6] net: openvswitch: IPv6: Add IPv6 extension header support

2021-09-28 Thread Toms Atteka
This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Signed-off-by: Toms Atteka 
---
 include/uapi/linux/openvswitch.h |  12 +++
 net/openvswitch/flow.c   | 140 +++
 net/openvswitch/flow.h   |  14 
 net/openvswitch/flow_netlink.c   |  24 +-
 4 files changed, 189 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index a87b44cd5590..dc6eb5f6399f 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -346,6 +346,13 @@ enum ovs_key_attr {
 #ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
 #endif
+
+#ifndef __KERNEL__
+   PADDING,  /* Padding so kernel and non kernel field count would match */
+#endif
+
+   OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
+
__OVS_KEY_ATTR_MAX
 };
 
@@ -421,6 +428,11 @@ struct ovs_key_ipv6 {
__u8   ipv6_frag;   /* One of OVS_FRAG_TYPE_*. */
 };
 
+/* separate structure to support backward compatibility with older user space 
*/
+struct ovs_key_ipv6_exthdrs {
+   __u16  hdrs;
+};
+
 struct ovs_key_tcp {
__be16 tcp_src;
__be16 tcp_dst;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 9d375e74b607..28acb40437ca 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -239,6 +239,144 @@ static bool icmphdr_ok(struct sk_buff *skb)
  sizeof(struct icmphdr));
 }
 
+/**
+ * get_ipv6_ext_hdrs() - Parses packet and sets IPv6 extension header flags.
+ *
+ * @skb: buffer where extension header data starts in packet
+ * @nh: ipv6 header
+ * @ext_hdrs: flags are stored here
+ *
+ * OFPIEH12_UNREP is set if more than one of a given IPv6 extension header
+ * is unexpectedly encountered. (Two destination options headers may be
+ * expected and would not cause this bit to be set.)
+ *
+ * OFPIEH12_UNSEQ is set if IPv6 extension headers were not in the order
+ * preferred (but not required) by RFC 2460:
+ *
+ * When more than one extension header is used in the same packet, it is
+ * recommended that those headers appear in the following order:
+ *  IPv6 header
+ *  Hop-by-Hop Options header
+ *  Destination Options header
+ *  Routing header
+ *  Fragment header
+ *  Authentication header
+ *  Encapsulating Security Payload header
+ *  Destination Options header
+ *  upper-layer header
+ */
+static void get_ipv6_ext_hdrs(struct sk_buff *skb, struct ipv6hdr *nh,
+ u16 *ext_hdrs)
+{
+   u8 next_type = nh->nexthdr;
+   unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+   int dest_options_header_count = 0;
+
+   *ext_hdrs = 0;
+
+   while (ipv6_ext_hdr(next_type)) {
+   struct ipv6_opt_hdr _hdr, *hp;
+
+   switch (next_type) {
+   case IPPROTO_NONE:
+   *ext_hdrs |= OFPIEH12_NONEXT;
+   /* stop parsing */
+   return;
+
+   case IPPROTO_ESP:
+   if (*ext_hdrs & OFPIEH12_ESP)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs & ~(OFPIEH12_HOP | OFPIEH12_DEST |
+  OFPIEH12_ROUTER | IPPROTO_FRAGMENT |
+  OFPIEH12_AUTH | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_ESP;
+   break;
+
+   case IPPROTO_AH:
+   if (*ext_hdrs & OFPIEH12_AUTH)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs &
+~(OFPIEH12_HOP | OFPIEH12_DEST | OFPIEH12_ROUTER |
+  IPPROTO_FRAGMENT | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_AUTH;
+   break;
+
+   case IPPROTO_DSTOPTS:
+   if (dest_options_header_count == 0) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_UNREP))
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   *ext_hdrs |= OFPIEH12_DEST;
+   } else if (dest_options_header_count == 1) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_DEST |
+ OFPIEH12_ROUTER | OFPIEH12_FRAG |
+

[ovs-dev] [PATCH net-next v5] net: openvswitch: IPv6: Add IPv6 extension header support

2021-09-20 Thread Toms Atteka
This change adds a new OpenFlow field OFPXMT_OFB_IPV6_EXTHDR and
packets can be filtered using ipv6_ext flag.

Signed-off-by: Toms Atteka 
---
 include/uapi/linux/openvswitch.h |  12 +++
 net/openvswitch/flow.c   | 140 +++
 net/openvswitch/flow.h   |  14 
 net/openvswitch/flow_netlink.c   |  24 +-
 4 files changed, 189 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index a87b44cd5590..dc6eb5f6399f 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -346,6 +346,13 @@ enum ovs_key_attr {
 #ifdef __KERNEL__
OVS_KEY_ATTR_TUNNEL_INFO,  /* struct ip_tunnel_info */
 #endif
+
+#ifndef __KERNEL__
+   PADDING,  /* Padding so kernel and non kernel field count would match */
+#endif
+
+   OVS_KEY_ATTR_IPV6_EXTHDRS,  /* struct ovs_key_ipv6_exthdr */
+
__OVS_KEY_ATTR_MAX
 };
 
@@ -421,6 +428,11 @@ struct ovs_key_ipv6 {
__u8   ipv6_frag;   /* One of OVS_FRAG_TYPE_*. */
 };
 
+/* separate structure to support backward compatibility with older user space 
*/
+struct ovs_key_ipv6_exthdrs {
+   __u16  hdrs;
+};
+
 struct ovs_key_tcp {
__be16 tcp_src;
__be16 tcp_dst;
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 9d375e74b607..6c78169867fe 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -239,6 +239,144 @@ static bool icmphdr_ok(struct sk_buff *skb)
  sizeof(struct icmphdr));
 }
 
+/**
+ * Parses packet and sets IPv6 extension header flags.
+ *
+ * @skb: buffer where extension header data starts in packet
+ * @nh: ipv6 header
+ * @ext_hdrs: flags are stored here
+ *
+ * OFPIEH12_UNREP is set if more than one of a given IPv6 extension header
+ * is unexpectedly encountered. (Two destination options headers may be
+ * expected and would not cause this bit to be set.)
+ *
+ * OFPIEH12_UNSEQ is set if IPv6 extension headers were not in the order
+ * preferred (but not required) by RFC 2460:
+ *
+ * When more than one extension header is used in the same packet, it is
+ * recommended that those headers appear in the following order:
+ *  IPv6 header
+ *  Hop-by-Hop Options header
+ *  Destination Options header
+ *  Routing header
+ *  Fragment header
+ *  Authentication header
+ *  Encapsulating Security Payload header
+ *  Destination Options header
+ *  upper-layer header
+ */
+static void get_ipv6_ext_hdrs(struct sk_buff *skb, struct ipv6hdr *nh,
+ u16 *ext_hdrs)
+{
+   u8 next_type = nh->nexthdr;
+   unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+   int dest_options_header_count = 0;
+
+   *ext_hdrs = 0;
+
+   while (ipv6_ext_hdr(next_type)) {
+   struct ipv6_opt_hdr _hdr, *hp;
+
+   switch (next_type) {
+   case IPPROTO_NONE:
+   *ext_hdrs |= OFPIEH12_NONEXT;
+   /* stop parsing */
+   return;
+
+   case IPPROTO_ESP:
+   if (*ext_hdrs & OFPIEH12_ESP)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs & ~(OFPIEH12_HOP | OFPIEH12_DEST |
+  OFPIEH12_ROUTER | IPPROTO_FRAGMENT |
+  OFPIEH12_AUTH | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_ESP;
+   break;
+
+   case IPPROTO_AH:
+   if (*ext_hdrs & OFPIEH12_AUTH)
+   *ext_hdrs |= OFPIEH12_UNREP;
+   if ((*ext_hdrs &
+~(OFPIEH12_HOP | OFPIEH12_DEST | OFPIEH12_ROUTER |
+  IPPROTO_FRAGMENT | OFPIEH12_UNREP)) ||
+   dest_options_header_count >= 2) {
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   }
+   *ext_hdrs |= OFPIEH12_AUTH;
+   break;
+
+   case IPPROTO_DSTOPTS:
+   if (dest_options_header_count == 0) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_UNREP))
+   *ext_hdrs |= OFPIEH12_UNSEQ;
+   *ext_hdrs |= OFPIEH12_DEST;
+   } else if (dest_options_header_count == 1) {
+   if (*ext_hdrs &
+   ~(OFPIEH12_HOP | OFPIEH12_DEST |
+ OFPIEH12_ROUTER | OFPIEH12_FRAG |
+

[ovs-dev] [PATCH v4] netlink: removed incorrect optimization

2021-06-07 Thread Toms Atteka
This optimization caused FLOW_TNL_F_UDPIF flag not to be used in
hash calculation for geneve tunnel when revalidating flows which
resulted in different cache hash values and incorrect behaviour.

Added test to prevent regression.

CC: Jesse Gross 
Fixes: 6728d578f64e ("dpif-netdev: Translate Geneve options per-flow, not 
per-packet.")
Reported-at: https://github.com/vmware-tanzu/antrea/issues/897
Signed-off-by: Toms Atteka 
---
 lib/tun-metadata.c  |  2 +-
 tests/system-traffic.at | 54 +
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/lib/tun-metadata.c b/lib/tun-metadata.c
index c0b0ae044..af0bcbde8 100644
--- a/lib/tun-metadata.c
+++ b/lib/tun-metadata.c
@@ -828,7 +828,7 @@ tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
 } else {
 tun_metadata_to_geneve_nlattr_mask(key, tun, flow, b);
 }
-} else if (flow->metadata.present.len || is_mask) {
+} else {
 nl_msg_put_unspec(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
   tun->metadata.opts.gnv,
   flow->metadata.present.len);
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index fb5b9a36d..483cc7e83 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -574,6 +574,60 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 
10.1.1.100 | FORMAT_PI
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([datapath - ping over geneve tunnel, delete flow regression])
+OVS_CHECK_GENEVE()
+
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-underlay])
+
+AT_DATA([flows.txt], [dnl
+priority=100,icmp actions=resubmit(,10)
+priority=0 actions=NORMAL
+table=10, priority=100, ip, actions=ct(table=20,zone=65520)
+table=20, priority=200, ip, ct_state=-new+trk, actions=resubmit(,30)
+table=20, priority=100, ip, ct_state=+new, actions=resubmit(,30)
+table=20, priority=50, ip, actions=DROP
+table=30, priority=100, ip, actions=ct(commit,table=40,zone=65520)
+table=40, actions=normal
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
+
+ADD_NAMESPACES(at_ns0)
+
+dnl Set up underlay link from host into the namespace using veth pair.
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24")
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
+AT_CHECK([ip link set dev br-underlay up])
+
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
+dnl linux device inside the namespace.
+ADD_OVS_TUNNEL([geneve], [br0], [at_gnv0], [172.31.1.1], [10.1.1.100/24])
+ADD_NATIVE_TUNNEL([geneve], [ns_gnv0], [at_ns0], [172.31.1.100], [10.1.1.1/24],
+  [vni 0])
+
+dnl First, check the underlay
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], 
[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl ping over tunnel should work
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], 
[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+AT_CHECK([ovs-ofctl del-flows br0 "ct_state=+new"])
+
+dnl ping should not go through after removal of the flow
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], 
[0], [dnl
+7 packets transmitted, 0 received, 100% packet loss, time 0ms
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP(["/|ERR|/d
+/|WARN|/d"])
+AT_CLEANUP
+
 AT_SETUP([datapath - flow resume with geneve tun_metadata])
 OVS_CHECK_GENEVE()
 
-- 
2.25.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v3] netlink: removed incorrect optimization

2021-06-03 Thread Toms Atteka
This optimization caused FLOW_TNL_F_UDPIF flag not to be used in
hash calculation for geneve tunnel when revalidating flows which
resulted in different cache hash values and incorrect behaviour.

Added test to prevent regression.

Reported-at: https://github.com/vmware-tanzu/antrea/issues/897
Signed-off-by: Toms Atteka 
---
 lib/tun-metadata.c  |  2 +-
 tests/system-traffic.at | 54 +
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/lib/tun-metadata.c b/lib/tun-metadata.c
index c0b0ae044..af0bcbde8 100644
--- a/lib/tun-metadata.c
+++ b/lib/tun-metadata.c
@@ -828,7 +828,7 @@ tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
 } else {
 tun_metadata_to_geneve_nlattr_mask(key, tun, flow, b);
 }
-} else if (flow->metadata.present.len || is_mask) {
+} else {
 nl_msg_put_unspec(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
   tun->metadata.opts.gnv,
   flow->metadata.present.len);
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index fb5b9a36d..483cc7e83 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -574,6 +574,60 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 
10.1.1.100 | FORMAT_PI
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([datapath - ping over geneve tunnel, delete flow regression])
+OVS_CHECK_GENEVE()
+
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-underlay])
+
+AT_DATA([flows.txt], [dnl
+priority=100,icmp actions=resubmit(,10)
+priority=0 actions=NORMAL
+table=10, priority=100, ip, actions=ct(table=20,zone=65520)
+table=20, priority=200, ip, ct_state=-new+trk, actions=resubmit(,30)
+table=20, priority=100, ip, ct_state=+new, actions=resubmit(,30)
+table=20, priority=50, ip, actions=DROP
+table=30, priority=100, ip, actions=ct(commit,table=40,zone=65520)
+table=40, actions=normal
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
+
+ADD_NAMESPACES(at_ns0)
+
+dnl Set up underlay link from host into the namespace using veth pair.
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24")
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
+AT_CHECK([ip link set dev br-underlay up])
+
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
+dnl linux device inside the namespace.
+ADD_OVS_TUNNEL([geneve], [br0], [at_gnv0], [172.31.1.1], [10.1.1.100/24])
+ADD_NATIVE_TUNNEL([geneve], [ns_gnv0], [at_ns0], [172.31.1.100], [10.1.1.1/24],
+  [vni 0])
+
+dnl First, check the underlay
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], 
[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl ping over tunnel should work
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], 
[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+AT_CHECK([ovs-ofctl del-flows br0 "ct_state=+new"])
+
+dnl ping should not go through after removal of the flow
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], 
[0], [dnl
+7 packets transmitted, 0 received, 100% packet loss, time 0ms
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP(["/|ERR|/d
+/|WARN|/d"])
+AT_CLEANUP
+
 AT_SETUP([datapath - flow resume with geneve tun_metadata])
 OVS_CHECK_GENEVE()
 
-- 
2.25.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v2] netlink: removed incorrect optimization

2021-06-02 Thread Toms Atteka
This optimization caused FLOW_TNL_F_UDPIF flag not to be used in
hash calculation for geneve tunnel when revalidating flows which
resulted in different cache hash values and incorrect behaviour.

Added test to prevent regression.

Reported-at: https://github.com/vmware-tanzu/antrea/issues/897
Signed-off-by: Toms Atteka 
---
 lib/tun-metadata.c  |  2 +-
 tests/system-traffic.at | 54 +
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/lib/tun-metadata.c b/lib/tun-metadata.c
index c0b0ae044..828db72f5 100644
--- a/lib/tun-metadata.c
+++ b/lib/tun-metadata.c
@@ -828,7 +828,7 @@ tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
 } else {
 tun_metadata_to_geneve_nlattr_mask(key, tun, flow, b);
 }
-} else if (flow->metadata.present.len || is_mask) {
+} else { 
 nl_msg_put_unspec(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
   tun->metadata.opts.gnv,
   flow->metadata.present.len);
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index fb5b9a36d..483cc7e83 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -574,6 +574,60 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 
10.1.1.100 | FORMAT_PI
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([datapath - ping over geneve tunnel, delete flow regression])
+OVS_CHECK_GENEVE()
+
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-underlay])
+
+AT_DATA([flows.txt], [dnl
+priority=100,icmp actions=resubmit(,10)
+priority=0 actions=NORMAL
+table=10, priority=100, ip, actions=ct(table=20,zone=65520)
+table=20, priority=200, ip, ct_state=-new+trk, actions=resubmit(,30)
+table=20, priority=100, ip, ct_state=+new, actions=resubmit(,30)
+table=20, priority=50, ip, actions=DROP
+table=30, priority=100, ip, actions=ct(commit,table=40,zone=65520)
+table=40, actions=normal
+])
+
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
+
+ADD_NAMESPACES(at_ns0)
+
+dnl Set up underlay link from host into the namespace using veth pair.
+ADD_VETH(p0, at_ns0, br-underlay, "172.31.1.1/24")
+AT_CHECK([ip addr add dev br-underlay "172.31.1.100/24"])
+AT_CHECK([ip link set dev br-underlay up])
+
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
+dnl linux device inside the namespace.
+ADD_OVS_TUNNEL([geneve], [br0], [at_gnv0], [172.31.1.1], [10.1.1.100/24])
+ADD_NATIVE_TUNNEL([geneve], [ns_gnv0], [at_ns0], [172.31.1.100], [10.1.1.1/24],
+  [vni 0])
+
+dnl First, check the underlay
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 172.31.1.100 | FORMAT_PING], 
[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl ping over tunnel should work
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], 
[0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+AT_CHECK([ovs-ofctl del-flows br0 "ct_state=+new"])
+
+dnl ping should not go through after removal of the flow
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], 
[0], [dnl
+7 packets transmitted, 0 received, 100% packet loss, time 0ms
+])
+
+OVS_TRAFFIC_VSWITCHD_STOP(["/|ERR|/d
+/|WARN|/d"])
+AT_CLEANUP
+
 AT_SETUP([datapath - flow resume with geneve tun_metadata])
 OVS_CHECK_GENEVE()
 
-- 
2.25.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCHv2] netdev-afxdp: updated documentation

2020-12-07 Thread Toms Atteka
If system is missing ethtool, test fails silently.

Signed-off-by: Toms Atteka 
---
 Documentation/intro/install/afxdp.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/intro/install/afxdp.rst 
b/Documentation/intro/install/afxdp.rst
index 3c8f78825..f4b7cc4f9 100644
--- a/Documentation/intro/install/afxdp.rst
+++ b/Documentation/intro/install/afxdp.rst
@@ -167,6 +167,7 @@ Finally, build and install OVS::
 To kick start end-to-end autotesting::
 
   uname -a # make sure having 5.0+ kernel
+  ethtool --version # make sure ethtool is installed
   make check-afxdp TESTSUITEFLAGS='1'
 
 .. note::
-- 
2.25.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH] netdev-afxdp: updated documentation

2020-12-02 Thread Toms Atteka
If system is missing ethtool, test fails silently.

Signed-off-by: Toms Atteka 
---
 Documentation/intro/install/afxdp.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/intro/install/afxdp.rst 
b/Documentation/intro/install/afxdp.rst
index 3c8f78825..a597658e2 100644
--- a/Documentation/intro/install/afxdp.rst
+++ b/Documentation/intro/install/afxdp.rst
@@ -166,7 +166,7 @@ Finally, build and install OVS::
 
 To kick start end-to-end autotesting::
 
-  uname -a # make sure having 5.0+ kernel
+  uname -a # make sure having 5.0+ kernel and ethtool installed
   make check-afxdp TESTSUITEFLAGS='1'
 
 .. note::
-- 
2.25.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH] netlink: removed incorrect optimization

2020-11-20 Thread Toms Atteka
This optimization caused FLOW_TNL_F_UDPIF flag not to be used in
hash calculation for geneve tunnel when revalidating flows which
resulted in different cache hash values and incorrect behaviour.

Reported-at: https://github.com/vmware-tanzu/antrea/issues/897
Signed-off-by: Toms Atteka 
---
 lib/tun-metadata.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/tun-metadata.c b/lib/tun-metadata.c
index c0b0ae044..af0bcbde8 100644
--- a/lib/tun-metadata.c
+++ b/lib/tun-metadata.c
@@ -828,7 +828,7 @@ tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
 } else {
 tun_metadata_to_geneve_nlattr_mask(key, tun, flow, b);
 }
-} else if (flow->metadata.present.len || is_mask) {
+} else {
 nl_msg_put_unspec(b, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS,
   tun->metadata.opts.gnv,
   flow->metadata.present.len);
-- 
2.25.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCHv2] python: fixed package dependency

2020-07-22 Thread Toms Atteka
Python3 does not have python3-twisted-web. Required codebase is inside
python3-twisted.

Signed-off-by: Toms Atteka 
---
 debian/control | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/debian/control b/debian/control
index 0646b22a1..6420b9d3e 100644
--- a/debian/control
+++ b/debian/control
@@ -188,7 +188,7 @@ Description: Python bindings for Open vSwitch
 Package: openvswitch-test
 Architecture: all
 Depends: python3,
- python3-twisted-web,
+ python3-twisted,
  ${misc:Depends},
  ${python3:Depends}
 Description: Open vSwitch test package
-- 
2.17.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH] python: fixed package dependency

2020-07-22 Thread Toms Atteka
From: Toms Atteka 

Python3 does not have python3-twisted-web. Required codebase is inside
python3-twisted.

Signed-off-by: Toms Atteka 
---
 debian/control | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/debian/control b/debian/control
index 0646b22a1..6420b9d3e 100644
--- a/debian/control
+++ b/debian/control
@@ -188,7 +188,7 @@ Description: Python bindings for Open vSwitch
 Package: openvswitch-test
 Architecture: all
 Depends: python3,
- python3-twisted-web,
+ python3-twisted,
  ${misc:Depends},
  ${python3:Depends}
 Description: Open vSwitch test package
-- 
2.17.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCHv2] odp-util: extend usage of limit for parse functions

2019-05-09 Thread Toms Atteka
This fixes stack overflow issues for odp_actions_from_string.
Added wrapper functions for recursion limitation.

Basic manual testing was performed.

Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=13808
Signed-off-by: Toms Atteka 

v1->v2: added wrapper functions
---
 lib/odp-util.c | 96 --
 1 file changed, 70 insertions(+), 26 deletions(-)

diff --git a/lib/odp-util.c b/lib/odp-util.c
index 1b2347d6f..3a28877e3 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -67,6 +67,10 @@ struct parse_odp_context {
 
 static int parse_odp_key_mask_attr(struct parse_odp_context *, const char *,
struct ofpbuf *, struct ofpbuf *);
+
+static int parse_odp_key_mask_attr__(struct parse_odp_context *, const char *,
+   struct ofpbuf *, struct ofpbuf *);
+
 static void format_odp_key_attr(const struct nlattr *a,
 const struct nlattr *ma,
 const struct hmap *portno_names, struct ds *ds,
@@ -90,7 +94,10 @@ static void format_u128(struct ds *d, const 
ovs_32aligned_u128 *key,
 const ovs_32aligned_u128 *mask, bool verbose);
 static int scan_u128(const char *s, ovs_u128 *value, ovs_u128 *mask);
 
-static int parse_odp_action(const char *s, const struct simap *port_names,
+static int parse_odp_action(struct parse_odp_context *context, const char *s,
+struct ofpbuf *actions);
+
+static int parse_odp_action__(struct parse_odp_context *context, const char *s,
 struct ofpbuf *actions);
 
 /* Returns one the following for the action with the given OVS_ACTION_ATTR_*
@@ -2183,7 +2190,7 @@ out:
 }
 
 static int
-parse_action_list(const char *s, const struct simap *port_names,
+parse_action_list(struct parse_odp_context *context, const char *s,
   struct ofpbuf *actions)
 {
 int n = 0;
@@ -2195,7 +2202,7 @@ parse_action_list(const char *s, const struct simap 
*port_names,
 if (s[n] == ')') {
 break;
 }
-retval = parse_odp_action(s + n, port_names, actions);
+retval = parse_odp_action(context, s + n, actions);
 if (retval < 0) {
 return retval;
 }
@@ -2209,9 +2216,30 @@ parse_action_list(const char *s, const struct simap 
*port_names,
 return n;
 }
 
+
 static int
-parse_odp_action(const char *s, const struct simap *port_names,
+parse_odp_action(struct parse_odp_context *context, const char *s,
  struct ofpbuf *actions)
+{
+int retval;
+
+context->depth++;
+
+if (context->depth == MAX_ODP_NESTED) {
+retval = -EINVAL;
+} else {
+retval = parse_odp_action__(context, s, actions);
+}
+
+context->depth--;
+
+return retval;
+}
+
+
+static int
+parse_odp_action__(struct parse_odp_context *context, const char *s,
+   struct ofpbuf *actions)
 {
 {
 uint32_t port;
@@ -2237,11 +2265,11 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 }
 }
 
-if (port_names) {
+if (context->port_names) {
 int len = strcspn(s, delimiters);
 struct simap_node *node;
 
-node = simap_find_len(port_names, s, len);
+node = simap_find_len(context->port_names, s, len);
 if (node) {
 nl_msg_put_u32(actions, OVS_ACTION_ATTR_OUTPUT, node->data);
 return len;
@@ -2269,12 +2297,9 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 struct ofpbuf maskbuf = OFPBUF_STUB_INITIALIZER(mask);
 struct nlattr *nested, *key;
 size_t size;
-struct parse_odp_context context = (struct parse_odp_context) {
-.port_names = port_names,
-};
 
 start_ofs = nl_msg_start_nested(actions, OVS_ACTION_ATTR_SET);
-retval = parse_odp_key_mask_attr(, s + 4, actions, );
+retval = parse_odp_key_mask_attr(context, s + 4, actions, );
 if (retval < 0) {
 ofpbuf_uninit();
 return retval;
@@ -2376,9 +2401,11 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 
 actions_ofs = nl_msg_start_nested(actions,
   OVS_SAMPLE_ATTR_ACTIONS);
-int retval = parse_action_list(s + n, port_names, actions);
-if (retval < 0)
+int retval = parse_action_list(context, s + n, actions);
+if (retval < 0) {
 return retval;
+}
+
 
 n += retval;
 nl_msg_end_nested(actions, actions_ofs);
@@ -2394,7 +2421,7 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 int n = 6;
 
 actions_ofs = nl_msg_start_nested(actions, OVS_ACTION_ATTR_CLONE);
-int retval = parse_action_list(s + n, port_names, actions);
+ 

[ovs-dev] [PATCH] odp-util: extend usage of limit for parse functions

2019-05-08 Thread Toms Atteka
This fixes stack overflow issues for odp_actions_from_string.
As well moved depth check inside parse_odp_key_mask_attr to beginning.
Added some missing depth reductions.

Basic manual testing was performed.

Reported-by:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=13808
Signed-off-by: Toms Atteka 
---
 lib/odp-util.c | 89 --
 1 file changed, 65 insertions(+), 24 deletions(-)

diff --git a/lib/odp-util.c b/lib/odp-util.c
index 1b2347d6f..fc85c6123 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -90,7 +90,7 @@ static void format_u128(struct ds *d, const 
ovs_32aligned_u128 *key,
 const ovs_32aligned_u128 *mask, bool verbose);
 static int scan_u128(const char *s, ovs_u128 *value, ovs_u128 *mask);
 
-static int parse_odp_action(const char *s, const struct simap *port_names,
+static int parse_odp_action(struct parse_odp_context *context, const char *s,
 struct ofpbuf *actions);
 
 /* Returns one the following for the action with the given OVS_ACTION_ATTR_*
@@ -2183,7 +2183,7 @@ out:
 }
 
 static int
-parse_action_list(const char *s, const struct simap *port_names,
+parse_action_list(struct parse_odp_context *context, const char *s,
   struct ofpbuf *actions)
 {
 int n = 0;
@@ -2195,7 +2195,7 @@ parse_action_list(const char *s, const struct simap 
*port_names,
 if (s[n] == ')') {
 break;
 }
-retval = parse_odp_action(s + n, port_names, actions);
+retval = parse_odp_action(context, s + n, actions);
 if (retval < 0) {
 return retval;
 }
@@ -2210,15 +2210,21 @@ parse_action_list(const char *s, const struct simap 
*port_names,
 }
 
 static int
-parse_odp_action(const char *s, const struct simap *port_names,
+parse_odp_action(struct parse_odp_context *context, const char *s,
  struct ofpbuf *actions)
 {
+if (context->depth + 1 == MAX_ODP_NESTED) {
+return -EINVAL;
+}
+context->depth++;
+
 {
 uint32_t port;
 int n;
 
 if (ovs_scan(s, "%"SCNi32"%n", , )) {
 nl_msg_put_u32(actions, OVS_ACTION_ATTR_OUTPUT, port);
+context->depth--;
 return n;
 }
 }
@@ -2233,17 +2239,19 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 trunc = nl_msg_put_unspec_uninit(actions,
  OVS_ACTION_ATTR_TRUNC, sizeof *trunc);
 trunc->max_len = max_len;
+context->depth--;
 return n;
 }
 }
 
-if (port_names) {
+if (context->port_names) {
 int len = strcspn(s, delimiters);
 struct simap_node *node;
 
-node = simap_find_len(port_names, s, len);
+node = simap_find_len(context->port_names, s, len);
 if (node) {
 nl_msg_put_u32(actions, OVS_ACTION_ATTR_OUTPUT, node->data);
+context->depth--;
 return len;
 }
 }
@@ -2254,11 +2262,13 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 
 if (ovs_scan(s, "recirc(%"PRIu32")%n", _id, )) {
 nl_msg_put_u32(actions, OVS_ACTION_ATTR_RECIRC, recirc_id);
+context->depth--;
 return n;
 }
 }
 
 if (!strncmp(s, "userspace(", 10)) {
+context->depth--;
 return parse_odp_userspace_action(s, actions);
 }
 
@@ -2269,18 +2279,17 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 struct ofpbuf maskbuf = OFPBUF_STUB_INITIALIZER(mask);
 struct nlattr *nested, *key;
 size_t size;
-struct parse_odp_context context = (struct parse_odp_context) {
-.port_names = port_names,
-};
 
 start_ofs = nl_msg_start_nested(actions, OVS_ACTION_ATTR_SET);
-retval = parse_odp_key_mask_attr(, s + 4, actions, );
+retval = parse_odp_key_mask_attr(context, s + 4, actions, );
 if (retval < 0) {
 ofpbuf_uninit();
+context->depth--;
 return retval;
 }
 if (s[retval + 4] != ')') {
 ofpbuf_uninit();
+context->depth--;
 return -EINVAL;
 }
 
@@ -2311,6 +2320,7 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 ofpbuf_uninit();
 
 nl_msg_end_nested(actions, start_ofs);
+context->depth--;
 return retval + 5;
 }
 
@@ -2330,6 +2340,7 @@ parse_odp_action(const char *s, const struct simap 
*port_names,
 , , , , )) {
 if ((vid & ~(VLAN_VID_MASK >> VLAN_VID_SHIFT)) != 0
 || (pcp & ~(VLAN_PCP_MASK >> VLAN_PCP_SHIFT)) != 0) {
+context->depth--;
 return -EINVAL;
 }
 push.vlan_tpid = htons(tpid)

[ovs-dev] [PATCH] oss-fuzz: fixed wrong lib path

2019-04-30 Thread Toms Atteka
the logical-fields.h file was moved. Path has been updated
accordingly. This broke oss-fuzz buils.

Signed-off-by: Toms Atteka 
---
 tests/oss-fuzz/expr_parse_target.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/oss-fuzz/expr_parse_target.c 
b/tests/oss-fuzz/expr_parse_target.c
index 1a3893858..1fdd3895b 100644
--- a/tests/oss-fuzz/expr_parse_target.c
+++ b/tests/oss-fuzz/expr_parse_target.c
@@ -16,7 +16,7 @@
 #include "ovn/actions.h"
 #include "ovn/expr.h"
 #include "ovn/lex.h"
-#include "ovn/lib/logical-fields.h"
+#include "ovn/logical-fields.h"
 #include "ovn/lib/ovn-l7.h"
 #include "ovn/lib/extend-table.h"
 #include "openvswitch/shash.h"
-- 
2.17.1

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCHv2] lib: added check to prevent int overflow

2019-03-20 Thread Toms Atteka
If enough large input is given ofpact_finish will fail.
Implemented ofpbuf_oversized function to check for oversized
buffer. Checks were added for parse functions and error messages
returned.

Basic manual testing performed.

Reported-by:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12972
Signed-off-by: Toms Atteka 

v1->v2: added over sized check as a separate function and added
checks for other parse functions where they might fail.
---
 include/openvswitch/ofpbuf.h |  6 ++
 lib/bundle.c |  5 +
 lib/learn.c  |  5 +
 lib/ofp-actions.c| 29 +
 4 files changed, 45 insertions(+)

diff --git a/include/openvswitch/ofpbuf.h b/include/openvswitch/ofpbuf.h
index e4cf088..1136ba0 100644
--- a/include/openvswitch/ofpbuf.h
+++ b/include/openvswitch/ofpbuf.h
@@ -162,6 +162,7 @@ char *ofpbuf_to_string(const struct ofpbuf *, size_t 
maxbytes);
 static inline struct ofpbuf *ofpbuf_from_list(const struct ovs_list *);
 void ofpbuf_list_delete(struct ovs_list *);
 static inline bool ofpbuf_equal(const struct ofpbuf *, const struct ofpbuf *);
+static inline bool ofpbuf_oversized(const struct ofpbuf *ofpacts);
 
 
 /* Frees memory that 'b' points to, as well as 'b' itself. */
@@ -272,6 +273,11 @@ static inline bool ofpbuf_equal(const struct ofpbuf *a, 
const struct ofpbuf *b)
memcmp(a->data, b->data, a->size) == 0;
 }
 
+static inline bool ofpbuf_oversized(const struct ofpbuf *ofpacts)
+{
+return (char *)ofpbuf_tail(ofpacts) - (char *)ofpacts->header > UINT16_MAX;
+}
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/lib/bundle.c b/lib/bundle.c
index 558e890..edb11f6 100644
--- a/lib/bundle.c
+++ b/lib/bundle.c
@@ -183,6 +183,11 @@ bundle_parse__(const char *s, const struct 
ofputil_port_map *port_map,
 bundle = ofpacts->header;
 bundle->n_slaves++;
 }
+
+if (ofpbuf_oversized(ofpacts)) {
+return xasprintf("input too big");
+}
+
 ofpact_finish_BUNDLE(ofpacts, );
 bundle->basis = atoi(basis);
 
diff --git a/lib/learn.c b/lib/learn.c
index 642ce18..a40209e 100644
--- a/lib/learn.c
+++ b/lib/learn.c
@@ -455,6 +455,11 @@ learn_parse__(char *orig, char *arg, const struct 
ofputil_port_map *port_map,
 learn = ofpacts->header;
 }
 }
+
+if (ofpbuf_oversized(ofpacts)) {
+return xasprintf("input too big");
+}
+
 ofpact_finish_LEARN(ofpacts, );
 
 return NULL;
diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c
index e8e88ac..1340614 100644
--- a/lib/ofp-actions.c
+++ b/lib/ofp-actions.c
@@ -989,6 +989,11 @@ parse_CONTROLLER(char *arg, const struct 
ofpact_parse_params *pp)
 controller = pp->ofpacts->header;
 controller->userdata_len = userdata_len;
 }
+
+if (ofpbuf_oversized(pp->ofpacts)) {
+return xasprintf("input too big");
+}
+
 ofpact_finish_CONTROLLER(pp->ofpacts, );
 }
 
@@ -3690,6 +3695,11 @@ parse_DEC_TTL(char *arg, const struct 
ofpact_parse_params *pp)
 return xstrdup("dec_ttl_cnt_ids: expected at least one controller "
"id.");
 }
+
+if (ofpbuf_oversized(pp->ofpacts)) {
+return xasprintf("input too big");
+}
+
 ofpact_finish_DEC_TTL(pp->ofpacts, );
 }
 return NULL;
@@ -4443,6 +4453,11 @@ parse_ENCAP(char *arg, const struct ofpact_parse_params 
*pp)
 /* ofpbuf may have been re-allocated. */
 encap = pp->ofpacts->header;
 encap->n_props = n_props;
+
+if (ofpbuf_oversized(pp->ofpacts)) {
+return xasprintf("input too big");
+}
+
 ofpact_finish_ENCAP(pp->ofpacts, );
 return NULL;
 }
@@ -5772,6 +5787,11 @@ parse_NOTE(const char *arg, const struct 
ofpact_parse_params *pp)
 struct ofpact_note *note = ofpbuf_at_assert(pp->ofpacts, start_ofs,
 sizeof *note);
 note->length = pp->ofpacts->size - (start_ofs + sizeof *note);
+
+if (ofpbuf_oversized(pp->ofpacts)) {
+return xasprintf("input too big");
+}
+
 ofpact_finish_NOTE(pp->ofpacts, );
 return NULL;
 }
@@ -5929,6 +5949,10 @@ parse_CLONE(char *arg, const struct ofpact_parse_params 
*pp)
 pp->ofpacts->header = ofpbuf_push_uninit(pp->ofpacts, sizeof *clone);
 clone = pp->ofpacts->header;
 
+if (ofpbuf_oversized(pp->ofpacts)) {
+return xasprintf("input too big");
+}
+
 ofpact_finish_CLONE(pp->ofpacts, );
 ofpbuf_push_uninit(pp->ofpacts, clone_offset);
 return error;
@@ -6615,6 +6639,11 @@ parse_CT(char *arg, const struct ofpact_parse_params *pp)
 if (!error && oc->flags & NX_CT_F_FORCE && !(oc->flags & NX_CT_F_COMMIT)) {
 error = xasprintf("

[ovs-dev] [PATCH] odp-util: added NULL check for error pointer argument

2019-03-18 Thread Toms Atteka
If NULL value was provided for odp_flow_from_string errorp argument
segmentation fault error occurred.

This patch fixes it by ignoring error formatting if error pointer
is not provided.

Reported-at:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12972
Signed-off-by: Toms Atteka 
---
 lib/odp-util.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/lib/odp-util.c b/lib/odp-util.c
index 8bcbd2c..0716161 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -5725,7 +5725,9 @@ odp_flow_from_string(const char *s, const struct simap 
*port_names,
  struct ofpbuf *key, struct ofpbuf *mask,
  char **errorp)
 {
-*errorp = NULL;
+if (errorp) {
+*errorp = NULL;
+}
 
 const size_t old_size = key->size;
 struct parse_odp_context context = (struct parse_odp_context) {
@@ -5743,7 +5745,9 @@ odp_flow_from_string(const char *s, const struct simap 
*port_names,
 ovs_u128 ufid;
 retval = odp_ufid_from_string(s, );
 if (retval < 0) {
-*errorp = xasprintf("syntax error at %s", s);
+if (errorp) {
+*errorp = xasprintf("syntax error at %s", s);
+}
 key->size = old_size;
 return -retval;
 } else if (retval > 0) {
@@ -5753,7 +5757,9 @@ odp_flow_from_string(const char *s, const struct simap 
*port_names,
 
 retval = parse_odp_key_mask_attr(, s, key, mask);
 if (retval < 0) {
-*errorp = xasprintf("syntax error at %s", s);
+if (errorp) {
+*errorp = xasprintf("syntax error at %s", s);
+}
 key->size = old_size;
 return -retval;
 }
-- 
2.7.4

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH] lib: added check to prevent int overflow

2019-03-12 Thread Toms Atteka
If enough large input is given ofpact_finish will fail.
Check was added and error message returned.

Basic manual testing performed.

Reported-by:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12972
Signed-off-by: Toms Atteka 
---
 lib/learn.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/lib/learn.c b/lib/learn.c
index 642ce18..5b168e4 100644
--- a/lib/learn.c
+++ b/lib/learn.c
@@ -455,6 +455,11 @@ learn_parse__(char *orig, char *arg, const struct 
ofputil_port_map *port_map,
 learn = ofpacts->header;
 }
 }
+
+if ((char *)ofpbuf_tail(ofpacts) - (char *)ofpacts->header > UINT16_MAX) {
+return xasprintf("input too big");
+}
+
 ofpact_finish_LEARN(ofpacts, );
 
 return NULL;
-- 
2.7.4

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCHv3] netlink: added check to prevent netlink attribute overflow

2019-02-19 Thread Toms Atteka
If enough large input is passed to odp_actions_from_string it can
cause netlink attribute to overflow.
Check for buffer size was added to prevent entering this function
and returning appropriate error code.

Basic manual testing was performed.

Reported-by:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12231
Signed-off-by: Toms Atteka 
---
 lib/odp-util.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/lib/odp-util.c b/lib/odp-util.c
index e893f46..e288ae8 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -2161,6 +2161,10 @@ parse_action_list(const char *s, const struct simap 
*port_names,
 n += retval;
 }
 
+if (actions->size > UINT16_MAX) {
+return -EFBIG;
+}
+
 return n;
 }
 
-- 
2.7.4

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCHv2] netlink: added check to prevent netlink attribute overflow

2019-02-19 Thread Toms Atteka
If enough large input is passed to odp_actions_from_string it can
cause netlink attribute to overflow.
ovs_assert was added just before the problematic code so it could
be debugged faster in similar cases if they would arise. Check
for buffer size was added to prevent entering this function and
returning appropriate error code.

Basic manual testing was performed.

Reported-by:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12231
Signed-off-by: Toms Atteka 
---
 lib/odp-util.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/lib/odp-util.c b/lib/odp-util.c
index e893f46..e288ae8 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -2161,6 +2161,10 @@ parse_action_list(const char *s, const struct simap 
*port_names,
 n += retval;
 }
 
+if (actions->size > UINT16_MAX) {
+return -EFBIG;
+}
+
 return n;
 }
 
-- 
2.7.4

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH] netlink: added check to prevent netlink attribute overflow

2019-02-11 Thread Toms Atteka
If enough large input is passed to odp_actions_from_string it can
cause netlink attribute to overflow.
ovs_assert was added just before the problematic code so it could
be debugged faster in similar cases if they would arise. Check
for buffer size was added to prevent entering this function and
returning appropriate error code.

Basic manual testing was performed.

Reported-by:
https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12231
Signed-off-by: Toms Atteka 
---
 lib/netlink.c  | 1 +
 lib/odp-util.c | 4 
 2 files changed, 5 insertions(+)

diff --git a/lib/netlink.c b/lib/netlink.c
index de3ebcd..c91c868 100644
--- a/lib/netlink.c
+++ b/lib/netlink.c
@@ -498,6 +498,7 @@ void
 nl_msg_end_nested(struct ofpbuf *msg, size_t offset)
 {
 struct nlattr *attr = ofpbuf_at_assert(msg, offset, sizeof *attr);
+ovs_assert(msg->size - offset <= USHRT_MAX);
 attr->nla_len = msg->size - offset;
 }
 
diff --git a/lib/odp-util.c b/lib/odp-util.c
index e893f46..9f637ca 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -2161,6 +2161,10 @@ parse_action_list(const char *s, const struct simap 
*port_names,
 n += retval;
 }
 
+if (actions->size > USHRT_MAX) {
+return -EFBIG;
+}
+
 return n;
 }
 
-- 
2.7.4

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH] ofpbuf: fixed a bug in ofpbuf_insert

2019-01-18 Thread Toms Atteka
memmove byte count was calculated incorrectly as ofpbuf_put_uninit
is increasing b->size by n.

This patch fixes it by deducing byte count by n.

Reported-at: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=12296
Signed-off-by: Toms Atteka 
---
 lib/ofpbuf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/ofpbuf.c b/lib/ofpbuf.c
index 9c06236..91a5295 100644
--- a/lib/ofpbuf.c
+++ b/lib/ofpbuf.c
@@ -469,9 +469,9 @@ void
 ofpbuf_insert(struct ofpbuf *b, size_t offset, const void *data, size_t n)
 {
 if (offset < b->size) {
-ofpbuf_put_uninit(b, n);
+ofpbuf_put_uninit(b, n); // b->size gets increased
 memmove((char *) b->data + offset + n, (char *) b->data + offset,
-b->size - offset);
+b->size - offset - n);
 memcpy((char *) b->data + offset, data, n);
 } else {
 ovs_assert(offset == b->size);
-- 
2.7.4

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH] python: add OVSDB IDL tutorial with examples

2018-07-09 Thread Toms Atteka
created tutorial on how to use OVSDB IDL Python library

Signed-off-by: Toms Atteka 
---
 Documentation/automake.mk|   1 +
 Documentation/index.rst  |   1 +
 Documentation/tutorials/index.rst|   1 +
 Documentation/tutorials/ovsdb-idl-python.rst | 285 +++
 4 files changed, 288 insertions(+)
 create mode 100644 Documentation/tutorials/ovsdb-idl-python.rst

diff --git a/Documentation/automake.mk b/Documentation/automake.mk
index 2444794..34b6d32 100644
--- a/Documentation/automake.mk
+++ b/Documentation/automake.mk
@@ -28,6 +28,7 @@ DOC_SOURCE = \
Documentation/tutorials/ovn-openstack.rst \
Documentation/tutorials/ovn-sandbox.rst \
Documentation/tutorials/ovs-conntrack.rst \
+   Documentation/tutorials/ovsdb-idl-python.rst \
Documentation/topics/index.rst \
Documentation/topics/bonding.rst \
Documentation/topics/idl-compound-indexes.rst \
diff --git a/Documentation/index.rst b/Documentation/index.rst
index 06602f7..e55fcd3 100644
--- a/Documentation/index.rst
+++ b/Documentation/index.rst
@@ -66,6 +66,7 @@ vSwitch? Start here.
   :doc:`tutorials/ovn-sandbox` |
   :doc:`tutorials/ovn-openstack` |
   :doc:`tutorials/ovs-conntrack`
+  :doc:`tutorials/ovsdb-idl-python`
 
 Deeper Dive
 ---
diff --git a/Documentation/tutorials/index.rst 
b/Documentation/tutorials/index.rst
index ab90b7c..4fbb41e 100644
--- a/Documentation/tutorials/index.rst
+++ b/Documentation/tutorials/index.rst
@@ -44,3 +44,4 @@ vSwitch.
ovn-sandbox
ovn-openstack
ovs-conntrack
+   ovsdb-idl-python
diff --git a/Documentation/tutorials/ovsdb-idl-python.rst 
b/Documentation/tutorials/ovsdb-idl-python.rst
new file mode 100644
index 000..894c6f8
--- /dev/null
+++ b/Documentation/tutorials/ovsdb-idl-python.rst
@@ -0,0 +1,285 @@
+..
+  Licensed under the Apache License, Version 2.0 (the "License"); you may
+  not use this file except in compliance with the License. You may obtain
+  a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+  License for the specific language governing permissions and limitations
+  under the License.
+
+  Convention for heading levels in Open vSwitch documentation:
+
+  ===  Heading 0 (reserved for the title in a document)
+  ---  Heading 1
+  ~~~  Heading 2
+  +++  Heading 3
+  '''  Heading 4
+
+  Avoid deeper levels because they do not render well.
+
+
+OVSDB IDL Python Library
+
+
+OVSDB Interface Definition Language Python Library allows manipulation of OVS
+instance through its definition inside DB file.
+
+This tutorial will provide basic sample on how to use library. Description on
+how particular parts work are added in comments in the code.
+
+Insert Bridge
+-
+
+This is a simple example to show how to insert bridge in OVSDB. Main thing is
+to understand that bridge should be inserted inside Open_vSwitch table not
+Bridge table. Bridges which are not inside Open_vSwitch gets automatically
+removed.::
+
+#! /usr/bin/env python
+
+import six
+import ovs.db.idl
+
+print("insert bridge example")
+
+# define schema helper which will hold OVS DB structure
+schema_helper = ovs.db.idl.SchemaHelper(
+"/usr/share/openvswitch/vswitch.ovsschema"
+)
+# define which parts of schema we are interested in
+schema_helper.register_columns(
+"Open_vSwitch", ["bridges"]
+)
+schema_helper.register_columns(
+"Bridge", ["name", "fail_mode"]
+)
+
+# define whether we want use UNIX socket or IP protocol
+# remote = 'unix:/run/openvswitch/db.sock'
+remote = 'tcp:127.0.0.1:12345'
+
+# initialize DB object
+idl = ovs.db.idl.Idl(remote, schema_helper)
+
+# pull initial DB
+# must be performed before any transaction
+seq_no = idl.change_seqno
+while True:
+idl.run()
+
+if seq_no == idl.change_seqno:
+poller = ovs.poller.Poller()
+idl.wait(poller)
+poller.block()
+continue
+
+seq_no = idl.change_seqno
+break
+
+# start transaction
+# action can only be done within transactions
+# multiple actions can be done in transactions
+txn = ovs.db.idl.Transaction(idl)
+
+# create bridge row
+bridge = txn.insert(idl.tables["Bridge"])
+# specify unique name for bridge
+bridge.name = "Main Bridge"
+# other bridge fields can be specified here as well
+bridge.fail_mode = "secure"

[ovs-dev] [PATCH 2/2] python: add OVSDB IDL tutorial with examples

2018-07-09 Thread Toms Atteka
created tutorial on how to use OVSDB IDL Python library

Signed-off-by: Toms Atteka 
---
 Documentation/automake.mk|   1 +
 Documentation/tutorials/ovsdb-idl-python.rst | 284 +++
 2 files changed, 285 insertions(+)
 create mode 100644 Documentation/tutorials/ovsdb-idl-python.rst

diff --git a/Documentation/automake.mk b/Documentation/automake.mk
index 2444794..34b6d32 100644
--- a/Documentation/automake.mk
+++ b/Documentation/automake.mk
@@ -28,6 +28,7 @@ DOC_SOURCE = \
Documentation/tutorials/ovn-openstack.rst \
Documentation/tutorials/ovn-sandbox.rst \
Documentation/tutorials/ovs-conntrack.rst \
+   Documentation/tutorials/ovsdb-idl-python.rst \
Documentation/topics/index.rst \
Documentation/topics/bonding.rst \
Documentation/topics/idl-compound-indexes.rst \
diff --git a/Documentation/tutorials/ovsdb-idl-python.rst 
b/Documentation/tutorials/ovsdb-idl-python.rst
new file mode 100644
index 000..ba1aada
--- /dev/null
+++ b/Documentation/tutorials/ovsdb-idl-python.rst
@@ -0,0 +1,284 @@
+..
+  Licensed under the Apache License, Version 2.0 (the "License"); you may
+  not use this file except in compliance with the License. You may obtain
+  a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+  License for the specific language governing permissions and limitations
+  under the License.
+
+  Convention for heading levels in Open vSwitch documentation:
+
+  ===  Heading 0 (reserved for the title in a document)
+  ---  Heading 1
+  ~~~  Heading 2
+  +++  Heading 3
+  '''  Heading 4
+
+  Avoid deeper levels because they do not render well.
+
+
+OVSDB IDL Python Library
+
+
+OVSDB Interface Definition Language Python Library allows manipulation of OVS
+instance through its definition inside DB file.
+
+This tutorial will provide basic sample on how to use library. Description on
+how particular parts work are added in comments in the code.
+
+Insert Bridge
+-
+
+This is a simple example to show how to insert bridge in OVSDB. Main thing is 
to
+understand that bridge should be inserted inside Open_vSwitch table not Bridge
+table. Bridges which are not inside Open_vSwitch gets automatically removed.::
+
+#! /usr/bin/env python
+
+import six
+import ovs.db.idl
+
+print("insert bridge example")
+
+# define schema helper which will hold OVS DB structure
+schema_helper = ovs.db.idl.SchemaHelper(
+"/usr/share/openvswitch/vswitch.ovsschema"
+)
+# define which parts of schema we are interested in
+schema_helper.register_columns(
+"Open_vSwitch", ["bridges"]
+)
+schema_helper.register_columns(
+"Bridge", ["name", "fail_mode"]
+)
+
+# define whether we want use UNIX socket or IP protocol
+# remote = 'unix:/run/openvswitch/db.sock'
+remote = 'tcp:127.0.0.1:12345'
+
+# initialize DB object
+idl = ovs.db.idl.Idl(remote, schema_helper)
+
+# pull initial DB
+# must be performed before any transaction
+seq_no = idl.change_seqno
+while True:
+idl.run()
+
+if seq_no == idl.change_seqno:
+poller = ovs.poller.Poller()
+idl.wait(poller)
+poller.block()
+continue
+
+seq_no = idl.change_seqno
+break
+
+# start transaction
+# action can only be done within transactions
+# multiple actions can be done in transactions
+txn = ovs.db.idl.Transaction(idl)
+
+# create bridge row
+bridge = txn.insert(idl.tables["Bridge"])
+# specify unique name for bridge
+bridge.name = "Main Bridge"
+# other bridge fields can be specified here as well
+bridge.fail_mode = "secure"
+
+# bridge gets stored inside Open_vSwitch table
+row = six.next(six.itervalues(idl.tables["Open_vSwitch"].rows))
+
+# appending directly won't work:
+# row.bridges.append(s)
+# need to create new list
+bridges = row.bridges
+bridges.append(bridge)
+row.bridges = bridges
+
+# store changes in DB
+txn.commit_block()
+
+idl.close()
+
+Delete Bridges
+--
+
+This is a simple example to show how to delete bridges from OVSDB::
+
+#! /usr/bin/env python
+
+import six
+import ovs.db.idl
+
+print("delete empty bridges example")
+
+# define schema helper which will hold OVS DB structure
+schema_helper = ovs.db.idl.SchemaHelper(
+"/usr/share/openvswit

[ovs-dev] [PATCH] python: add IDL examples

2018-06-17 Thread Toms Atteka
created sample python scripts, which helps to learn how to use OVSDB library

Signed-off-by: Toms Atteka 
---
 python/howto/IDL/delete_bridges.py |  70 +
 python/howto/IDL/insert_bridge.py  |  75 +++
 python/howto/IDL/ovs_monitor.py| 102 +
 3 files changed, 247 insertions(+)
 create mode 100755 python/howto/IDL/delete_bridges.py
 create mode 100755 python/howto/IDL/insert_bridge.py
 create mode 100755 python/howto/IDL/ovs_monitor.py

diff --git a/python/howto/IDL/delete_bridges.py 
b/python/howto/IDL/delete_bridges.py
new file mode 100755
index 000..ff24107
--- /dev/null
+++ b/python/howto/IDL/delete_bridges.py
@@ -0,0 +1,70 @@
+#! /usr/bin/env python
+
+# This is a simple example to show how to delete bridges from OVSDB.
+
+import six
+import ovs.db.idl
+
+print("delete empty bridges example")
+
+# define schema helper which will hold OVS DB structure
+schema_helper = ovs.db.idl.SchemaHelper(
+"/usr/share/openvswitch/vswitch.ovsschema"
+)
+# define which parts of schema we are interested in
+schema_helper.register_columns(
+"Open_vSwitch", ["bridges"]
+)
+schema_helper.register_columns(
+"Bridge", ["name", "ports"]
+)
+schema_helper.register_columns(
+"Port", []
+)
+
+# define whether we want use UNIX socket or IP protocol
+# remote = 'unix:/run/openvswitch/db.sock'
+remote = 'tcp:127.0.0.1:12345'
+
+# initialize DB object
+idl = ovs.db.idl.Idl(remote, schema_helper)
+
+# pull initial DB
+# must be performed before any transaction
+seq_no = idl.change_seqno
+while True:
+idl.run()
+
+if seq_no == idl.change_seqno:
+poller = ovs.poller.Poller()
+idl.wait(poller)
+poller.block()
+continue
+
+seq_no = idl.change_seqno
+break
+
+# start transaction
+# action can only be done within transactions
+# multiple actions can be done in transactions
+txn = ovs.db.idl.Transaction(idl)
+
+# all the references are stored in main table which holds single row
+row = six.next(six.itervalues(idl.tables["Open_vSwitch"].rows))
+
+# to remove bridges they must be skipped in the new list
+# details in bridge table will be deleted automatically
+bridges = []
+for bridge in row.bridges:
+print(bridge.ports)
+if len(bridge.ports) > 0:
+bridges.append(bridge)
+row.bridges = bridges
+
+# store changes in DB
+txn.commit_block()
+
+idl.close()
+
+
+
diff --git a/python/howto/IDL/insert_bridge.py 
b/python/howto/IDL/insert_bridge.py
new file mode 100755
index 000..cb0209e
--- /dev/null
+++ b/python/howto/IDL/insert_bridge.py
@@ -0,0 +1,75 @@
+#! /usr/bin/env python
+
+# This is a simple example to show how to insert bridge in OVSDB. Main thing
+# is to understand that bridge should be inserted inside Open_vSwitch table not
+# Bridge table. Bridges which are not inside Open_vSwitch gets automatically
+# removed.
+
+import six
+import ovs.db.idl
+
+print("insert bridge example")
+
+# define schema helper which will hold OVS DB structure
+schema_helper = ovs.db.idl.SchemaHelper(
+"/usr/share/openvswitch/vswitch.ovsschema"
+)
+# define which parts of schema we are interested in
+schema_helper.register_columns(
+"Open_vSwitch", ["bridges"]
+)
+schema_helper.register_columns(
+"Bridge", ["name", "fail_mode"]
+)
+
+# define whether we want use UNIX socket or IP protocol
+# remote = 'unix:/run/openvswitch/db.sock'
+remote = 'tcp:127.0.0.1:12345'
+
+# initialize DB object
+idl = ovs.db.idl.Idl(remote, schema_helper)
+
+# pull initial DB
+# must be performed before any transaction
+seq_no = idl.change_seqno
+while True:
+idl.run()
+
+if seq_no == idl.change_seqno:
+poller = ovs.poller.Poller()
+idl.wait(poller)
+poller.block()
+continue
+
+seq_no = idl.change_seqno
+break
+
+# start transaction
+# action can only be done within transactions
+# multiple actions can be done in transactions
+txn = ovs.db.idl.Transaction(idl)
+
+# create bridge row
+bridge = txn.insert(idl.tables["Bridge"])
+# specify unique name for bridge
+bridge.name = "Main Bridge"
+# other bridge fields can be specified here as well
+bridge.fail_mode = "secure"
+
+# bridge gets stored inside Open_vSwitch table
+row = six.next(six.itervalues(idl.tables["Open_vSwitch"].rows))
+
+# appending directly won't work:
+# row.bridges.append(s)
+# need to create new list
+bridges = row.bridges
+bridges.append(bridge)
+row.bridges = bridges
+
+# store changes in DB
+txn.commit_block()
+
+idl.close()
+
+
+
diff --git a/python/howto/IDL/ovs_monitor.py b/python/howto/IDL/ovs_monitor.py
new file mode 100755
index 000..44c7117
--- /dev/null
+++ b/python/howto/IDL/ovs_monitor.py
@@ -0,0 +1,102 @@
+#! /usr/bin/env python
+
+# This example is to show how to 

[ovs-dev] [PATCH] python:updated docstring

2018-06-04 Thread Toms Atteka
Adjusted docstring and variable names according to previous code changes;
Fixed grammar "a attribute" > "an attribute".

Fixes: bf42f674 (idl: Convert python daemons to utilize SchemaHelper)
Signed-off-by: Toms Atteka 
---
 python/ovs/db/idl.py | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/python/ovs/db/idl.py b/python/ovs/db/idl.py
index 26421f2..64eb1a8 100644
--- a/python/ovs/db/idl.py
+++ b/python/ovs/db/idl.py
@@ -95,20 +95,21 @@ class Idl(object):
 IDL_S_MONITOR_REQUESTED = 1
 IDL_S_MONITOR_COND_REQUESTED = 2
 
-def __init__(self, remote, schema, probe_interval=None):
+def __init__(self, remote, schema_helper, probe_interval=None):
 """Creates and returns a connection to the database named 'db_name' on
 'remote', which should be in a form acceptable to
 ovs.jsonrpc.session.open().  The connection will maintain an in-memory
 replica of the remote database.
 
-'schema' should be the schema for the remote database.  The caller may
-have cut it down by removing tables or columns that are not of
-interest.  The IDL will only replicate the tables and columns that
-remain.  The caller may also add a attribute named 'alert' to selected
-remaining columns, setting its value to False; if so, then changes to
-those columns will not be considered changes to the database for the
-purpose of the return value of Idl.run() and Idl.change_seqno.  This is
-useful for columns that the IDL's client will write but not read.
+'schema_helper' should be an instance of the SchemaHelper class which
+generates schema for the remote database. The caller may have cut it
+down by removing tables or columns that are not of interest.  The IDL
+will only replicate the tables and columns that remain.  The caller may
+also add an attribute named 'alert' to selected remaining columns,
+setting its value to False; if so, then changes to those columns will
+not be considered changes to the database for the purpose of the return
+value of Idl.run() and Idl.change_seqno.  This is useful for columns
+that the IDL's client will write but not read.
 
 As a convenience to users, 'schema' may also be an instance of the
 SchemaHelper class.
@@ -120,8 +121,8 @@ class Idl(object):
 milliseconds. If None it will just use the default value in OVS.
 """
 
-assert isinstance(schema, SchemaHelper)
-schema = schema.get_idl_schema()
+assert isinstance(schema_helper, SchemaHelper)
+schema = schema_helper.get_idl_schema()
 
 self.tables = schema.tables
 self.readonly = schema.readonly
-- 
2.7.4

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev