aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/dpdk/device/dpdk_priv.h
blob: 794953da55e4fdcb47a6e34d4839a1461899cb93 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * 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.
 */

#define DPDK_NB_RX_DESC_DEFAULT   1024
#define DPDK_NB_TX_DESC_DEFAULT   1024
#define DPDK_MAX_LRO_SIZE_DEFAULT 65536

/* These args appear by themselves */
#define foreach_eal_double_hyphen_predicate_arg \
_(no-shconf)                                    \
_(no-hpet)                                      \
_(no-huge)                                      \
_(vmware-tsc-map)

#define foreach_eal_single_hyphen_arg           \
_(mem-alloc-request, m)                         \
_(force-ranks, r)

/* clang-format off */
/* These args are preceded by "--" and followed by a single string */
#define foreach_eal_double_hyphen_arg           \
_(huge-dir)                                     \
_(proc-type)                                    \
_(file-prefix)                                  \
_(vdev)                                         \
_(log-level)                                    \
_(block)                                        \
_(iova-mode)                                    \
_(base-virtaddr)
/* clang-format on */

static_always_inline void
dpdk_device_flag_set (dpdk_device_t *xd, __typeof__ (xd->flags) flag, int val)
{
  xd->flags = val ? xd->flags | flag : xd->flags & ~flag;
}

void dpdk_counters_xstats_init (dpdk_device_t *xd);

static inline void
dpdk_get_xstats (dpdk_device_t *xd, u32 thread_index)
{
  int ret;
  int i;
  if (!(xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP))
    return;

  ret = rte_eth_xstats_get (xd->port_id, xd->xstats, vec_len (xd->xstats));
  if (ret < 0)
    {
      dpdk_log_warn ("rte_eth_xstats_get(%d) failed: %d", xd->port_id, ret);
      return;
    }
  else if (ret != vec_len (xd->xstats))
    {
      dpdk_log_warn (
	"rte_eth_xstats_get(%d) returned %d/%d stats. Resetting counters.",
	xd->port_id, ret, vec_len (xd->xstats));
      dpdk_counters_xstats_init (xd);
      return;
    }

  vec_foreach_index (i, xd->xstats)
    {
      vlib_set_simple_counter (&xd->xstats_counters, thread_index, i,
			       xd->xstats[i].value);
    }
}

#define DPDK_UPDATE_COUNTER(vnm, tidx, xd, stat, cnt)                         \
  do                                                                          \
    {                                                                         \
      u64 _v = (xd)->stats.stat;                                              \
      u64 _lv = (xd)->last_stats.stat;                                        \
      if (PREDICT_FALSE (_v != _lv))                                          \
        {                                                                     \
          if (PREDICT_FALSE (_v < _lv))                                       \
            dpdk_log_warn ("%v: %s counter decreased (before %lu after %lu)", \
                           xd->name, #stat, _lv, _v);                         \
          else                                                                \
            vlib_increment_simple_counter (                                   \
                vec_elt_at_index ((vnm)->interface_main.sw_if_counters, cnt), \
                (tidx), (xd)->sw_if_index, _v - _lv);                         \
        }                                                                     \
    }                                                                         \
  while (0)

static inline void
dpdk_update_counters (dpdk_device_t * xd, f64 now)
{
  vnet_main_t *vnm = vnet_get_main ();
  u32 thread_index = vlib_get_thread_index ();

  xd->time_last_stats_update = now ? now : xd->time_last_stats_update;
  clib_memcpy_fast (&xd->last_stats, &xd->stats, sizeof (xd->last_stats));
  rte_eth_stats_get (xd->port_id, &xd->stats);

  /* maybe bump interface rx no buffer counter */
  DPDK_UPDATE_COUNTER (vnm, thread_index, xd, rx_nombuf,
		       VNET_INTERFACE_COUNTER_RX_NO_BUF);
  DPDK_UPDATE_COUNTER (vnm, thread_index, xd, imissed,
		       VNET_INTERFACE_COUNTER_RX_MISS);
  DPDK_UPDATE_COUNTER (vnm, thread_index, xd, ierrors,
		       VNET_INTERFACE_COUNTER_RX_ERROR);

  dpdk_get_xstats (xd, thread_index);
}

#if RTE_VERSION < RTE_VERSION_NUM(21, 11, 0, 0)
#define RTE_MBUF_F_RX_FDIR		  PKT_RX_FDIR
#define RTE_MBUF_F_RX_FDIR_FLX		  PKT_RX_FDIR_FLX
#define RTE_MBUF_F_RX_FDIR_ID		  PKT_RX_FDIR_ID
#define RTE_MBUF_F_RX_IEEE1588_PTP	  PKT_RX_IEEE1588_PTP
#define RTE_MBUF_F_RX_IEEE1588_TMST	  PKT_RX_IEEE1588_TMST
#define RTE_MBUF_F_RX_IP_CKSUM_BAD	  PKT_RX_IP_CKSUM_BAD
#define RTE_MBUF_F_RX_IP_CKSUM_GOOD	  PKT_RX_IP_CKSUM_GOOD
#define RTE_MBUF_F_RX_IP_CKSUM_NONE	  PKT_RX_IP_CKSUM_GOOD
#define RTE_MBUF_F_RX_L4_CKSUM_BAD	  PKT_RX_L4_CKSUM_BAD
#define RTE_MBUF_F_RX_L4_CKSUM_GOOD	  PKT_RX_L4_CKSUM_GOOD
#define RTE_MBUF_F_RX_L4_CKSUM_NONE	  PKT_RX_L4_CKSUM_GOOD
#define RTE_MBUF_F_RX_LRO		  PKT_RX_LRO
#define RTE_MBUF_F_RX_OUTER_IP_CKSUM_BAD  PKT_RX_OUTER_IP_CKSUM_BAD
#define RTE_MBUF_F_RX_OUTER_L4_CKSUM_BAD  PKT_RX_OUTER_L4_CKSUM_GOOD
#define RTE_MBUF_F_RX_OUTER_L4_CKSUM_GOOD PKT_RX_OUTER_L4_CKSUM_GOOD
#define RTE_MBUF_F_RX_OUTER_L4_CKSUM_NONE PKT_RX_OUTER_L4_CKSUM_GOOD
#define RTE_MBUF_F_RX_QINQ		  PKT_RX_QINQ
#define RTE_MBUF_F_RX_QINQ_STRIPPED	  PKT_RX_QINQ_STRIPPED
#define RTE_MBUF_F_RX_RSS_HASH		  PKT_RX_RSS_HASH
#define RTE_MBUF_F_RX_SEC_OFFLOAD	  PKT_RX_SEC_OFFLOAD
#define RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED  PKT_RX_SEC_OFFLOAD_FAILED
#define RTE_MBUF_F_RX_VLAN		  PKT_RX_VLAN
#define RTE_MBUF_F_RX_VLAN_STRIPPED	  PKT_RX_VLAN_STRIPPED
#define RTE_MBUF_F_TX_IEEE1588_TMST	  PKT_TX_IEEE1588_TMST
#define RTE_MBUF_F_TX_IPV4		  PKT_TX_IPV4
#define RTE_MBUF_F_TX_IPV6		  PKT_TX_IPV6
#define RTE_MBUF_F_TX_IP_CKSUM		  PKT_TX_IP_CKSUM
#define RTE_MBUF_F_TX_MACSEC		  PKT_TX_MACSEC
#define RTE_MBUF_F_TX_OUTER_IPV4	  PKT_TX_OUTER_IPV4
#define RTE_MBUF_F_TX_OUTER_IPV6	  PKT_TX_OUTER_IPV6
#define RTE_MBUF_F_TX_OUTER_IP_CKSUM	  PKT_TX_OUTER_IP_CKSUM
#define RTE_MBUF_F_TX_OUTER_UDP_CKSUM	  PKT_TX_OUTER_UDP_CKSUM
#define RTE_MBUF_F_TX_QINQ		  PKT_TX_QINQ
#define RTE_MBUF_F_TX_SCTP_CKSUM	  PKT_TX_SCTP_CKSUM
#define RTE_MBUF_F_TX_SEC_OFFLOAD	  PKT_TX_SEC_OFFLOAD
#define RTE_MBUF_F_TX_TCP_CKSUM		  PKT_TX_TCP_CKSUM
#define RTE_MBUF_F_TX_TCP_SEG		  PKT_TX_TCP_SEG
#define RTE_MBUF_F_TX_TUNNEL_GENEVE	  PKT_TX_TUNNEL_GENEVE
#define RTE_MBUF_F_TX_TUNNEL_GRE	  PKT_TX_TUNNEL_GRE
#define RTE_MBUF_F_TX_TUNNEL_GTP	  PKT_TX_TUNNEL_GTP
#define RTE_MBUF_F_TX_TUNNEL_IP		  PKT_TX_TUNNEL_IP
#define RTE_MBUF_F_TX_TUNNEL_IPIP	  PKT_TX_TUNNEL_IPIP
#define RTE_MBUF_F_TX_TUNNEL_MPLSINUDP	  PKT_TX_TUNNEL_MPLSINUDP
#define RTE_MBUF_F_TX_TUNNEL_UDP	  PKT_TX_TUNNEL_UDP
#define RTE_MBUF_F_TX_TUNNEL_VXLAN	  PKT_TX_TUNNEL_VXLAN
#define RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE	  PKT_TX_TUNNEL_VXLAN_GPE
#define RTE_MBUF_F_TX_UDP_CKSUM		  PKT_TX_UDP_CKSUM
#define RTE_MBUF_F_TX_UDP_SEG		  PKT_TX_UDP_SEG
#define RTE_MBUF_F_TX_VLAN		  PKT_TX_VLAN
#define RTE_ETH_RSS_FRAG_IPV4		    ETH_RSS_FRAG_IPV4
#define RTE_ETH_RSS_NONFRAG_IPV4_TCP	    ETH_RSS_NONFRAG_IPV4_TCP
#define RTE_ETH_RSS_NONFRAG_IPV4_UDP	    ETH_RSS_NONFRAG_IPV4_UDP
#define RTE_ETH_RSS_NONFRAG_IPV4_SCTP	    ETH_RSS_NONFRAG_IPV4_SCTP
#define RTE_ETH_RSS_NONFRAG_IPV4_OTHER	    ETH_RSS_NONFRAG_IPV4_OTHER
#define RTE_ETH_RSS_IPV4		    ETH_RSS_IPV4
#define RTE_ETH_RSS_IPV6_TCP_EX		    ETH_RSS_IPV6_TCP_EX
#define RTE_ETH_RSS_IPV6_UDP_EX		    ETH_RSS_IPV6_UDP_EX
#define RTE_ETH_RSS_FRAG_IPV6		    ETH_RSS_FRAG_IPV6
#define RTE_ETH_RSS_NONFRAG_IPV6_TCP	    ETH_RSS_NONFRAG_IPV6_TCP
#define RTE_ETH_RSS_NONFRAG_IPV6_UDP	    ETH_RSS_NONFRAG_IPV6_UDP
#define RTE_ETH_RSS_NONFRAG_IPV6_SCTP	    ETH_RSS_NONFRAG_IPV6_SCTP
#define RTE_ETH_RSS_NONFRAG_IPV6_OTHER	    ETH_RSS_NONFRAG_IPV6_OTHER
#define RTE_ETH_RSS_IPV6_EX		    ETH_RSS_IPV6_EX
#define RTE_ETH_RSS_IPV6		    ETH_RSS_IPV6
#define RTE_ETH_RSS_L2_PAYLOAD		    ETH_RSS_L2_PAYLOAD
#define RTE_ETH_RSS_PORT		    ETH_RSS_PORT
#define RTE_ETH_RSS_VXLAN		    ETH_RSS_VXLAN
#define RTE_ETH_RSS_GENEVE		    ETH_RSS_GENEVE
#define RTE_ETH_RSS_NVGRE		    ETH_RSS_NVGRE
#define RTE_ETH_RSS_GTPU		    ETH_RSS_GTPU
#define RTE_ETH_RSS_ESP			    ETH_RSS_ESP
#define RTE_ETH_RSS_L4_DST_ONLY		    ETH_RSS_L4_DST_ONLY
#define RTE_ETH_RSS_L4_SRC_ONLY		    ETH_RSS_L4_SRC_ONLY
#define RTE_ETH_RSS_L3_DST_ONLY		    ETH_RSS_L3_DST_ONLY
#define RTE_ETH_RSS_L3_SRC_ONLY		    ETH_RSS_L3_SRC_ONLY
#define RTE_ETH_RETA_GROUP_SIZE		    RTE_RETA_GROUP_SIZE
#define RTE_ETH_TX_OFFLOAD_IPV4_CKSUM	    DEV_TX_OFFLOAD_IPV4_CKSUM
#define RTE_ETH_TX_OFFLOAD_TCP_CKSUM	    DEV_TX_OFFLOAD_TCP_CKSUM
#define RTE_ETH_TX_OFFLOAD_UDP_CKSUM	    DEV_TX_OFFLOAD_UDP_CKSUM
#define RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM
#define RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM  DEV_TX_OFFLOAD_OUTER_UDP_CKSUM
#define RTE_ETH_TX_OFFLOAD_TCP_TSO	    DEV_TX_OFFLOAD_TCP_TSO
#define RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO    DEV_TX_OFFLOAD_VXLAN_TNL_TSO
#define RTE_ETH_TX_OFFLOAD_MULTI_SEGS	    DEV_TX_OFFLOAD_MULTI_SEGS
#define RTE_ETH_RX_OFFLOAD_IPV4_CKSUM	    DEV_RX_OFFLOAD_IPV4_CKSUM
#define RTE_ETH_RX_OFFLOAD_SCATTER	    DEV_RX_OFFLOAD_SCATTER
#define RTE_ETH_RX_OFFLOAD_TCP_LRO	    DEV_RX_OFFLOAD_TCP_LRO
#define RTE_ETH_MQ_RX_RSS		    ETH_MQ_RX_RSS
#define RTE_ETH_RX_OFFLOAD_TCP_CKSUM	    DEV_RX_OFFLOAD_TCP_CKSUM
#define RTE_ETH_RX_OFFLOAD_UDP_CKSUM	    DEV_RX_OFFLOAD_UDP_CKSUM
#define RTE_ETH_MQ_RX_NONE		    ETH_MQ_RX_NONE
#define RTE_ETH_LINK_FULL_DUPLEX	    ETH_LINK_FULL_DUPLEX
#define RTE_ETH_LINK_HALF_DUPLEX	    ETH_LINK_HALF_DUPLEX
#define RTE_ETH_VLAN_STRIP_OFFLOAD	    ETH_VLAN_STRIP_OFFLOAD
#define RTE_ETH_VLAN_FILTER_OFFLOAD	    ETH_VLAN_FILTER_OFFLOAD
#define RTE_ETH_VLAN_EXTEND_OFFLOAD	    ETH_VLAN_EXTEND_OFFLOAD
#define RTE_ETH_LINK_SPEED_200G		    ETH_LINK_SPEED_200G
#define RTE_ETH_LINK_SPEED_100G		    ETH_LINK_SPEED_100G
#define RTE_ETH_LINK_SPEED_56G		    ETH_LINK_SPEED_56G
#define RTE_ETH_LINK_SPEED_50G		    ETH_LINK_SPEED_50G
#define RTE_ETH_LINK_SPEED_40G		    ETH_LINK_SPEED_40G
#define RTE_ETH_LINK_SPEED_25G		    ETH_LINK_SPEED_25G
#define RTE_ETH_LINK_SPEED_20G		    ETH_LINK_SPEED_20G
#define RTE_ETH_LINK_SPEED_10G		    ETH_LINK_SPEED_10G
#define RTE_ETH_LINK_SPEED_5G		    ETH_LINK_SPEED_5G
#define RTE_ETH_LINK_SPEED_2_5G		    ETH_LINK_SPEED_2_5G
#define RTE_ETH_LINK_SPEED_1G		    ETH_LINK_SPEED_1G
#define RTE_ETH_RSS_IP			    ETH_RSS_IP
#define RTE_ETH_RSS_UDP			    ETH_RSS_UDP
#define RTE_ETH_RSS_TCP			    ETH_RSS_TCP
#endif

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
ass="c1"># Create list of pg_interfaces in VRFs cls.pg_in_vrf = list() # Create list of pg_interfaces not in VRFs cls.pg_not_in_vrf = [pg_if for pg_if in cls.pg_interfaces] # Create mapping of pg_interfaces to VRF IDs cls.pg_if_by_vrf_id = dict() for i in range(cls.nr_of_vrfs): vrf_id = i + 1 pg_list = [ cls.pg_interfaces[i * cls.pg_ifs_per_vrf + j] for j in range(cls.pg_ifs_per_vrf)] cls.pg_if_by_vrf_id[vrf_id] = pg_list except Exception: super(TestIP6VrfMultiInst, cls).tearDownClass() raise @classmethod def tearDownClass(cls): super(TestIP6VrfMultiInst, cls).tearDownClass() def setUp(self): """ Clear trace and packet infos before running each test. """ super(TestIP6VrfMultiInst, self).setUp() self.reset_packet_infos() def tearDown(self): """ Show various debug prints after each test. """ super(TestIP6VrfMultiInst, self).tearDown() def show_commands_at_teardown(self): self.logger.info(self.vapi.ppcli("show ip6 fib")) self.logger.info(self.vapi.ppcli("show ip6 neighbors")) def create_vrf_and_assign_interfaces(self, count, start=1): """ Create required number of FIB tables / VRFs, put 3 pg-ip6 interfaces to every FIB table / VRF. :param int count: Number of FIB tables / VRFs to be created. :param int start: Starting number of the FIB table / VRF ID. \ (Default value = 1) """ for i in range(count): vrf_id = i + start pg_if = self.pg_if_by_vrf_id[vrf_id][0] dest_addr = pg_if.local_ip6n dest_addr_len = 64 self.vapi.ip_table_add_del(is_ipv6=1, is_add=1, table_id=vrf_id) self.logger.info("IPv6 VRF ID %d created" % vrf_id) if vrf_id not in self.vrf_list: self.vrf_list.append(vrf_id) if vrf_id in self.vrf_reset_list: self.vrf_reset_list.remove(vrf_id) for j in range(self.pg_ifs_per_vrf): pg_if = self.pg_if_by_vrf_id[vrf_id][j] pg_if.set_table_ip6(vrf_id) self.logger.info("pg-interface %s added to IPv6 VRF ID %d" % (pg_if.name, vrf_id)) if pg_if not in self.pg_in_vrf: self.pg_in_vrf.append(pg_if) if pg_if in self.pg_not_in_vrf: self.pg_not_in_vrf.remove(pg_if) pg_if.config_ip6() pg_if.disable_ipv6_ra() pg_if.configure_ipv6_neighbors() self.logger.debug(self.vapi.ppcli("show ip6 fib")) self.logger.debug(self.vapi.ppcli("show ip6 neighbors")) def reset_vrf_and_remove_from_vrf_list(self, vrf_id): """ Reset required FIB table / VRF and remove it from VRF list. :param int vrf_id: The FIB table / VRF ID to be reset. """ # self.vapi.reset_vrf(vrf_id, is_ipv6=1) self.vapi.reset_fib(vrf_id, is_ipv6=1) if vrf_id in self.vrf_list: self.vrf_list.remove(vrf_id) if vrf_id not in self.vrf_reset_list: self.vrf_reset_list.append(vrf_id) for j in range(self.pg_ifs_per_vrf): pg_if = self.pg_if_by_vrf_id[vrf_id][j] pg_if.unconfig_ip6() if pg_if in self.pg_in_vrf: self.pg_in_vrf.remove(pg_if) if pg_if not in self.pg_not_in_vrf: self.pg_not_in_vrf.append(pg_if) self.logger.info("IPv6 VRF ID %d reset finished" % vrf_id) self.logger.debug(self.vapi.ppcli("show ip6 fib")) self.logger.debug(self.vapi.ppcli("show ip6 neighbors")) self.vapi.ip_table_add_del(is_ipv6=1, is_add=0, table_id=vrf_id) def create_stream(self, src_if, packet_sizes): """ Create input packet stream for defined interface using hosts list. :param object src_if: Interface to create packet stream for. :param list packet_sizes: List of required packet sizes. :return: Stream of packets. """ pkts = [] src_hosts = src_if.remote_hosts for dst_if in self.flows[src_if]: for dst_host in dst_if.remote_hosts: src_host = random.choice(src_hosts) pkt_info = self.create_packet_info(src_if, dst_if) payload = self.info_to_payload(pkt_info) p = (Ether(dst=src_if.local_mac, src=src_host.mac) / IPv6(src=src_host.ip6, dst=dst_host.ip6) / UDP(sport=1234, dport=1234) / Raw(payload)) pkt_info.data = p.copy() size = random.choice(packet_sizes) self.extend_packet(p, size) pkts.append(p) self.logger.debug("Input stream created for port %s. Length: %u pkt(s)" % (src_if.name, len(pkts))) return pkts def create_stream_crosswise_vrf(self, src_if, vrf_id, packet_sizes): """ Create input packet stream for negative test for leaking across different VRFs for defined interface using hosts list. :param object src_if: Interface to create packet stream for. :param int vrf_id: The FIB table / VRF ID where src_if is assigned. :param list packet_sizes: List of required packet sizes. :return: Stream of packets. """ pkts = [] src_hosts = src_if.remote_hosts vrf_lst = list(self.vrf_list) vrf_lst.remove(vrf_id) for vrf in vrf_lst: for dst_if in self.pg_if_by_vrf_id[vrf]: for dst_host in dst_if.remote_hosts: src_host = random.choice(src_hosts) pkt_info = self.create_packet_info(src_if, dst_if) payload = self.info_to_payload(pkt_info) p = (Ether(dst=src_if.local_mac, src=src_host.mac) / IPv6(src=src_host.ip6, dst=dst_host.ip6) / UDP(sport=1234, dport=1234) / Raw(payload)) pkt_info.data = p.copy() size = random.choice(packet_sizes) self.extend_packet(p, size) pkts.append(p) self.logger.debug("Input stream created for port %s. Length: %u pkt(s)" % (src_if.name, len(pkts))) return pkts def verify_capture(self, pg_if, capture): """ Verify captured input packet stream for defined interface. :param object pg_if: Interface to verify captured packet stream for. :param list capture: Captured packet stream. """ last_info = dict() for i in self.pg_interfaces: last_info[i.sw_if_index] = None dst_sw_if_index = pg_if.sw_if_index for packet in capture: try: ip = packet[IPv6] udp = packet[UDP] payload_info = self.payload_to_info(packet[Raw]) packet_index = payload_info.index self.assertEqual(payload_info.dst, dst_sw_if_index) self.logger.debug("Got packet on port %s: src=%u (id=%u)" % (pg_if.name, payload_info.src, packet_index)) next_info = self.get_next_packet_info_for_interface2( payload_info.src, dst_sw_if_index, last_info[payload_info.src]) last_info[payload_info.src] = next_info self.assertIsNotNone(next_info) self.assertEqual(packet_index, next_info.index) saved_packet = next_info.data # Check standard fields self.assertEqual(ip.src, saved_packet[IPv6].src) self.assertEqual(ip.dst, saved_packet[IPv6].dst) self.assertEqual(udp.sport, saved_packet[UDP].sport) self.assertEqual(udp.dport, saved_packet[UDP].dport) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise for i in self.pg_interfaces: remaining_packet = self.get_next_packet_info_for_interface2( i, dst_sw_if_index, last_info[i.sw_if_index]) self.assertIsNone( remaining_packet, "Port %u: Packet expected from source %u didn't arrive" % (dst_sw_if_index, i.sw_if_index)) def verify_vrf(self, vrf_id): """ Check if the FIB table / VRF ID is configured. :param int vrf_id: The FIB table / VRF ID to be verified. :return: 1 if the FIB table / VRF ID is configured, otherwise return 0. """ ip6_fib_dump = self.vapi.ip6_fib_dump() vrf_exist = False vrf_count = 0 for ip6_fib_details in ip6_fib_dump: if ip6_fib_details.table_id == vrf_id: if not vrf_exist: vrf_exist = True addr = inet_ntop(socket.AF_INET6, ip6_fib_details.address) found = False for pg_if in self.pg_if_by_vrf_id[vrf_id]: if found: break for host in pg_if.remote_hosts: if str(addr) == str(host.ip6): vrf_count += 1 found = True break if not vrf_exist and vrf_count == 0: self.logger.info("IPv6 VRF ID %d is not configured" % vrf_id) return VRFState.not_configured elif vrf_exist and vrf_count == 0: self.logger.info("IPv6 VRF ID %d has been reset" % vrf_id) return VRFState.reset else: self.logger.info("IPv6 VRF ID %d is configured" % vrf_id) return VRFState.configured def run_verify_test(self): """ Create packet streams for all configured pg interfaces, send all \ prepared packet streams and verify that: - all packets received correctly on all pg-ip6 interfaces assigned to VRFs - no packet received on all pg-ip6 interfaces not assigned to VRFs :raise RuntimeError: If no packet captured on pg-ip6 interface assigned to VRF or if any packet is captured on pg-ip6 interface not assigned to VRF. """ # Test # Create incoming packet streams for packet-generator interfaces for pg_if in self.pg_interfaces: pkts = self.create_stream(pg_if, self.pg_if_packet_sizes) pg_if.add_stream(pkts) # Enable packet capture and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify # Verify outgoing packet streams per packet-generator interface for pg_if in self.pg_interfaces: if pg_if in self.pg_in_vrf: capture = pg_if.get_capture(remark="interface is in VRF") self.verify_capture(pg_if, capture) elif pg_if in self.pg_not_in_vrf: pg_if.assert_nothing_captured(remark="interface is not in VRF", filter_out_fn=is_ipv6_misc_ext) self.logger.debug("No capture for interface %s" % pg_if.name) else: raise Exception("Unknown interface: %s" % pg_if.name) def run_crosswise_vrf_test(self): """ Create packet streams for every pg-ip6 interface in VRF towards all pg-ip6 interfaces in other VRFs, send all prepared packet streams and \ verify that: - no packet received on all configured pg-ip6 interfaces :raise RuntimeError: If any packet is captured on any pg-ip6 interface. """ # Test # Create incoming packet streams for packet-generator interfaces for vrf_id in self.vrf_list: for pg_if in self.pg_if_by_vrf_id[vrf_id]: pkts = self.create_stream_crosswise_vrf( pg_if, vrf_id, self.pg_if_packet_sizes) pg_if.add_stream(pkts) # Enable packet capture and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify # Verify outgoing packet streams per packet-generator interface for pg_if in self.pg_interfaces: pg_if.assert_nothing_captured(remark="interface is in other VRF", filter_out_fn=is_ipv6_misc_ext) self.logger.debug("No capture for interface %s" % pg_if.name) def test_ip6_vrf_01(self): """ IP6 VRF Multi-instance test 1 - create 4 VRFs """ # Config 1 # Create 4 VRFs self.create_vrf_and_assign_interfaces(4) # Verify 1 for vrf_id in self.vrf_list: self.assert_equal(self.verify_vrf(vrf_id), VRFState.configured, VRFState) # Test 1 self.run_verify_test() self.run_crosswise_vrf_test() def test_ip6_vrf_02(self): """ IP6 VRF Multi-instance test 2 - reset 2 VRFs """ # Config 2 # Delete 2 VRFs self.reset_vrf_and_remove_from_vrf_list(1) self.reset_vrf_and_remove_from_vrf_list(2) # Verify 2 for vrf_id in self.vrf_reset_list: self.assert_equal(self.verify_vrf(vrf_id), VRFState.reset, VRFState) for vrf_id in self.vrf_list: self.assert_equal(self.verify_vrf(vrf_id), VRFState.configured, VRFState) # Test 2 self.run_verify_test() self.run_crosswise_vrf_test() # Reset routes learned from ICMPv6 Neighbor Discovery for vrf_id in self.vrf_reset_list: self.reset_vrf_and_remove_from_vrf_list(vrf_id) def test_ip6_vrf_03(self): """ IP6 VRF Multi-instance 3 - add 2 VRFs """ # Config 3 # Add 1 of reset VRFs and 1 new VRF self.create_vrf_and_assign_interfaces(1) self.create_vrf_and_assign_interfaces(1, start=5) # Verify 3 for vrf_id in self.vrf_reset_list: self.assert_equal(self.verify_vrf(vrf_id), VRFState.reset, VRFState) for vrf_id in self.vrf_list: self.assert_equal(self.verify_vrf(vrf_id), VRFState.configured, VRFState) # Test 3 self.run_verify_test() self.run_crosswise_vrf_test() # Reset routes learned from ICMPv6 Neighbor Discovery for vrf_id in self.vrf_reset_list: self.reset_vrf_and_remove_from_vrf_list(vrf_id) def test_ip6_vrf_04(self): """ IP6 VRF Multi-instance test 4 - reset 4 VRFs """ # Config 4 # Reset all VRFs (i.e. no VRF except VRF=0 configured) for i in range(len(self.vrf_list)): self.reset_vrf_and_remove_from_vrf_list(self.vrf_list[0]) # Verify 4 for vrf_id in self.vrf_reset_list: self.assert_equal(self.verify_vrf(vrf_id), VRFState.reset, VRFState) vrf_list_length = len(self.vrf_list) self.assertEqual( vrf_list_length, 0, "List of configured VRFs is not empty: %s != 0" % vrf_list_length) # Test 4 self.run_verify_test() self.run_crosswise_vrf_test() if __name__ == '__main__': unittest.main(testRunner=VppTestRunner)