+class IpsecTcpTests(IpsecTcp):
+ def test_tcp_checksum(self):
+ """ verify checksum correctness for vpp generated packets """
+ self.verify_tcp_checksum()
+
+
+class IpsecTra4(object):
+ """ verify methods for Transport v4 """
+ def get_replay_counts(self, p):
+ replay_node_name = ('/err/%s/SA replayed packet' %
+ self.tra4_decrypt_node_name[0])
+ count = self.statistics.get_err_counter(replay_node_name)
+
+ if p.async_mode:
+ replay_post_node_name = ('/err/%s/SA replayed packet' %
+ self.tra4_decrypt_node_name[p.async_mode])
+ count += self.statistics.get_err_counter(replay_post_node_name)
+
+ return count
+
+ def get_hash_failed_counts(self, p):
+ if ESP == self.encryption_type and p.crypt_algo == "AES-GCM":
+ hash_failed_node_name = ('/err/%s/ESP decryption failed' %
+ self.tra4_decrypt_node_name[p.async_mode])
+ else:
+ hash_failed_node_name = ('/err/%s/Integrity check failed' %
+ self.tra4_decrypt_node_name[p.async_mode])
+ count = self.statistics.get_err_counter(hash_failed_node_name)
+
+ if p.async_mode:
+ count += self.statistics.get_err_counter(
+ '/err/crypto-dispatch/bad-hmac')
+
+ return count
+
+ def verify_hi_seq_num(self):
+ p = self.params[socket.AF_INET]
+ saf = VppEnum.vl_api_ipsec_sad_flags_t
+ esn_on = p.vpp_tra_sa.esn_en
+ ar_on = p.flags & saf.IPSEC_API_SAD_FLAG_USE_ANTI_REPLAY
+
+ seq_cycle_node_name = \
+ ('/err/%s/sequence number cycled (packet dropped)' %
+ self.tra4_encrypt_node_name)
+ replay_count = self.get_replay_counts(p)
+ hash_failed_count = self.get_hash_failed_counts(p)
+ seq_cycle_count = self.statistics.get_err_counter(seq_cycle_node_name)
+
+ # a few packets so we get the rx seq number above the window size and
+ # thus can simulate a wrap with an out of window packet
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(63, 80)]
+ recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ # these 4 packets will all choose seq-num 0 to decrpyt since none
+ # are out of window when first checked. however, once #200 has
+ # decrypted it will move the window to 200 and has #81 is out of
+ # window. this packet should be dropped.
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=200)),
+ (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=81)),
+ (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=201)),
+ (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=202))]
+
+ # if anti-replay is off then we won't drop #81
+ n_rx = 3 if ar_on else 4
+ self.send_and_expect(self.tra_if, pkts, self.tra_if, n_rx=n_rx)
+ # this packet is one before the wrap
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=203))]
+ recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ # move the window over half way to a wrap
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x80000001))]
+ recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ # anti-replay will drop old packets, no anti-replay will not
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x44000001))]
+
+ if ar_on:
+ self.send_and_assert_no_replies(self.tra_if, pkts)
+ else:
+ recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ if esn_on:
+ #
+ # validate wrapping the ESN
+ #
+
+ # wrap scapy's TX SA SN
+ p.scapy_tra_sa.seq_num = 0x100000005
+
+ # send a packet that wraps the window for both AR and no AR
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x100000005))]
+
+ rxs = self.send_and_expect(self.tra_if, pkts, self.tra_if)
+ for rx in rxs:
+ decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
+
+ # move the window forward to half way to the next wrap
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x180000005))]
+
+ rxs = self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ # a packet less than 2^30 from the current position is:
+ # - AR: out of window and dropped
+ # - non-AR: accepted
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x170000005))]
+
+ if ar_on:
+ self.send_and_assert_no_replies(self.tra_if, pkts)
+ else:
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ # a packet more than 2^30 from the current position is:
+ # - AR: out of window and dropped
+ # - non-AR: considered a wrap, but since it's not a wrap
+ # it won't decrpyt and so will be dropped
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x130000005))]
+
+ self.send_and_assert_no_replies(self.tra_if, pkts)
+
+ # a packet less than 2^30 from the current position and is a
+ # wrap; (the seq is currently at 0x180000005).
+ # - AR: out of window so considered a wrap, so accepted
+ # - non-AR: not considered a wrap, so won't decrypt
+ p.scapy_tra_sa.seq_num = 0x260000005
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x260000005))]
+ if ar_on:
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+ else:
+ self.send_and_assert_no_replies(self.tra_if, pkts)
+
+ #
+ # window positions are different now for AR/non-AR
+ # move non-AR forward
+ #
+ if not ar_on:
+ # a packet more than 2^30 from the current position and is a
+ # wrap; (the seq is currently at 0x180000005).
+ # - AR: accepted
+ # - non-AR: not considered a wrap, so won't decrypt
+
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x200000005)),
+ (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x200000006))]
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x260000005))]
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ def verify_tra_anti_replay(self):
+ p = self.params[socket.AF_INET]
+ esn_en = p.vpp_tra_sa.esn_en
+
+ seq_cycle_node_name = \
+ ('/err/%s/sequence number cycled (packet dropped)' %
+ self.tra4_encrypt_node_name)
+ replay_count = self.get_replay_counts(p)
+ hash_failed_count = self.get_hash_failed_counts(p)
+ seq_cycle_count = self.statistics.get_err_counter(seq_cycle_node_name)
+
+ if ESP == self.encryption_type:
+ undersize_node_name = ('/err/%s/undersized packet' %
+ self.tra4_decrypt_node_name[0])
+ undersize_count = self.statistics.get_err_counter(
+ undersize_node_name)
+
+ #
+ # send packets with seq numbers 1->34
+ # this means the window size is still in Case B (see RFC4303
+ # Appendix A)
+ #
+ # for reasons i haven't investigated Scapy won't create a packet with
+ # seq_num=0
+ #
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(1, 34)]
+ recv_pkts = self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ # replayed packets are dropped
+ self.send_and_assert_no_replies(self.tra_if, pkts, timeout=0.2)
+ replay_count += len(pkts)
+ self.assertEqual(self.get_replay_counts(p), replay_count)
+
+ #
+ # now send a batch of packets all with the same sequence number
+ # the first packet in the batch is legitimate, the rest bogus
+ #
+ self.vapi.cli("clear error")
+ self.vapi.cli("clear node counters")
+ pkts = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=35))
+ recv_pkts = self.send_and_expect(self.tra_if, pkts * 8,
+ self.tra_if, n_rx=1)
+ replay_count += 7
+ self.assertEqual(self.get_replay_counts(p), replay_count)
+
+ #
+ # now move the window over to 257 (more than one byte) and into Case A
+ #
+ self.vapi.cli("clear error")
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=257))
+ recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
+
+ # replayed packets are dropped
+ self.send_and_assert_no_replies(self.tra_if, pkt * 3, timeout=0.2)
+ replay_count += 3
+ self.assertEqual(self.get_replay_counts(p), replay_count)
+
+ # the window size is 64 packets
+ # in window are still accepted
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=200))
+ recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
+
+ # a packet that does not decrypt does not move the window forward
+ bogus_sa = SecurityAssociation(self.encryption_type,
+ p.vpp_tra_spi,
+ crypt_algo=p.crypt_algo,
+ crypt_key=mk_scapy_crypt_key(p)[::-1],
+ auth_algo=p.auth_algo,
+ auth_key=p.auth_key[::-1])
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ bogus_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=350))
+ self.send_and_assert_no_replies(self.tra_if, pkt * 17, timeout=0.2)
+
+ hash_failed_count += 17
+ self.assertEqual(self.get_hash_failed_counts(p), hash_failed_count)
+
+ # a malformed 'runt' packet
+ # created by a mis-constructed SA
+ if (ESP == self.encryption_type and p.crypt_algo != "NULL"):
+ bogus_sa = SecurityAssociation(self.encryption_type,
+ p.vpp_tra_spi)
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ bogus_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=350))
+ self.send_and_assert_no_replies(self.tra_if, pkt * 17, timeout=0.2)
+
+ undersize_count += 17
+ self.assert_error_counter_equal(undersize_node_name,
+ undersize_count)
+
+ # which we can determine since this packet is still in the window
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=234))
+ self.send_and_expect(self.tra_if, [pkt], self.tra_if)
+
+ #
+ # out of window are dropped
+ # this is Case B. So VPP will consider this to be a high seq num wrap
+ # and so the decrypt attempt will fail
+ #
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=17))
+ self.send_and_assert_no_replies(self.tra_if, pkt * 17, timeout=0.2)
+
+ if esn_en:
+ # an out of window error with ESN looks like a high sequence
+ # wrap. but since it isn't then the verify will fail.
+ hash_failed_count += 17
+ self.assertEqual(self.get_hash_failed_counts(p), hash_failed_count)
+
+ else:
+ replay_count += 17
+ self.assertEqual(self.get_replay_counts(p), replay_count)
+
+ # valid packet moves the window over to 258
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=258))
+ rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
+ decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
+
+ #
+ # move VPP's SA TX seq-num to just before the seq-number wrap.
+ # then fire in a packet that VPP should drop on TX because it
+ # causes the TX seq number to wrap; unless we're using extened sequence
+ # numbers.
+ #
+ self.vapi.cli("test ipsec sa %d seq 0xffffffff" % p.scapy_tra_sa_id)
+ self.logger.info(self.vapi.ppcli("show ipsec sa 0"))
+ self.logger.info(self.vapi.ppcli("show ipsec sa 1"))
+
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(259, 280)]
+
+ if esn_en:
+ rxs = self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ #
+ # in order for scapy to decrypt its SA's high order number needs
+ # to wrap
+ #
+ p.vpp_tra_sa.seq_num = 0x100000000
+ for rx in rxs:
+ decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
+
+ #
+ # wrap scapy's TX high sequence number. VPP is in case B, so it
+ # will consider this a high seq wrap also.
+ # The low seq num we set it to will place VPP's RX window in Case A
+ #
+ p.scapy_tra_sa.seq_num = 0x100000005
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x100000005))
+ rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
+
+ decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
+
+ #
+ # A packet that has seq num between (2^32-64) and 5 is within
+ # the window
+ #
+ p.scapy_tra_sa.seq_num = 0xfffffffd
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0xfffffffd))
+ rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
+ decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
+
+ #
+ # While in case A we cannot wrap the high sequence number again
+ # because VPP will consider this packet to be one that moves the
+ # window forward
+ #
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x200000999))
+ self.send_and_assert_no_replies(self.tra_if, [pkt], self.tra_if,
+ timeout=0.2)
+
+ hash_failed_count += 1
+ self.assertEqual(self.get_hash_failed_counts(p), hash_failed_count)
+
+ #
+ # but if we move the window forward to case B, then we can wrap
+ # again
+ #
+ p.scapy_tra_sa.seq_num = 0x100000555
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x100000555))
+ rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
+ decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
+
+ p.scapy_tra_sa.seq_num = 0x200000444
+ pkt = (Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=0x200000444))
+ rx = self.send_and_expect(self.tra_if, [pkt], self.tra_if)
+ decrypted = p.vpp_tra_sa.decrypt(rx[0][IP])
+
+ else:
+ #
+ # without ESN TX sequence numbers can't wrap and packets are
+ # dropped from here on out.
+ #
+ self.send_and_assert_no_replies(self.tra_if, pkts, timeout=0.2)
+ seq_cycle_count += len(pkts)
+ self.assert_error_counter_equal(seq_cycle_node_name,
+ seq_cycle_count)
+
+ # move the security-associations seq number on to the last we used
+ self.vapi.cli("test ipsec sa %d seq 0x15f" % p.scapy_tra_sa_id)
+ p.scapy_tra_sa.seq_num = 351
+ p.vpp_tra_sa.seq_num = 351
+
+ def verify_tra_lost(self):
+ p = self.params[socket.AF_INET]
+ esn_en = p.vpp_tra_sa.esn_en
+
+ #
+ # send packets with seq numbers 1->34
+ # this means the window size is still in Case B (see RFC4303
+ # Appendix A)
+ #
+ # for reasons i haven't investigated Scapy won't create a packet with
+ # seq_num=0
+ #
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(1, 3)]
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ self.assertEqual(p.tra_sa_out.get_lost(), 0)
+
+ # skip a sequence number
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(4, 6)]
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ self.assertEqual(p.tra_sa_out.get_lost(), 0)
+
+ # the lost packet are counted untill we get up past the first
+ # sizeof(replay_window) packets
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(6, 100)]
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ self.assertEqual(p.tra_sa_out.get_lost(), 1)
+
+ # lost of holes in the sequence
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(100, 200, 2)]
+ self.send_and_expect(self.tra_if, pkts, self.tra_if, n_rx=50)
+
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(200, 300)]
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ self.assertEqual(p.tra_sa_out.get_lost(), 51)
+
+ # a big hole in the seq number space
+ pkts = [(Ether(src=self.tra_if.remote_mac,
+ dst=self.tra_if.local_mac) /
+ p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4,
+ dst=self.tra_if.local_ip4) /
+ ICMP(),
+ seq_num=seq))
+ for seq in range(400, 500)]
+ self.send_and_expect(self.tra_if, pkts, self.tra_if)
+
+ self.assertEqual(p.tra_sa_out.get_lost(), 151)
+
+ def verify_tra_basic4(self, count=1, payload_size=54):