@@ -5,6 +5,7 @@ usr/bin/ovn-ic-nbctl
usr/bin/ovn-ic-sbctl
usr/bin/ovn-trace
usr/bin/ovn-detrace
+usr/bin/ovn-match-ip
usr/share/ovn/scripts/ovn-ctl
usr/share/ovn/scripts/ovndb-servers.ocf
usr/share/ovn/scripts/ovn-lib
@@ -1060,6 +1060,200 @@ expr_constant_set_destroy(struct expr_constant_set *cs)
}
}
+struct ip_in
+{
+ uint32_t *ip;
+ size_t size;
+};
+
+struct ip_out_entry
+{
+ uint32_t ip;
+ uint32_t mask;
+ bool masked;
+};
+
+struct ip_out
+{
+ struct ip_out_entry *entries;
+ size_t used;
+ size_t size;
+};
+
+static int
+compare_mask_ip(const void *a, const void *b)
+{
+ uint32_t a_ = *(uint32_t *)a;
+ uint32_t b_ = *(uint32_t *)b;
+
+ return a_ < b_ ? -1 : a_ > b_;
+}
+
+/* Function to check ip return data and xrealloc. */
+static void
+check_realloc_ip_out(struct ip_out *ip_out_data){
+ if (ip_out_data->used >= ip_out_data->size) {
+ ip_out_data->entries = x2nrealloc(ip_out_data->entries,
+ &ip_out_data->size,
+ sizeof *ip_out_data->entries);
+ }
+}
+
+/* Simple description of the algorithm.
+ * There are two situations
+ * 1. Combine once
+ * such as:
+ * 1.1.1.0 1.1.1.1 1.0.1.0 1.0.1.1
+ * Combined into: 1.1.1.0/31, 1.0.1.0/31
+ * 2. Combine multiple times
+ * 1.1.1.0 1.1.1.1 1.0.1.0 1.0.1.1
+ * Combined into: 1.0.1.0/255.254.255.254
+ *
+ * Considering the actual scene and simplicity, the first case is used to
+ * combine once.
+ *
+ * ...00...
+ * ...01...
+ * ...10...
+ * ...11...
+ * "..." means the same value omitted.
+ * Obviously, the above value can be expressed as ...00.../11100111. This
+ * continuous interval that can be represented by one or several wildcard
+ * masks is called a segment.
+ * Only if all 2<<n values from the minimum value 00...(n) to 11...(n)
+ * exist, can they be combined into 00...(n)/00...( n)
+ *
+ * First sort all the values by size. Iterate through each value.
+ * 1. Find a new segment, where two values differ only by 1 bit, such as
+ * ...0... and ...1...
+ * diff = ip_next ^ ip
+ * if (diff & (diff-1)) == 0
+ * new_segment = true
+ * The first non-zero place in the high direction of ip is the end of the
+ * segment(segment_end).
+ * For example...100... and...101..., the segment_end is ...111...
+ *
+ * 2. Count the number of consecutive and less than continuous_size in the
+ * segment.
+ * diff = ip_next - ip
+ * if (diff & (diff-1)) == 0 && ip_next <= segment_end
+ * continuous_size++
+ *
+ * 3. Combine different ip intervals in the segment according to
+ * continuous_size.
+ * In continuous_size, from the highest bit of 1 to the lowest bit of 1, in
+ * the order of segment start, each bit that is 1 is a different ip interval
+ * that can be combined with a wildcard mask.
+ * For example, 000, 001, 010:
+ * continuous_size: 3 (binary 11), segment_start: 000
+ * mask: ~(1 << 1 - 1) = 110; ~(1 << 0 - 1) = 111;
+ * Combined to: 000/110, 010/111
+ *
+ * 4. The ip that cannot be recorded in a segment will not be combined. */
+static void
+combine_ipv4_in_mask(struct ip_in *ip_in_data, struct ip_out *ip_out_data){
+ bool recording = false;
+ uint32_t i, diff, connect, start, end, continuous_size, mask_base;
+
+ start = 0;
+ continuous_size = 0;
+ mask_base = 0;
+ end = 0;
+
+ qsort(ip_in_data->ip, ip_in_data->size, sizeof(uint32_t),
+ compare_mask_ip);
+ memset(ip_out_data, 0, sizeof(struct ip_out));
+
+ for (i = 0; i < ip_in_data->size; i++) {
+ if (i + 1 >= ip_in_data->size) {
+ if (!recording) {
+ goto end_when_not_recording;
+ } else {
+ goto end_when_recording;
+ }
+ }
+ /* Not recording in a segment.
+ * Record a new segment or not combine. */
+ if (!recording) {
+ connect = ip_in_data->ip[i + 1] ^ ip_in_data->ip[i];
+ /* Only one bit different. */
+ if ((connect & (connect - 1)) == 0) {
+ recording = true;
+ start = ip_in_data->ip[i];
+ continuous_size = 2;
+ mask_base = connect;
+
+ int j = 0;
+ end = start;
+ /* The first non-zero place in the high direction is
+ * the end of the segment. */
+ while (j < 32 && ((start & (mask_base << j)) == 0)) {
+ end |= (mask_base << j);
+ j++;
+ }
+
+ continue;
+ /* Different segments and different bit, dnot combine. */
+ } else {
+end_when_not_recording:
+ check_realloc_ip_out(ip_out_data);
+
+ ip_out_data->entries[ip_out_data->used].ip =
+ ip_in_data->ip[i];
+ ip_out_data->entries[ip_out_data->used].masked = false;
+ ip_out_data->used++;
+
+ continue;
+ }
+ /* Recording in the current segment. */
+ } else {
+ diff = ip_in_data->ip[i + 1] - ip_in_data->ip[i];
+ /* Ignore equal node. */
+ if (diff == 0) {
+ continue;
+ }
+ /* Stop recording and combine, or continue recording. */
+ if (((diff & (diff - 1)) != 0)
+ || (ip_in_data->ip[i + 1] > end)) {
+end_when_recording:
+ recording = false;
+ while (continuous_size) {
+ check_realloc_ip_out(ip_out_data);
+
+ int segment_power, pow_base;
+ if (continuous_size == 0) {
+ segment_power = 0;
+ } else {
+ segment_power = 31 - clz32(continuous_size);
+ }
+
+ if (mask_base == 0) {
+ pow_base = 0;
+ } else {
+ pow_base = 31 - clz32(mask_base);
+ }
+
+ ip_out_data->entries[ip_out_data->used].mask =
+ ~(((1 << segment_power) - 1) << pow_base);
+ ip_out_data->entries[ip_out_data->used].ip =
+ ip_out_data->entries[ip_out_data->used].mask
+ & start;
+ ip_out_data->entries[ip_out_data->used].masked = true;
+ ip_out_data->used++;
+
+ continuous_size &= (~(1 << segment_power));
+ start = ip_out_data->entries[ip_out_data->used - 1].ip
+ + (1 << (segment_power + pow_base));
+ }
+ } else {
+ continuous_size++;
+ }
+
+ continue;
+ }
+ }
+}
+
/* Adds an constant set named 'name' to 'const_sets', replacing any existing
* constant set entry with the given name. */
void
@@ -1074,6 +1268,11 @@ expr_const_sets_add(struct shash *const_sets, const char *name,
cs->in_curlies = true;
cs->n_values = 0;
cs->values = xmalloc(n_values * sizeof *cs->values);
+ struct ip_out ip_out_data;
+ struct ip_in ip_in_data;
+ ip_in_data.ip = xmalloc(n_values * sizeof(uint32_t));
+ ip_in_data.size = 0;
+
if (convert_to_integer) {
cs->type = EXPR_C_INTEGER;
for (size_t i = 0; i < n_values; i++) {
@@ -1086,6 +1285,9 @@ expr_const_sets_add(struct shash *const_sets, const char *name,
&& lex.token.type != LEX_T_MASKED_INTEGER) {
VLOG_WARN("Invalid constant set entry: '%s', token type: %d",
values[i], lex.token.type);
+ } else if (lex.token.type == LEX_T_INTEGER
+ && lex.token.format == LEX_F_IPV4) {
+ ip_in_data.ip[ip_in_data.size++] = ntohl(lex.token.value.ipv4);
} else {
union expr_constant *c = &cs->values[cs->n_values++];
c->value = lex.token.value;
@@ -1105,6 +1307,23 @@ expr_const_sets_add(struct shash *const_sets, const char *name,
}
}
+ if (ip_in_data.size > 0) {
+ combine_ipv4_in_mask(&ip_in_data, &ip_out_data);
+ for (size_t i = 0; i < ip_out_data.used; ++i) {
+ union expr_constant *c = &cs->values[cs->n_values++];
+ memset(&c->value, 0, sizeof c->value);
+ memset(&c->mask, 0, sizeof c->mask);
+ c->value.ipv4 = htonl(ip_out_data.entries[i].ip);
+ c->format = LEX_F_IPV4;
+ c->masked = ip_out_data.entries[i].masked;
+ if (c->masked) {
+ c->mask.ipv4 = htonl(ip_out_data.entries[i].mask);
+ }
+ }
+ free(ip_out_data.entries);
+ }
+
+ free(ip_in_data.ip);
shash_add(const_sets, name, cs);
}
@@ -455,6 +455,7 @@ fi
%{_bindir}/ovn-sbctl
%{_bindir}/ovn-trace
%{_bindir}/ovn-detrace
+%{_bindir}/ovn-match-ip
%{_bindir}/ovn-appctl
%{_bindir}/ovn-ic-nbctl
%{_bindir}/ovn-ic-sbctl
@@ -618,20 +618,32 @@ ip,nw_src=10.0.0.3
])
AT_CHECK([expr_to_flow 'ip4.src == $set1'], [0], [dnl
ip,nw_src=10.0.0.1
-ip,nw_src=10.0.0.2
-ip,nw_src=10.0.0.3
+ip,nw_src=10.0.0.2/31
+])
+AT_CHECK([expr_to_flow 'ip4.src == $set5'], [0], [dnl
+ip,nw_src=1.1.1.128/26
+ip,nw_src=1.1.1.16/28
+ip,nw_src=1.1.1.192/27
+ip,nw_src=1.1.1.2/31
+ip,nw_src=1.1.1.224/28
+ip,nw_src=1.1.1.240/29
+ip,nw_src=1.1.1.248/30
+ip,nw_src=1.1.1.252/31
+ip,nw_src=1.1.1.254
+ip,nw_src=1.1.1.32/27
+ip,nw_src=1.1.1.4/30
+ip,nw_src=1.1.1.64/26
+ip,nw_src=1.1.1.8/29
])
AT_CHECK([expr_to_flow 'ip4.src == {1.2.3.4, $set1}'], [0], [dnl
ip,nw_src=1.2.3.4
ip,nw_src=10.0.0.1
-ip,nw_src=10.0.0.2
-ip,nw_src=10.0.0.3
+ip,nw_src=10.0.0.2/31
])
AT_CHECK([expr_to_flow 'ip4.src == {1.2.0.0/20, 5.5.5.0/24, $set1}'], [0], [dnl
ip,nw_src=1.2.0.0/20
ip,nw_src=10.0.0.1
-ip,nw_src=10.0.0.2
-ip,nw_src=10.0.0.3
+ip,nw_src=10.0.0.2/31
ip,nw_src=5.5.5.0/24
])
AT_CHECK([expr_to_flow 'ip6.src == {::1, ::2, ::3}'], [0], [dnl
@@ -13580,23 +13592,20 @@ cat 2.expected > expout
$PYTHON "$ovs_srcdir/utilities/ovs-pcap.in" hv1/vif2-tx.pcap > 2.packets
AT_CHECK([cat 2.packets], [0], [expout])
-# There should be total of 9 flows present with conjunction action and 2 flows
+# There should be total of 6 flows present with conjunction action and 2 flows
# with conj match. Eg.
-# table=44, priority=2001,conj_id=2,metadata=0x1 actions=resubmit(,45)
-# table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(2,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(2,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.5 actions=conjunction(2,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(3,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(3,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8 actions=conjunction(3,2/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(2,1/2),conjunction(3,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(2,1/2),conjunction(3,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(2,1/2),conjunction(3,1/2)
-
-OVS_WAIT_UNTIL([test 9 = `as hv1 ovs-ofctl dump-flows br-int | \
+#table=45, n_packets=1, n_bytes=42, idle_age=211, priority=2001,conj_id=2,ip,metadata=0x1 actions=resubmit(,46)
+#table=45, n_packets=0, n_bytes=0, idle_age=211, priority=2001,conj_id=3,ip,metadata=0x1 actions=drop
+#priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(2,2/2),conjunction(3,2/2)
+#priority=2001,ip,metadata=0x1,nw_src=10.0.0.4/31 actions=conjunction(2,2/2),conjunction(3,2/2)
+#priority=2001,ip,metadata=0x1,nw_dst=10.0.0.4/31 actions=conjunction(2,1/2)
+#priority=2001,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(2,1/2)
+#priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(3,1/2)
+#priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8/31 actions=conjunction(3,1/2)
+
+OVS_WAIT_UNTIL([test 6 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction | wc -l`])
-OVS_WAIT_UNTIL([test 3 = `as hv1 ovs-ofctl dump-flows br-int | \
+OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction.*conjunction | wc -l`])
OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conj_id | wc -l`])
@@ -13623,18 +13632,16 @@ AT_CHECK([cat 2.packets], [0], [])
# properly.
# There should be total of 6 flows present with conjunction action and 1 flow
# with conj match. Eg.
-# table=44, priority=2001,conj_id=3,metadata=0x1 actions=drop
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(4,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(4,2/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8 actions=conjunction(4,2/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(4,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(4,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(4,1/2)
+# table=45, n_packets=1, n_bytes=42, idle_age=34, priority=2001,conj_id=3,ip,metadata=0x1 actions=drop
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(3,2/2)
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4/31 actions=conjunction(3,2/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8/31 actions=conjunction(3,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(3,1/2)
ovn-nbctl acl-del ls1 to-lport 1001 \
'ip4 && ip4.src == $set1 && ip4.dst == $set1'
-OVS_WAIT_UNTIL([test 6 = `as hv1 ovs-ofctl dump-flows br-int | \
+OVS_WAIT_UNTIL([test 4 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction | wc -l`])
OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction.*conjunction | wc -l`])
@@ -13648,43 +13655,40 @@ ovn-nbctl acl-add ls1 to-lport 1001 \
ovn-nbctl acl-add ls1 to-lport 1001 \
'ip4 && ip4.src == $set1 && ip4.dst == {10.0.0.9, 10.0.0.10}' drop
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8 actions=conjunction(4,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(4,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(5,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.5 actions=conjunction(5,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(5,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(4,1/2),conjunction(6,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.10 actions=conjunction(6,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(4,2/2),conjunction(5,2/2),conjunction(6,2/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(4,2/2),conjunction(5,2/2),conjunction(6,2/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(4,2/2),conjunction(5,2/2),conjunction(6,2/2)
-
-OVS_WAIT_UNTIL([test 10 = `as hv1 ovs-ofctl dump-flows br-int | \
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.7 actions=conjunction(3,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8/31 actions=conjunction(3,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.4/31 actions=conjunction(4,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(4,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(5,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.10 actions=conjunction(5,1/2)
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4/31 actions=conjunction(3,2/2),conjunction(4,2/2),conjunction(5,2/2)
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(3,2/2),conjunction(4,2/2),conjunction(5,2/2)
+
+OVS_WAIT_UNTIL([test 8 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction | wc -l`])
-OVS_WAIT_UNTIL([test 4 = `as hv1 ovs-ofctl dump-flows br-int | \
+OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction.*conjunction | wc -l`])
-OVS_WAIT_UNTIL([test 3 = `as hv1 ovs-ofctl dump-flows br-int | \
+OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction.*conjunction.*conjunction | wc -l`])
# Remove 10.0.0.7 from address set2. All flows should be updated properly.
ovn-nbctl set Address_Set set2 \
addresses=\"10.0.0.8\",\"10.0.0.9\"
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.4 actions=conjunction(9,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.10 actions=conjunction(7,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8 actions=conjunction(8,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.5 actions=conjunction(9,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(7,1/2),conjunction(8,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(9,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(7,2/2),conjunction(8,2/2),conjunction(9,2/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(7,2/2),conjunction(8,2/2),conjunction(9,2/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(7,2/2),conjunction(8,2/2),conjunction(9,2/2)
-
-OVS_WAIT_UNTIL([test 9 = `as hv1 ovs-ofctl dump-flows br-int | \
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4/31,nw_dst=10.0.0.8/31 actions=drop
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6,nw_dst=10.0.0.8/31 actions=drop
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.4/31 actions=conjunction(4,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.6 actions=conjunction(4,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(5,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.10 actions=conjunction(5,1/2)
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(5,2/2),conjunction(4,2/2)
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4/31 actions=conjunction(5,2/2),conjunction(4,2/2)
+
+OVS_WAIT_UNTIL([test 6 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction | wc -l`])
-OVS_WAIT_UNTIL([test 4 = `as hv1 ovs-ofctl dump-flows br-int | \
+OVS_WAIT_UNTIL([test 2 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction.*conjunction | wc -l`])
-OVS_WAIT_UNTIL([test 3 = `as hv1 ovs-ofctl dump-flows br-int | \
+OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction.*conjunction.*conjunction | wc -l`])
# Remove an ACL again
@@ -13693,16 +13697,16 @@ ovn-nbctl acl-del ls1 to-lport 1001 \
wait_for_ports_up
ovn-nbctl --wait=hv sync
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.10 actions=conjunction(10,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.8 actions=conjunction(11,1/2)
-# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(10,1/2),conjunction(11,1/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.5 actions=conjunction(10,2/2),conjunction(11,2/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(10,2/2),conjunction(11,2/2)
-# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4 actions=conjunction(10,2/2),conjunction(11,2/2)
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6,nw_dst=10.0.0.8/31 actions=drop
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4/31,nw_dst=10.0.0.8/31 actions=drop
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.6 actions=conjunction(5,2/2)
+# priority=2001,ip,metadata=0x1,nw_src=10.0.0.4/31 actions=conjunction(5,2/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.10 actions=conjunction(5,1/2)
+# priority=2001,ip,metadata=0x1,nw_dst=10.0.0.9 actions=conjunction(5,1/2)
-OVS_WAIT_UNTIL([test 6 = `as hv1 ovs-ofctl dump-flows br-int | \
-grep conjunction | wc -l`])
OVS_WAIT_UNTIL([test 4 = `as hv1 ovs-ofctl dump-flows br-int | \
+grep conjunction | wc -l`])
+OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction.*conjunction | wc -l`])
OVS_WAIT_UNTIL([test 0 = `as hv1 ovs-ofctl dump-flows br-int | \
grep conjunction.*conjunction.*conjunction | wc -l`])
@@ -15373,11 +15377,11 @@ for i in 1 2 3; do
# Update address set as1
ovn-nbctl --wait=hv set addr as1 addresses="10.1.2.10 10.1.2.11"
- AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.11"], [0], [ignore])
+ AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.10/31"], [0], [ignore])
# Update address set as2
ovn-nbctl --wait=hv set addr as2 addresses="10.1.2.12 10.1.2.13"
- AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12"], [0], [ignore])
+ AT_CHECK([ovs-ofctl dump-flows br-int | grep "10.1.2.12/31"], [0], [ignore])
# Add another ACL referencing as1
n_flows_before=`ovs-ofctl dump-flows br-int | grep "10.1.2.10" | wc -l`
@@ -227,10 +227,19 @@ create_addr_sets(struct shash *addr_sets)
};
static const char *const addrs4[] = { NULL };
+ static const char *addrs5[253];
+ static char addrs5_[253][20];
+ for (int i = 0, ip_num = 2; i < 253; i++, ip_num++) {
+ sprintf(addrs5_[i], "1.1.1.%d", ip_num);
+ addrs5[i] = addrs5_[i];
+ }
+
expr_const_sets_add(addr_sets, "set1", addrs1, 3, true);
expr_const_sets_add(addr_sets, "set2", addrs2, 3, true);
expr_const_sets_add(addr_sets, "set3", addrs3, 3, true);
expr_const_sets_add(addr_sets, "set4", addrs4, 0, true);
+ expr_const_sets_add(addr_sets, "set5", (const char *const *)addrs5,
+ 253, true);
}
static void
@@ -21,7 +21,8 @@ MAN_ROOTS += \
bin_SCRIPTS += \
utilities/ovn-docker-overlay-driver \
utilities/ovn-docker-underlay-driver \
- utilities/ovn-detrace
+ utilities/ovn-detrace \
+ utilities/ovn-match-ip
EXTRA_DIST += \
utilities/ovn-ctl \
@@ -35,6 +36,7 @@ EXTRA_DIST += \
utilities/ovn-appctl.8.xml \
utilities/ovn-trace.8.xml \
utilities/ovn-detrace.in \
+ utilities/ovn-match-ip.in \
utilities/ovndb-servers.ocf \
utilities/checkpatch.py \
utilities/docker/Makefile \
@@ -60,6 +62,7 @@ CLEANFILES += \
utilities/ovn-trace.8 \
utilities/ovn-detrace.1 \
utilities/ovn-detrace \
+ utilities/ovn-match-ip \
utilities/ovn-appctl.8 \
utilities/ovn-appctl \
utilities/ovn-sim
new file mode 100755
@@ -0,0 +1,78 @@
+#!/bin/bash
+#
+# 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.
+
+IPCALC_WILDCARD_RET=
+
+ipcalc_wildcard () {
+ ip=`echo $1 | awk -F '/' '{print $1}'`
+ ip_list=${ip//./ }
+ read -a ip_array <<< ${ip_list}
+ mask=`echo $1 | awk -F '/' '{print $2}'`
+ mask_list=${mask//./ }
+ read -a mask_array <<< ${mask_list}
+ ip_0=$((${ip_array[0]} & ${mask_array[0]}))
+ ip_1=$((${ip_array[1]} & ${mask_array[1]}))
+ ip_2=$((${ip_array[2]} & ${mask_array[2]}))
+ ip_3=$((${ip_array[3]} & ${mask_array[3]}))
+ IPCALC_WILDCARD_RET="$ip_0.$ip_1.$ip_2.$ip_3"
+}
+
+for arg
+do
+ case $arg in
+ -h | --help)
+ cat <<EOF
+$0: A tool that can match ip wildcard mask similar to grep
+usage: $0 ip
+Search for ip/mask that can be matched in standard input.
+Example: echo ip 192.168.1.0/24 | $0 192.168.1.1
+Result: ip 192.168.1.0/24
+
+You might use this: ovs-ofctl dump-flows br-int | $0 192.168.1.1
+EOF
+ exit 0
+ ;;
+ esac
+done
+
+while read line
+do
+ ip=`echo $line | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'`
+ if test "$ip" == "$1"; then
+ echo $line | grep --color $1
+ continue
+ fi
+
+ ip_mask=`echo $line | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+'`
+ if test "$ip_mask" != ""; then
+ ipcalc_wildcard $ip_mask
+ ip_mask_ret=$IPCALC_WILDCARD_RET
+ match_ip_mask=`echo $ip_mask | sed 's/.*\//'$1'\//'`
+ ipcalc_wildcard $match_ip_mask
+ match_ip_mask_ret=$IPCALC_WILDCARD_RET
+ if test $ip_mask_ret == $match_ip_mask_ret; then
+ echo $line | grep --color $ip_mask
+ fi
+ continue
+ fi
+
+ ip_prefix=`echo $line | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+'`
+ if test "$ip_prefix" != ""; then
+ match_ip_prefix=`echo $ip_prefix | sed 's/.*\//'$1'\//'`
+ if test `ipcalc -n $match_ip_prefix` == `ipcalc -n $ip_prefix`; then
+ echo $line | grep --color $ip_prefix
+ fi
+ continue
+ fi
+done