ovn-northd: Handle IPv4 addresses with prefixes in lport port security
authorNuman Siddique <nusiddiq@redhat.com>
Fri, 8 Apr 2016 17:51:16 +0000 (23:21 +0530)
committerBen Pfaff <blp@ovn.org>
Thu, 14 Apr 2016 21:22:32 +0000 (14:22 -0700)
Initial implementation of port security, missed out this feature.

Reported-by: Na Zhu <nazhu@cn.ibm.com>
Reported-at: https://bugs.launchpad.net/networking-ovn/+bug/1564414
Signed-off-by: Numan Siddique <nusiddiq@redhat.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
ovn/northd/ovn-northd.c
tests/ovn.at

index 898a319..260c02f 100644 (file)
@@ -1180,8 +1180,20 @@ build_port_security_nd(struct ovn_port *op, struct hmap *lflows)
             if (ps.n_ipv4_addrs) {
                 ds_put_cstr(&match, " && (");
                 for (size_t i = 0; i < ps.n_ipv4_addrs; i++) {
-                    ds_put_format(&match, "arp.spa == "IP_FMT" || ",
-                                  IP_ARGS(ps.ipv4_addrs[i].addr));
+                    ds_put_cstr(&match, "arp.spa == ");
+                    ovs_be32 mask = be32_prefix_mask(ps.ipv4_addrs[i].plen);
+                    /* When the netmask is applied, if the host portion is
+                     * non-zero, the host can only use the specified
+                     * address in the arp.spa.  If zero, the host is allowed
+                     * to use any address in the subnet. */
+                    if (ps.ipv4_addrs[i].addr & ~mask) {
+                        ds_put_format(&match, IP_FMT,
+                                      IP_ARGS(ps.ipv4_addrs[i].addr));
+                    } else {
+                       ip_format_masked(ps.ipv4_addrs[i].addr & mask, mask,
+                                        &match);
+                    }
+                    ds_put_cstr(&match, " || ");
                 }
                 ds_chomp(&match, ' ');
                 ds_chomp(&match, '|');
@@ -1265,7 +1277,28 @@ build_port_security_ip(enum ovn_pipeline pipeline, struct ovn_port *op,
             }
 
             for (int i = 0; i < ps.n_ipv4_addrs; i++) {
-                ds_put_format(&match, IP_FMT", ", IP_ARGS(ps.ipv4_addrs[i].addr));
+                ovs_be32 mask = be32_prefix_mask(ps.ipv4_addrs[i].plen);
+                /* When the netmask is applied, if the host portion is
+                 * non-zero, the host can only use the specified
+                 * address.  If zero, the host is allowed to use any
+                 * address in the subnet.
+                 * */
+                if (ps.ipv4_addrs[i].addr & ~mask) {
+                    ds_put_format(&match, IP_FMT,
+                                  IP_ARGS(ps.ipv4_addrs[i].addr));
+                    if (pipeline == P_OUT && ps.ipv4_addrs[i].plen != 32) {
+                         /* Host is also allowed to receive packets to the
+                         * broadcast address in the specified subnet.
+                         */
+                        ds_put_format(&match, ", "IP_FMT,
+                                      IP_ARGS(ps.ipv4_addrs[i].addr | ~mask));
+                    }
+                } else {
+                    /* host portion is zero */
+                    ip_format_masked(ps.ipv4_addrs[i].addr & mask, mask,
+                                     &match);
+                }
+                ds_put_cstr(&match, ", ");
             }
 
             /* Replace ", " by "}". */
index 22121e1..30ca127 100644 (file)
@@ -1930,6 +1930,55 @@ for i in 1 2 3; do
     test_ipv6 ${i}3 f00000000${i}${i}3 f00000000021 $sip $tip
 done
 
+# configure lport13 to send and received IPv4 packets with an address range
+ovn-nbctl lport-set-port-security lp13 "f0:00:00:00:00:13 192.168.0.13 20.0.0.4/24 10.0.0.0/24"
+
+sip=`ip_to_hex 10 0 0 13`
+tip=`ip_to_hex 192 168 0 22`
+# arp packet with inner ip 10.0.0.13 should be allowed for lport13
+test_arp 13 f00000000013 f00000000013 $sip $tip 0 f00000000022
+
+sip=`ip_to_hex 10 0 0 14`
+tip=`ip_to_hex 192 168 0 23`
+# IPv4 packet from lport13 with src ip 10.0.0.14 destined to lport23
+# with dst ip 192.168.0.23 should be allowed
+test_ip 13 f00000000013 f00000000023 $sip $tip 23
+
+sip=`ip_to_hex 192 168 0 33`
+tip=`ip_to_hex 10 0 0 15`
+# IPv4 packet from lport33 with src ip 192.168.0.33 destined to lport13
+# with dst ip 10.0.0.15 should be received by lport13
+test_ip 33 f00000000033 f00000000013 $sip $tip 13
+
+sip=`ip_to_hex 192 168 0 33`
+tip=`ip_to_hex 20 0 0 4`
+# IPv4 packet from lport33 with src ip 192.168.0.33 destined to lport13
+# with dst ip 20.0.0.4 should be received by lport13
+test_ip 33 f00000000033 f00000000013 $sip $tip 13
+
+sip=`ip_to_hex 192 168 0 33`
+tip=`ip_to_hex 20 0 0 5`
+# IPv4 packet from lport33 with src ip 192.168.0.33 destined to lport13
+# with dst ip 20.0.0.5 should not be received by lport13
+test_ip 33 f00000000033 f00000000013 $sip $tip
+
+sip=`ip_to_hex 192 168 0 33`
+tip=`ip_to_hex 20 0 0 255`
+# IPv4 packet from lport33 with src ip 192.168.0.33 destined to lport13
+# with dst ip 20.0.0.255 should be received by lport13
+test_ip 33 f00000000033 f00000000013 $sip $tip 13
+
+sip=`ip_to_hex 192 168 0 33`
+tip=`ip_to_hex 192 168 0 255`
+# IPv4 packet from lport33 with src ip 192.168.0.33 destined to lport13
+# with dst ip 192.168.0.255 should not be received by lport13
+test_ip 33 f00000000033 f00000000013 $sip $tip
+
+sip=`ip_to_hex 192 168 0 33`
+tip=`ip_to_hex 224 0 0 4`
+# IPv4 packet from lport33 with src ip 192.168.0.33 destined to lport13
+# with dst ip 224.0.0.4  should be received by lport13
+test_ip 33 f00000000033 f00000000013 $sip $tip 13
 
 # Allow some time for packet forwarding.