def to_acl_rule(self, is_permit, wildcard_sport=False): p = self rule_family = AF_INET6 if p.haslayer(IPv6) else AF_INET rule_prefix_len = 128 if p.haslayer(IPv6) else 32 rule_l3_layer = IPv6 if p.haslayer(IPv6) else IP rule_l4_sport = p.sport rule_l4_dport = p.dport if p.haslayer(IPv6): rule_l4_proto = p[IPv6].nh else: rule_l4_proto = p[IP].proto if wildcard_sport: rule_l4_sport_first = 0 rule_l4_sport_last = 65535 else: rule_l4_sport_first = rule_l4_sport rule_l4_sport_last = rule_l4_sport new_rule = AclRule(is_permit=is_permit, proto=rule_l4_proto, src_prefix=ip_network( (p[rule_l3_layer].src, rule_prefix_len)), dst_prefix=ip_network( (p[rule_l3_layer].dst, rule_prefix_len)), sport_from=rule_l4_sport_first, sport_to=rule_l4_sport_last, dport_from=rule_l4_dport, dport_to=rule_l4_dport) return new_rule
def test_abf6(self): """ IPv6 ACL Based Forwarding """ # # Simple test for matching IPv6 packets # # # Rule 1 # rule_1 = AclRule(is_permit=1, proto=17, ports=1234, src_prefix=IPv6Network("2001::2/128"), dst_prefix=IPv6Network("2001::1/128")) acl_1 = VppAcl(self, rules=[rule_1]) acl_1.add_vpp_config() # # ABF policy for ACL 1 - path via interface 1 # abf_1 = VppAbfPolicy(self, 10, acl_1, [VppRoutePath("3001::1", 0xffffffff)]) abf_1.add_vpp_config() attach_1 = VppAbfAttach(self, 10, self.pg0.sw_if_index, 45, is_ipv6=True) attach_1.add_vpp_config() # # a packet matching the rule # p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src="2001::2", dst="2001::1") / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) # # packets are dropped because there is no route to the policy's # next hop # self.send_and_assert_no_replies(self.pg1, p * NUM_PKTS, "no route") # # add a route resolving the next-hop # route = VppIpRoute(self, "3001::1", 32, [VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index)]) route.add_vpp_config() # # now expect packets forwarded. # self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
def wildcard_rule(self, is_permit): any_addr = ["0.0.0.0", "::"] rule_family = self.address_family is_ip6 = 1 if rule_family == AF_INET6 else 0 new_rule = AclRule(is_permit=is_permit, proto=0, src_prefix=ip_network((any_addr[is_ip6], 0)), dst_prefix=ip_network((any_addr[is_ip6], 0)), sport_from=0, sport_to=65535, dport_from=0, dport_to=65535) return new_rule
def test_abf4(self): """ IPv4 ACL Based Forwarding """ # # We are not testing the various matching capabilities # of ACLs, that's done elsewhere. Here ware are testing # the application of ACLs to a forwarding path to achieve # ABF # So we construct just a few ACLs to ensure the ABF policies # are correctly constructed and used. And a few path types # to test the API path decoding. # # # Rule 1 # rule_1 = AclRule(is_permit=1, proto=17, ports=1234, src_prefix=IPv4Network("1.1.1.1/32"), dst_prefix=IPv4Network("1.1.1.2/32")) acl_1 = VppAcl(self, rules=[rule_1]) acl_1.add_vpp_config() # # ABF policy for ACL 1 - path via interface 1 # abf_1 = VppAbfPolicy(self, 10, acl_1, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)]) abf_1.add_vpp_config() # # Attach the policy to input interface Pg0 # attach_1 = VppAbfAttach(self, 10, self.pg0.sw_if_index, 50) attach_1.add_vpp_config() # # fire in packet matching the ACL src,dst. If it's forwarded # then the ABF was successful, since default routing will drop it # p_1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="1.1.1.1", dst="1.1.1.2") / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg1) # # Attach a 'better' priority policy to the same interface # abf_2 = VppAbfPolicy(self, 11, acl_1, [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)]) abf_2.add_vpp_config() attach_2 = VppAbfAttach(self, 11, self.pg0.sw_if_index, 40) attach_2.add_vpp_config() self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg2) # # Attach a policy with priority in the middle # abf_3 = VppAbfPolicy(self, 12, acl_1, [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)]) abf_3.add_vpp_config() attach_3 = VppAbfAttach(self, 12, self.pg0.sw_if_index, 45) attach_3.add_vpp_config() self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg2) # # remove the best priority # attach_2.remove_vpp_config() self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg3) # # Attach one of the same policies to Pg1 # attach_4 = VppAbfAttach(self, 12, self.pg1.sw_if_index, 45) attach_4.add_vpp_config() p_2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(src="1.1.1.1", dst="1.1.1.2") / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) self.send_and_expect(self.pg1, p_2 * NUM_PKTS, self.pg3) # # detach the policy from PG1, now expect traffic to be dropped # attach_4.remove_vpp_config() self.send_and_assert_no_replies(self.pg1, p_2 * NUM_PKTS, "Detached") # # Swap to route via a next-hop in the non-default table # table_20 = VppIpTable(self, 20) table_20.add_vpp_config() self.pg4.set_table_ip4(table_20.table_id) self.pg4.admin_up() self.pg4.config_ip4() self.pg4.resolve_arp() abf_13 = VppAbfPolicy(self, 13, acl_1, [VppRoutePath(self.pg4.remote_ip4, 0xffffffff, nh_table_id=table_20.table_id)]) abf_13.add_vpp_config() attach_5 = VppAbfAttach(self, 13, self.pg0.sw_if_index, 30) attach_5.add_vpp_config() self.send_and_expect(self.pg0, p_1*NUM_PKTS, self.pg4) self.pg4.unconfig_ip4() self.pg4.set_table_ip4(0)
def test_pipe(self): """Pipes""" pipes = [VppPipe(self), VppPipe(self, 10)] for p in pipes: p.add_vpp_config() p.admin_up() # # L2 cross-connect pipe0 east with pg0 and west with pg1 # self.vapi.sw_interface_set_l2_xconnect(self.pg0.sw_if_index, pipes[0].east, enable=1) self.vapi.sw_interface_set_l2_xconnect(pipes[0].east, self.pg0.sw_if_index, enable=1) self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index, pipes[0].west, enable=1) self.vapi.sw_interface_set_l2_xconnect(pipes[0].west, self.pg1.sw_if_index, enable=1) # test bi-directional L2 flow pg0<->pg1 p = (Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac) / IP(src="1.1.1.1", dst="1.1.1.2") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1) self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) # # Attach ACL to ensure features are run on the pipe # rule_1 = AclRule( is_permit=0, proto=17, src_prefix=IPv4Network("1.1.1.1/32"), dst_prefix=IPv4Network("1.1.1.2/32"), ports=1234, ) acl = VppAcl(self, rules=[rule_1]) acl.add_vpp_config() # Apply the ACL on the pipe on output acl_if_e = VppAclInterface(self, sw_if_index=pipes[0].east, n_input=0, acls=[acl]) acl_if_e.add_vpp_config() self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS) self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) # remove from output and apply on input acl_if_e.remove_vpp_config() acl_if_w = VppAclInterface(self, sw_if_index=pipes[0].west, n_input=1, acls=[acl]) acl_if_w.add_vpp_config() self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS) self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) acl_if_w.remove_vpp_config() self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1) self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) # # L3 routes in two separate tables so a pipe can be used to L3 # x-connect # tables = [] tables.append(VppIpTable(self, 1)) tables.append(VppIpTable(self, 2)) for t in tables: t.add_vpp_config() self.pg2.set_table_ip4(1) self.pg2.config_ip4() self.pg2.resolve_arp() self.pg3.set_table_ip4(2) self.pg3.config_ip4() self.pg3.resolve_arp() routes = [] routes.append( VppIpRoute( self, "1.1.1.1", 32, [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)], table_id=2, )) routes.append( VppIpRoute( self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", pipes[1].east)], table_id=1, )) routes.append( VppIpRoute( self, "1.1.1.2", 32, [VppRoutePath("0.0.0.0", pipes[1].west)], table_id=2, )) routes.append( VppIpRoute( self, "1.1.1.2", 32, [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)], table_id=1, )) for r in routes: r.add_vpp_config() p_east = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src="1.1.1.2", dst="1.1.1.1") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) # bind the pipe ends to the correct tables self.vapi.sw_interface_set_table(pipes[1].west, 0, 2) self.vapi.sw_interface_set_table(pipes[1].east, 0, 1) # IP is not enabled on the pipes at this point self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS) # IP enable the Pipes by making them unnumbered pipes[1].set_unnumbered(self.pg2.sw_if_index, True) pipes[1].set_unnumbered(self.pg3.sw_if_index, False) self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3) # and the return path p_west = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) / IP(src="1.1.1.1", dst="1.1.1.2") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2) # # Use ACLs to test features run on the Pipes # acl_if_e1 = VppAclInterface(self, sw_if_index=pipes[1].east, n_input=0, acls=[acl]) acl_if_e1.add_vpp_config() self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS) self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2) # remove from output and apply on input acl_if_e1.remove_vpp_config() acl_if_w1 = VppAclInterface(self, sw_if_index=pipes[1].west, n_input=1, acls=[acl]) acl_if_w1.add_vpp_config() self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS) self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2) acl_if_w1.remove_vpp_config() self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3) self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2) # cleanup (so the tables delete) self.pg2.unconfig_ip4() self.pg2.set_table_ip4(0) self.pg3.unconfig_ip4() self.pg3.set_table_ip4(0) self.vapi.sw_interface_set_table(pipes[1].west, 0, 0) self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
def test_dvr(self): """ Distributed Virtual Router """ # # A packet destined to an IP address that is L2 bridged via # a non-tag interface # ip_non_tag_bridged = "10.10.10.10" ip_tag_bridged = "10.10.10.11" any_src_addr = "1.1.1.1" pkt_no_tag = ( Ether(src=self.pg0.remote_mac, dst=self.loop0.local_mac) / IP(src=any_src_addr, dst=ip_non_tag_bridged) / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) pkt_tag = (Ether(src=self.pg0.remote_mac, dst=self.loop0.local_mac) / IP(src=any_src_addr, dst=ip_tag_bridged) / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) # # Two sub-interfaces so we can test VLAN tag push/pop # sub_if_on_pg2 = VppDot1QSubint(self, self.pg2, 92) sub_if_on_pg3 = VppDot1QSubint(self, self.pg3, 93) sub_if_on_pg2.admin_up() sub_if_on_pg3.admin_up() # # Put all the interfaces into a new bridge domain # self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg0.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.loop0.sw_if_index, bd_id=1, port_type=L2_PORT_TYPE.BVI) self.vapi.l2_interface_vlan_tag_rewrite( sw_if_index=sub_if_on_pg2.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=92) self.vapi.l2_interface_vlan_tag_rewrite( sw_if_index=sub_if_on_pg3.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=93) # # Add routes to bridge the traffic via a tagged an nontagged interface # route_no_tag = VppIpRoute(self, ip_non_tag_bridged, 32, [ VppRoutePath("0.0.0.0", self.pg1.sw_if_index, type=FibPathType.FIB_PATH_TYPE_DVR) ]) route_no_tag.add_vpp_config() # # Inject the packet that arrives and leaves on a non-tagged interface # Since it's 'bridged' expect that the MAC headed is unchanged. # rx = self.send_and_expect(self.pg0, pkt_no_tag * NUM_PKTS, self.pg1) self.assert_same_mac_addr(pkt_no_tag, rx) self.assert_has_no_tag(rx) # # Add routes to bridge the traffic via a tagged interface # route_with_tag = VppIpRoute(self, ip_tag_bridged, 32, [ VppRoutePath("0.0.0.0", sub_if_on_pg3.sw_if_index, type=FibPathType.FIB_PATH_TYPE_DVR) ]) route_with_tag.add_vpp_config() # # Inject the packet that arrives non-tag and leaves on a tagged # interface # rx = self.send_and_expect(self.pg0, pkt_tag * NUM_PKTS, self.pg3) self.assert_same_mac_addr(pkt_tag, rx) self.assert_has_vlan_tag(93, rx) # # Tag to tag # pkt_tag_to_tag = ( Ether(src=self.pg2.remote_mac, dst=self.loop0.local_mac) / Dot1Q(vlan=92) / IP(src=any_src_addr, dst=ip_tag_bridged) / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) rx = self.send_and_expect(self.pg2, pkt_tag_to_tag * NUM_PKTS, self.pg3) self.assert_same_mac_addr(pkt_tag_to_tag, rx) self.assert_has_vlan_tag(93, rx) # # Tag to non-Tag # pkt_tag_to_non_tag = ( Ether(src=self.pg2.remote_mac, dst=self.loop0.local_mac) / Dot1Q(vlan=92) / IP(src=any_src_addr, dst=ip_non_tag_bridged) / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) rx = self.send_and_expect(self.pg2, pkt_tag_to_non_tag * NUM_PKTS, self.pg1) self.assert_same_mac_addr(pkt_tag_to_tag, rx) self.assert_has_no_tag(rx) # # Add an output L3 ACL that will block the traffic # rule_1 = AclRule(is_permit=0, proto=17, ports=1234, src_prefix=IPv4Network((any_src_addr, 32)), dst_prefix=IPv4Network((ip_non_tag_bridged, 32))) acl = VppAcl(self, rules=[rule_1]) acl.add_vpp_config() # # Apply the ACL on the output interface # acl_if1 = VppAclInterface(self, sw_if_index=self.pg1.sw_if_index, n_input=0, acls=[acl]) acl_if1.add_vpp_config() # # Send packet's that should match the ACL and be dropped # rx = self.send_and_assert_no_replies(self.pg2, pkt_tag_to_non_tag * NUM_PKTS) # # cleanup # acl_if1.remove_vpp_config() acl.remove_vpp_config() self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg0.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.loop0.sw_if_index, bd_id=1, port_type=L2_PORT_TYPE.BVI, enable=0) # # Do a FIB dump to make sure the paths are correctly reported as DVR # routes = self.vapi.ip_route_dump(0) for r in routes: if (ip_tag_bridged == str(r.route.prefix.network_address)): self.assertEqual(r.route.paths[0].sw_if_index, sub_if_on_pg3.sw_if_index) self.assertEqual(r.route.paths[0].type, FibPathType.FIB_PATH_TYPE_DVR) if (ip_non_tag_bridged == str(r.route.prefix.network_address)): self.assertEqual(r.route.paths[0].sw_if_index, self.pg1.sw_if_index) self.assertEqual(r.route.paths[0].type, FibPathType.FIB_PATH_TYPE_DVR) # # the explicit route delete is require so it happens before # the sbu-interface delete. subinterface delete is required # because that object type does not use the object registry # route_no_tag.remove_vpp_config() route_with_tag.remove_vpp_config() sub_if_on_pg3.remove_vpp_config() sub_if_on_pg2.remove_vpp_config()
def create_stream( self, src_ip_if, dst_ip_if, reverse, packet_sizes, is_ip6, expect_blocked, expect_established, add_extension_header, icmp_stateful=False, ): pkts = [] rules = [] permit_rules = [] permit_and_reflect_rules = [] total_packet_count = 8 for i in range(0, total_packet_count): modulo = (i // 2) % 2 icmp_type_delta = i % 2 icmp_code = i is_udp_packet = modulo == 0 if is_udp_packet and icmp_stateful: continue is_reflectable_icmp = (icmp_stateful and icmp_type_delta == 0 and not is_udp_packet) is_reflected_icmp = is_reflectable_icmp and expect_established can_reflect_this_packet = is_udp_packet or is_reflectable_icmp is_permit = i % 2 remote_dst_index = i % len(dst_ip_if.remote_hosts) remote_dst_host = dst_ip_if.remote_hosts[remote_dst_index] if is_permit == 1: info = self.create_packet_info(src_ip_if, dst_ip_if) payload = self.info_to_payload(info) else: to_be_blocked = False if expect_blocked and not expect_established: to_be_blocked = True if not can_reflect_this_packet: to_be_blocked = True if to_be_blocked: payload = "to be blocked" else: info = self.create_packet_info(src_ip_if, dst_ip_if) payload = self.info_to_payload(info) if reverse: dst_mac = "de:ad:00:00:00:00" src_mac = remote_dst_host._mac dst_ip6 = src_ip_if.remote_ip6 src_ip6 = remote_dst_host.ip6 dst_ip4 = src_ip_if.remote_ip4 src_ip4 = remote_dst_host.ip4 dst_l4 = 1234 + i src_l4 = 4321 + i else: dst_mac = src_ip_if.local_mac src_mac = src_ip_if.remote_mac src_ip6 = src_ip_if.remote_ip6 dst_ip6 = remote_dst_host.ip6 src_ip4 = src_ip_if.remote_ip4 dst_ip4 = remote_dst_host.ip4 src_l4 = 1234 + i dst_l4 = 4321 + i if is_reflected_icmp: icmp_type_delta = 1 # default ULP should be something we do not use in tests ulp_l4 = TCP(sport=src_l4, dport=dst_l4) # potentially a chain of protocols leading to ULP ulp = ulp_l4 if is_udp_packet: if is_ip6: ulp_l4 = UDP(sport=src_l4, dport=dst_l4) if add_extension_header: # prepend some extension headers ulp = (IPv6ExtHdrRouting() / IPv6ExtHdrRouting() / IPv6ExtHdrFragment(offset=0, m=1) / ulp_l4) # uncomment below to test invalid ones # ulp = IPv6ExtHdrRouting(len = 200) / ulp_l4 else: ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IPv6(src=src_ip6, dst=dst_ip6) / ulp / Raw(payload)) else: ulp_l4 = UDP(sport=src_l4, dport=dst_l4) # IPv4 does not allow extension headers, # but we rather make it a first fragment flags = 1 if add_extension_header else 0 ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IP(src=src_ip4, dst=dst_ip4, frag=0, flags=flags) / ulp / Raw(payload)) elif modulo == 1: if is_ip6: ulp_l4 = ICMPv6Unknown(type=128 + icmp_type_delta, code=icmp_code) ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IPv6(src=src_ip6, dst=dst_ip6) / ulp / Raw(payload)) else: ulp_l4 = ICMP(type=8 - 8 * icmp_type_delta, code=icmp_code) ulp = ulp_l4 p = (Ether(dst=dst_mac, src=src_mac) / IP(src=src_ip4, dst=dst_ip4) / ulp / Raw(payload)) if i % 2 == 1: info.data = p.copy() size = packet_sizes[(i // 2) % len(packet_sizes)] self.extend_packet(p, size) pkts.append(p) rule_family = AF_INET6 if p.haslayer(IPv6) else AF_INET rule_prefix_len = 128 if p.haslayer(IPv6) else 32 rule_l3_layer = IPv6 if p.haslayer(IPv6) else IP if p.haslayer(UDP): rule_l4_sport = p[UDP].sport rule_l4_dport = p[UDP].dport else: if p.haslayer(ICMP): rule_l4_sport = p[ICMP].type rule_l4_dport = p[ICMP].code else: rule_l4_sport = p[ICMPv6Unknown].type rule_l4_dport = p[ICMPv6Unknown].code if p.haslayer(IPv6): rule_l4_proto = ulp_l4.overload_fields[IPv6]["nh"] else: rule_l4_proto = p[IP].proto new_rule = AclRule( is_permit=is_permit, proto=rule_l4_proto, src_prefix=ip_network((p[rule_l3_layer].src, rule_prefix_len)), dst_prefix=ip_network((p[rule_l3_layer].dst, rule_prefix_len)), sport_from=rule_l4_sport, sport_to=rule_l4_sport, dport_from=rule_l4_dport, dport_to=rule_l4_dport, ) rules.append(new_rule) new_rule_permit = copy.copy(new_rule) new_rule_permit.is_permit = 1 permit_rules.append(new_rule_permit) new_rule_permit_and_reflect = copy.copy(new_rule) if can_reflect_this_packet: new_rule_permit_and_reflect.is_permit = 2 else: new_rule_permit_and_reflect.is_permit = is_permit permit_and_reflect_rules.append(new_rule_permit_and_reflect) self.logger.info("create_stream pkt#%d: %s" % (i, payload)) return { "stream": pkts, "rules": rules, "permit_rules": permit_rules, "permit_and_reflect_rules": permit_and_reflect_rules, }
def create_stream( self, mac_type, ip_type, packet_count, src_if, dst_if, traffic, is_ip6, tags=PERMIT_TAGS, ): # exact MAC and exact IP # exact MAC and subnet of IPs # exact MAC and wildcard IP # wildcard MAC and exact IP # wildcard MAC and subnet of IPs # wildcard MAC and wildcard IP # OUI restricted MAC and exact IP # OUI restricted MAC and subnet of IPs # OUI restricted MAC and wildcard IP packets = [] macip_rules = [] acl_rules = [] ip_permit = "" mac_permit = "" dst_mac = "" mac_rule = "00:00:00:00:00:00" mac_mask = "00:00:00:00:00:00" for p in range(0, packet_count): remote_dst_index = p % len(dst_if.remote_hosts) remote_dst_host = dst_if.remote_hosts[remote_dst_index] dst_port = 1234 + p src_port = 4321 + p is_permit = self.PERMIT if p % 3 == 0 else self.DENY denyMAC = True if not is_permit and p % 3 == 1 else False denyIP = True if not is_permit and p % 3 == 2 else False if not is_permit and ip_type == self.WILD_IP: denyMAC = True if not is_permit and mac_type == self.WILD_MAC: denyIP = True if traffic == self.BRIDGED: if is_permit: src_mac = remote_dst_host._mac dst_mac = "de:ad:00:00:00:00" src_ip4 = remote_dst_host.ip4 dst_ip4 = src_if.remote_ip4 src_ip6 = remote_dst_host.ip6 dst_ip6 = src_if.remote_ip6 ip_permit = src_ip6 if is_ip6 else src_ip4 mac_permit = src_mac if denyMAC: mac = src_mac.split(":") mac[0] = format(int(mac[0], 16) + 1, "02x") src_mac = ":".join(mac) if is_ip6: src_ip6 = ip_permit else: src_ip4 = ip_permit if denyIP: if ip_type != self.WILD_IP: src_mac = mac_permit src_ip4 = remote_dst_host.ip4 dst_ip4 = src_if.remote_ip4 src_ip6 = remote_dst_host.ip6 dst_ip6 = src_if.remote_ip6 else: if is_permit: src_mac = remote_dst_host._mac dst_mac = src_if.local_mac src_ip4 = src_if.remote_ip4 dst_ip4 = remote_dst_host.ip4 src_ip6 = src_if.remote_ip6 dst_ip6 = remote_dst_host.ip6 ip_permit = src_ip6 if is_ip6 else src_ip4 mac_permit = src_mac if denyMAC: mac = src_mac.split(":") mac[0] = format(int(mac[0], 16) + 1, "02x") src_mac = ":".join(mac) if is_ip6: src_ip6 = ip_permit else: src_ip4 = ip_permit if denyIP: src_mac = remote_dst_host._mac if ip_type != self.WILD_IP: src_mac = mac_permit src_ip4 = remote_dst_host.ip4 dst_ip4 = src_if.remote_ip4 src_ip6 = remote_dst_host.ip6 dst_ip6 = src_if.remote_ip6 if is_permit: info = self.create_packet_info(src_if, dst_if) payload = self.info_to_payload(info) else: payload = "to be blocked" if mac_type == self.WILD_MAC: mac = src_mac.split(":") for i in range(1, 5): mac[i] = format(random.randint(0, 255), "02x") src_mac = ":".join(mac) # create packet packet = Ether(src=src_mac, dst=dst_mac) ip_rule = src_ip6 if is_ip6 else src_ip4 if is_ip6: if ip_type != self.EXACT_IP: sub_ip = list(unpack("<16B", inet_pton(AF_INET6, ip_rule))) if ip_type == self.WILD_IP: sub_ip[0] = random.randint(240, 254) sub_ip[1] = random.randint(230, 239) sub_ip[14] = random.randint(100, 199) sub_ip[15] = random.randint(200, 255) elif ip_type == self.SUBNET_IP: if denyIP: sub_ip[2] = int(sub_ip[2]) + 1 sub_ip[14] = random.randint(100, 199) sub_ip[15] = random.randint(200, 255) packed_src_ip6 = b"".join([scapy.compat.chb(x) for x in sub_ip]) src_ip6 = inet_ntop(AF_INET6, packed_src_ip6) packet /= IPv6(src=src_ip6, dst=dst_ip6) else: if ip_type != self.EXACT_IP: sub_ip = ip_rule.split(".") if ip_type == self.WILD_IP: sub_ip[0] = random.randint(1, 49) sub_ip[1] = random.randint(50, 99) sub_ip[2] = random.randint(100, 199) sub_ip[3] = random.randint(200, 255) elif ip_type == self.SUBNET_IP: if denyIP: sub_ip[1] = int(sub_ip[1]) + 1 sub_ip[2] = random.randint(100, 199) sub_ip[3] = random.randint(200, 255) src_ip4 = ".".join(["{!s}".format(x) for x in sub_ip]) packet /= IP(src=src_ip4, dst=dst_ip4, frag=0, flags=0) packet /= UDP(sport=src_port, dport=dst_port) / Raw(payload) packet[Raw].load += b" mac:%s" % src_mac.encode("utf-8") size = self.pg_if_packet_sizes[p % len(self.pg_if_packet_sizes)] if isinstance(src_if, VppSubInterface): size = size + 4 if isinstance(src_if, VppDot1QSubint): if src_if is self.subifs[0]: if tags == self.PERMIT_TAGS: packet = src_if.add_dot1q_layer(packet, 10) else: packet = src_if.add_dot1q_layer(packet, 11) else: if tags == self.PERMIT_TAGS: packet = src_if.add_dot1q_layer(packet, 30) else: packet = src_if.add_dot1q_layer(packet, 33) elif isinstance(src_if, VppDot1ADSubint): if src_if is self.subifs[1]: if tags == self.PERMIT_TAGS: packet = src_if.add_dot1ad_layer(packet, 300, 400) else: packet = src_if.add_dot1ad_layer(packet, 333, 444) else: if tags == self.PERMIT_TAGS: packet = src_if.add_dot1ad_layer(packet, 600, 700) else: packet = src_if.add_dot1ad_layer(packet, 666, 777) self.extend_packet(packet, size) packets.append(packet) # create suitable MACIP rule if mac_type == self.EXACT_MAC: mac_rule = src_mac mac_mask = "ff:ff:ff:ff:ff:ff" elif mac_type == self.WILD_MAC: mac_rule = "00:00:00:00:00:00" mac_mask = "00:00:00:00:00:00" elif mac_type == self.OUI_MAC: mac = src_mac.split(":") mac[3] = mac[4] = mac[5] = "00" mac_rule = ":".join(mac) mac_mask = "ff:ff:ff:00:00:00" if is_ip6: if ip_type == self.WILD_IP: ip = "0::0" else: ip = src_ip6 if ip_type == self.SUBNET_IP: sub_ip = list(unpack("<16B", inet_pton(AF_INET6, ip))) for i in range(8, 16): sub_ip[i] = 0 packed_ip = b"".join([scapy.compat.chb(x) for x in sub_ip]) ip = inet_ntop(AF_INET6, packed_ip) else: if ip_type == self.WILD_IP: ip = "0.0.0.0" else: ip = src_ip4 if ip_type == self.SUBNET_IP: sub_ip = ip.split(".") sub_ip[2] = sub_ip[3] = "0" ip = ".".join(sub_ip) prefix_len = 128 if is_ip6 else 32 if ip_type == self.WILD_IP: prefix_len = 0 elif ip_type == self.SUBNET_IP: prefix_len = 64 if is_ip6 else 16 ip_rule = inet_pton(AF_INET6 if is_ip6 else AF_INET, ip) # create suitable ACL rule if is_permit: rule_l4_sport = packet[UDP].sport rule_l4_dport = packet[UDP].dport rule_family = AF_INET6 if packet.haslayer(IPv6) else AF_INET rule_prefix_len = 128 if packet.haslayer(IPv6) else 32 rule_l3_layer = IPv6 if packet.haslayer(IPv6) else IP if packet.haslayer(IPv6): rule_l4_proto = packet[UDP].overload_fields[IPv6]["nh"] else: rule_l4_proto = packet[IP].proto src_network = ip_network((packet[rule_l3_layer].src, rule_prefix_len)) dst_network = ip_network((packet[rule_l3_layer].dst, rule_prefix_len)) acl_rule = AclRule( is_permit=is_permit, proto=rule_l4_proto, src_prefix=src_network, dst_prefix=dst_network, sport_from=rule_l4_sport, sport_to=rule_l4_sport, dport_from=rule_l4_dport, dport_to=rule_l4_dport, ) acl_rules.append(acl_rule) if mac_type == self.WILD_MAC and ip_type == self.WILD_IP and p > 0: continue if is_permit: macip_rule = MacipRule( is_permit=is_permit, src_prefix=ip_network((ip_rule, prefix_len)), src_mac=MACAddress(mac_rule).packed, src_mac_mask=MACAddress(mac_mask).packed, ) macip_rules.append(macip_rule) # deny all other packets if not (mac_type == self.WILD_MAC and ip_type == self.WILD_IP): network = IPv6Network((0, 0)) if is_ip6 else IPv4Network((0, 0)) macip_rule = MacipRule( is_permit=0, src_prefix=network, src_mac=MACAddress("00:00:00:00:00:00").packed, src_mac_mask=MACAddress("00:00:00:00:00:00").packed, ) macip_rules.append(macip_rule) network = IPv6Network((0, 0)) if is_ip6 else IPv4Network((0, 0)) acl_rule = AclRule( is_permit=0, src_prefix=network, dst_prefix=network, sport_from=0, sport_to=0, dport_from=0, dport_to=0, ) acl_rules.append(acl_rule) return {"stream": packets, "macip_rules": macip_rules, "acl_rules": acl_rules}