NSB: fix port topology 91/41891/7
authorMartin Banszel <martinx.banszel@intel.com>
Wed, 19 Jul 2017 19:35:02 +0000 (19:35 +0000)
committerEdward MacGillivray <edward.s.macgillivray@intel.com>
Thu, 14 Sep 2017 22:46:38 +0000 (15:46 -0700)
Add a new PortPair class to resolve the
topology into list of public and private ports.

Before we were calculating public/private in multiple
locations and using different conventions.

In addition for all the DPDK test we need to use the DPDK
port number and no rely on interface ordering or interface naming
conventions.

We used to use  xe0 -> 0, xe1 -> 1, etc.  This is not the DPDK port
number.

Use the new dpdknicbind_helper class to parse the output of
dpdk-devbind.py to find the actual DPDK port number at runtime.

We then use this DPDK port number to correctly calculate the
port_mask_hex.

The port mask maps the DPDK port num (PMD ID) to the LINK ID
used in the pipeline config

We also need to make sure we only use the interfaces matched to the
topology and not use all the interfaces, because in some cases we will
have unused interfaces.  In particular TRex always requires an even
number of interfaces, so for single port TRex tests we have to create
the second port and not use it.

Thus we had to modify the traffic generator stats code to only dump
stats for used ports and no unused ports.

Ixia was using interface ordering to map to Ixia ports, instead we use
the dpdk_port_num which must be hardcoded for Ixia.

Renamed traffic_profile.execute to traffic_profile.execute_traffic so
we can trace the code easier.

We pass the port used by the traffic profile to generate_samples so we
don't get stats for unused ports.

Fixed up vPE config creation and bring up issues.

Fixed up CGNAPT and UDP_Replay to work correctly.

Tested with 4-port scale-out

Change-Id: I2e4f328bff2904108081e92a4bf712333fa73869
Signed-off-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Edward MacGillivray <edward.s.macgillivray@intel.com>
75 files changed:
samples/vnf_samples/nsut/acl/acl-tg-topology-3node.yaml
samples/vnf_samples/nsut/acl/tc_baremetal_rfc2544_ipv4_1rule_1flow_64B_trex_corelated_traffic.yaml
samples/vnf_samples/nsut/cgnapt/cgnapt-vnf-topology-3node.yaml
samples/vnf_samples/nsut/cgnapt/tc_baremetal_rfc2544_ipv4_1flow_64B_trex_corelated_traffic.yaml
samples/vnf_samples/nsut/ping/tc_ping_heat_context.yaml
samples/vnf_samples/nsut/vfw/tc_baremetal_rfc2544_ipv4_1rule_1flow_64B_trex_corelated_traffic.yaml
samples/vnf_samples/nsut/vpe/tc_baremetal_http_ipv4_ixload.yaml
samples/vnf_samples/nsut/vpe/tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml
samples/vnf_samples/nsut/vpe/tc_baremetal_rfc2544_ipv4_1flow_64B.yaml
samples/vnf_samples/nsut/vpe/tc_baremetal_rfc2544_ipv4_1flow_64B_ixia.yaml
samples/vnf_samples/nsut/vpe/tc_baremetal_rfc2544_ipv4_1flow_64B_trex_corelated_traffic.yaml
samples/vnf_samples/nsut/vpe/tc_baremetal_rfc2544_ipv4_1flow_IMIX.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput_cgnapt.yaml
samples/vnf_samples/traffic_profiles/ipv4_throughput_vpe.yaml
samples/vnf_samples/traffic_profiles/ixia_ipv4_latency.yaml
samples/vnf_samples/traffic_profiles/ixia_ipv4_latency_vpe.yaml
samples/vnf_samples/vnf_descriptors/acl_vnf.yaml
samples/vnf_samples/vnf_descriptors/cgnapt_vnf.yaml
samples/vnf_samples/vnf_descriptors/prox_vnf-1.yaml
samples/vnf_samples/vnf_descriptors/prox_vnf-2.yaml
samples/vnf_samples/vnf_descriptors/prox_vnf-4.yaml
samples/vnf_samples/vnf_descriptors/tg_rfc2544_tpl.yaml
samples/vnf_samples/vnf_descriptors/udp_replay_vnf.yaml
samples/vnf_samples/vnf_descriptors/vfw_vnf.yaml
tests/unit/benchmark/contexts/test_heat.py
tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
tests/unit/network_services/helpers/test_dpdkbindnic_helper.py [new file with mode: 0644]
tests/unit/network_services/helpers/test_samplevnf_helper.py
tests/unit/network_services/libs/ixia_libs/test_IxNet.py
tests/unit/network_services/nfvi/test_resource.py
tests/unit/network_services/traffic_profile/test_base.py
tests/unit/network_services/traffic_profile/test_fixed.py
tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py
tests/unit/network_services/traffic_profile/test_rfc2544.py
tests/unit/network_services/traffic_profile/test_traffic_profile.py
tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py
tests/unit/network_services/vnf_generic/vnf/test_base.py
tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py
tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
tests/unit/network_services/vnf_generic/vnf/test_prox_vnf.py
tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
tests/unit/network_services/vnf_generic/vnf/test_tg_ixload.py
tests/unit/network_services/vnf_generic/vnf/test_tg_ping.py
tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py
tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py
tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py
tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py
tests/unit/network_services/vnf_generic/vnf/test_udp_replay.py
tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py
tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py
yardstick/benchmark/contexts/heat.py
yardstick/benchmark/contexts/model.py
yardstick/benchmark/scenarios/networking/vnf_generic.py
yardstick/network_services/helpers/dpdknicbind_helper.py [new file with mode: 0644]
yardstick/network_services/helpers/samplevnf_helper.py
yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py
yardstick/network_services/nfvi/resource.py
yardstick/network_services/traffic_profile/base.py
yardstick/network_services/traffic_profile/ixia_rfc2544.py
yardstick/network_services/traffic_profile/rfc2544.py
yardstick/network_services/traffic_profile/traffic_profile.py
yardstick/network_services/vnf_generic/vnf/acl_vnf.py
yardstick/network_services/vnf_generic/vnf/base.py
yardstick/network_services/vnf_generic/vnf/cgnapt_vnf.py
yardstick/network_services/vnf_generic/vnf/prox_helpers.py
yardstick/network_services/vnf_generic/vnf/prox_vnf.py
yardstick/network_services/vnf_generic/vnf/sample_vnf.py
yardstick/network_services/vnf_generic/vnf/tg_ping.py
yardstick/network_services/vnf_generic/vnf/tg_prox.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
yardstick/network_services/vnf_generic/vnf/udp_replay.py
yardstick/network_services/vnf_generic/vnf/vfw_vnf.py
yardstick/network_services/vnf_generic/vnf/vpe_vnf.py

index f8c01da..36cb2e8 100644 (file)
@@ -40,7 +40,16 @@ nsd:nsd-catalog:
             -   member-vnf-index-ref: '2'
                 vnfd-connection-point-ref: xe0
                 vnfd-id-ref: vnf__1
-
+        -   id: private_2
+            name: tg__1 to vnf__1 link 2
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: tg__1
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: tg__1
         -   id: public_1
             name: vnf__1 to tg__2 link 2
             type: ELAN
index aea127a..1261aa0 100644 (file)
@@ -33,7 +33,7 @@ scenarios:
     traffic_type: 4
     rfc2544:
       allowed_drop_rate: 0.0001 - 0.0001
-      corelated_traffic: true
+      correlated_traffic: true
     vnf__1:
       rules: acl_1rule.yaml
       vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1}
index 24407dc..7b681b5 100644 (file)
@@ -40,7 +40,16 @@ nsd:nsd-catalog:
             -   member-vnf-index-ref: '2'
                 vnfd-connection-point-ref: xe0
                 vnfd-id-ref: vnf__1
-
+        -   id: private_2
+            name: tg__1 to vnf__1 link 2
+            type: ELAN
+            vnfd-connection-point-ref:
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: tg__1
+            -   member-vnf-index-ref: '1'
+                vnfd-connection-point-ref: xe1
+                vnfd-id-ref: tg__1
         -   id: public_1
             name: vnf__1 to tg__2 link 2
             type: ELAN
index 38549f0..f110ab2 100644 (file)
@@ -28,19 +28,19 @@ scenarios:
       public: {64B: 100}
     flow:
       src_ip: [{'tg__1': 'xe0'}]
-      dst_ip: [{'tg__2': 'xe0'}
+      dst_ip: [{'tg__2': 'xe0'}]
       count: 1
     traffic_type: 4
     rfc2544:
       allowed_drop_rate: 0.0001 - 0.0001
-      corelated_traffic: true
+      correlated_traffic: true
     vnf__1:
       vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1}
       napt: 'dynamic'
       nfvi_enable: True
   runner:
     type: Iteration
-    iterations: 10
+    iterations: 14
     interval: 35
 context:
   type: Node
index 394523f..d6f096b 100644 (file)
@@ -31,7 +31,7 @@ scenarios:
 
 context:
   name: yardstick
-  image: yardstick-image
+  image: yardstick-samplevnfs
   flavor: yardstick-flavor
   user: ubuntu
 
index cadc428..6a55bfb 100644 (file)
@@ -33,7 +33,7 @@ scenarios:
     traffic_type: 4
     rfc2544:
       allowed_drop_rate: 0.0001 - 0.0001
-      corelated_traffic: true
+      correlated_traffic: true
     vnf__1:
       rules: acl_1rule.yaml
       vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1}
index 4dd6d81..a401793 100644 (file)
@@ -31,8 +31,8 @@ scenarios:
       count: 1
     traffic_type: 4
     vnf__1:
-      cfg: vpe_config
       nfvi_enable: True
+      vnf_config: vpe_config
   runner:
     type: Duration
     duration: 4
index 8029ba3..bff9743 100644 (file)
@@ -33,8 +33,8 @@ scenarios:
     rfc2544:
       allowed_drop_rate: 0.0001 - 0.0001
     vnf__1:
-      cfg: vpe_config
       nfvi_enable: True
+      vnf_config: vpe_config
   runner:
     type: Iteration
     iterations: 10
index d393aa7..50874ac 100644 (file)
@@ -33,8 +33,8 @@ scenarios:
     rfc2544:
       allowed_drop_rate: 0.0001 - 0.0001
     vnf__1:
-      cfg: vpe_config
       nfvi_enable: True
+      vnf_config: vpe_config
   runner:
     type: Iteration
     iterations: 10
index f33d869..394d078 100644 (file)
@@ -33,8 +33,8 @@ scenarios:
     rfc2544:
       allowed_drop_rate: 0.0001 - 0.0001
     vnf__1:
-      cfg: vpe_config
       nfvi_enable: True
+      vnf_config: vpe_config
   runner:
     type: Iteration
     iterations: 10
index 91099fd..972d58b 100644 (file)
@@ -33,10 +33,10 @@ scenarios:
     traffic_type: 4
     rfc2544:
       allowed_drop_rate: 0.0001 - 0.0001
-      corelated_traffic: true
+      correlated_traffic: true
     vnf__1:
-      cfg: vpe_config
       nfvi_enable: True
+      vnf_config: vpe_config
   runner:
     type: Iteration
     iterations: 10
index e237dca..092f068 100644 (file)
@@ -34,8 +34,8 @@ scenarios:
     rfc2544:
       allowed_drop_rate: 0.0001 - 0.0001
     vnf__1:
-      cfg: vpe_config
       nfvi_enable: True
+      vnf_config: vpe_config
   runner:
     type: Iteration
     iterations: 10
index 98624b1..6e0c693 100644 (file)
@@ -61,14 +61,14 @@ private_1:
 
         outer_l3v4:
             proto: "udp"
-            srcip4: "{{get(flow, 'flow.src_ip0', '1.1.1.1-1.1.255.255') }}"
-            dstip4: "{{get(flow, 'flow.dst_ip0', '90.90.1.1-90.90.255.255') }}"
+            srcip4: "{{get(flow, 'flow.src_ip_0', '1.1.1.1-1.1.255.255') }}"
+            dstip4: "{{get(flow, 'flow.dst_ip_0', '90.90.1.1-90.90.255.255') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 0
         outer_l4:
-            srcport: "{{get(flow, 'flow.src_port0', '1234-4321') }}"
-            dstport: "{{get(flow, 'flow.dst_port0', '2001-4001') }}"
+            srcport: "{{get(flow, 'flow.src_port_0', '1234-4321') }}"
+            dstport: "{{get(flow, 'flow.dst_port_0', '2001-4001') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
 public_1:
       ipv4:
@@ -86,12 +86,12 @@ public_1:
 
         outer_l3v4:
             proto: "udp"
-            srcip4: "{{get(flow, 'flow.dst_ip0', '90.90.1.1-90.90.255.255') }}"
-            dstip4: "{{get(flow, 'flow.src_ip0', '1.1.1.1-1.1.255.255') }}"
+            srcip4: "{{get(flow, 'flow.dst_ip_0', '90.90.1.1-90.90.255.255') }}"
+            dstip4: "{{get(flow, 'flow.src_ip_0', '1.1.1.1-1.1.255.255') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 0
         outer_l4:
-            srcport: "{{get(flow, 'flow.dst_port0', '1234-4321') }}"
-            dstport: "{{get(flow, 'flow.src_port0', '2001-4001') }}"
+            srcport: "{{get(flow, 'flow.dst_port_0', '1234-4321') }}"
+            dstport: "{{get(flow, 'flow.src_port_0', '2001-4001') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
index 0758cf3..df04a93 100644 (file)
@@ -61,14 +61,14 @@ private_1:
 
         outer_l3v4:
             proto: "udp"
-            srcip4: "{{get(flow, 'flow.src_ip0', '10.0.2.1-10.0.2.255') }}"
-            dstip4: "{{get(flow, 'flow.dst_ip0', '10.0.3.1-10.0.3.255') }}"
+            srcip4: "{{get(flow, 'flow.src_ip_0', '10.0.2.1-10.0.2.255') }}"
+            dstip4: "{{get(flow, 'flow.dst_ip_0', '10.0.3.1-10.0.3.255') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 0
         outer_l4:
-            srcport: "{{get(flow, 'flow.src_port0', '1234-4321') }}"
-            dstport: "{{get(flow, 'flow.dst_port0', '2001-4001') }}"
+            srcport: "{{get(flow, 'flow.src_port_0', '1234-4321') }}"
+            dstport: "{{get(flow, 'flow.dst_port_0', '2001-4001') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
 public_1:
       ipv4:
@@ -86,12 +86,12 @@ public_1:
 
         outer_l3v4:
             proto: "udp"
-            srcip4: "{{get(flow, 'flow.dst_ip0', '10.0.3.1-10.0.3.255') }}"
-            dstip4: "{{get(flow, 'flow.public_ip0', '10.0.2.1-10.0.2.255') }}"
+            srcip4: "{{get(flow, 'flow.dst_ip_0', '10.0.3.1-10.0.3.255') }}"
+            dstip4: "{{get(flow, 'flow.public_ip_0', '10.0.2.1-10.0.2.255') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 0
         outer_l4:
-            srcport: "{{get(flow, 'flow.dst_port0', '1234-4321') }}"
-            dstport: "{{get(flow, 'flow.src_port0', '2001-4001') }}"
+            srcport: "{{get(flow, 'flow.dst_port_0', '1234-4321') }}"
+            dstport: "{{get(flow, 'flow.src_port_0', '2001-4001') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
index 233457e..da9bc40 100644 (file)
@@ -71,14 +71,16 @@ private_1:
 
         outer_l3v4:
             proto: "tcp"
-            srcip4: "{{get(flow, 'flow.src_ip0', '192.168.0.0-192.168.255.255') }}"
-            dstip4: "{{get(flow, 'flow.dst_ip0', '192.16.0.0-192.16.0.31') }}"
+            srcip4: "{{get(flow, 'flow.src_ip_0', '192.168.0.0-192.168.255.255') }}"
+            dstip4: "{{get(flow, 'flow.dst_ip_0', '192.16.0.0-192.16.0.31') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 32
 
         outer_l4:
-            srcport: "{{get(flow, 'flow.src_port0', '0') }}"
-            dstport: "{{get(flow, 'flow.dst_port0', '0') }}"
+            srcport: "{{get(flow, 'flow.src_port_0', '0') }}"
+            dstport: "{{get(flow, 'flow.dst_port_0', '0') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
 public_1:
       ipv4:
         outer_l2:
@@ -93,14 +95,16 @@ public_1:
 
         outer_l3v4:
             proto: "tcp"
-            srcip4: "{{get(flow, 'flow.dst_ip0', '192.16.0.0-192.16.0.31') }}"
-            dstip4: "{{get(flow, 'flow.src_ip0', '192.168.0.0-192.168.255.255') }}"
+            srcip4: "{{get(flow, 'flow.dst_ip_0', '192.16.0.0-192.16.0.31') }}"
+            dstip4: "{{get(flow, 'flow.src_ip_0', '192.168.0.0-192.168.255.255') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 32
 
         outer_l4:
-            srcport: "{{get(flow, 'flow.dst_port0', '0') }}"
-            dstport: "{{get(flow, 'flow.src_port0', '0') }}"
+            srcport: "{{get(flow, 'flow.dst_port_0', '0') }}"
+            dstport: "{{get(flow, 'flow.src_port_0', '0') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
 private_2:
       ipv4:
         outer_l2:
@@ -129,12 +133,14 @@ private_2:
             proto: "tcp"
             srcip4: "{{get(flow, 'flow.src_ip1', '192.168.0.0-192.168.255.255') }}"
             dstip4: "{{get(flow, 'flow.dst_ip1', '192.16.0.0-192.16.0.31') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 32
 
         outer_l4:
             srcport: "{{get(flow, 'flow.src_port1', '0') }}"
             dstport: "{{get(flow, 'flow.dst_port1', '0') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
 public_2:
       ipv4:
         outer_l2:
@@ -151,9 +157,11 @@ public_2:
             proto: "tcp"
             srcip4: "{{get(flow, 'flow.dst_ip1', '192.16.0.0-192.16.0.31') }}"
             dstip4: "{{get(flow, 'flow.src_ip1', '192.168.0.0-192.168.255.255') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 32
 
         outer_l4:
             srcport: "{{get(flow, 'flow.dst_port1', '0') }}"
             dstport: "{{get(flow, 'flow.src_port1', '0') }}"
+            count: "{{get(flow, 'flow.count', '1') }}"
index c53b4fa..a008eb3 100644 (file)
@@ -47,14 +47,14 @@ private_1:
 
         outer_l3v4:
             proto: "udp"
-            srcip4: "{{get(flow, 'flow.src_ip0', '1.1.1.1-1.15.255.255') }}"
-            dstip4: "{{get(flow, 'flow.dst_ip0', '90.90.1.1-90.105.255.255') }}"
+            srcip4: "{{get(flow, 'flow.src_ip_0', '1.1.1.1-1.15.255.255') }}"
+            dstip4: "{{get(flow, 'flow.dst_ip_0', '90.90.1.1-90.105.255.255') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 0
         outer_l4:
-            srcport: "{{get(flow, 'flow.src_port0', '1234') }}"
-            dstport: "{{get(flow, 'flow.dst_port0', '2001') }}"
+            srcport: "{{get(flow, 'flow.src_port_0', '1234') }}"
+            dstport: "{{get(flow, 'flow.dst_port_0', '2001') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
 public_1:
       ipv4:
@@ -72,14 +72,14 @@ public_1:
 
         outer_l3v4:
             proto: "udp"
-            srcip4: "{{get(flow, 'flow.dst_ip0', '1.1.1.1-1.15.255.255') }}"
-            dstip4: "{{get(flow, 'flow.src_ip0', '90.90.1.1-90.105.255.255') }}"
+            srcip4: "{{get(flow, 'flow.dst_ip_0', '1.1.1.1-1.15.255.255') }}"
+            dstip4: "{{get(flow, 'flow.src_ip_0', '90.90.1.1-90.105.255.255') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 0
         outer_l4:
-            srcport: "{{get(flow, 'flow.src_port0', '1234') }}"
-            dstport: "{{get(flow, 'flow.dst_port0', '2001') }}"
+            srcport: "{{get(flow, 'flow.src_port_0', '1234') }}"
+            dstport: "{{get(flow, 'flow.dst_port_0', '2001') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
 private_2:
       ipv4:
index 7468dbd..7ca2f10 100644 (file)
@@ -68,15 +68,15 @@ private_1:
 
         outer_l3v4:
             proto: "tcp"
-            srcip4: "{{get(flow, 'flow.src_ip0', '192.168.0.0-192.168.255.255') }}"
-            dstip4: "{{get(flow, 'flow.dst_ip0', '192.16.0.0-192.16.0.31') }}"
+            srcip4: "{{get(flow, 'flow.src_ip_0', '192.168.0.0-192.168.255.255') }}"
+            dstip4: "{{get(flow, 'flow.dst_ip_0', '192.16.0.0-192.16.0.31') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 32
 
         outer_l4:
-            srcport: "{{get(flow, 'flow.src_port0', '0') }}"
-            dstport: "{{get(flow, 'flow.dst_port0', '0') }}"
+            srcport: "{{get(flow, 'flow.src_port_0', '0') }}"
+            dstport: "{{get(flow, 'flow.dst_port_0', '0') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
 public_1:
       ipv4:
@@ -92,15 +92,15 @@ public_1:
 
         outer_l3v4:
             proto: "tcp"
-            srcip4: "{{get(flow, 'flow.dst_ip0', '192.16.0.0-192.16.0.31') }}"
-            dstip4: "{{get(flow, 'flow.src_ip0', '192.168.0.0-192.168.255.255') }}"
+            srcip4: "{{get(flow, 'flow.dst_ip_0', '192.16.0.0-192.16.0.31') }}"
+            dstip4: "{{get(flow, 'flow.src_ip_0', '192.168.0.0-192.168.255.255') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
             ttl: 32
             dscp: 32
 
         outer_l4:
-            srcport: "{{get(flow, 'flow.dst_port0', '0') }}"
-            dstport: "{{get(flow, 'flow.src_port0', '0') }}"
+            srcport: "{{get(flow, 'flow.dst_port_0', '0') }}"
+            dstport: "{{get(flow, 'flow.src_port_0', '0') }}"
             count: "{{get(flow, 'flow.count', '1') }}"
 private_2:
       ipv4:
index b38e6b8..62188b8 100644 (file)
@@ -32,11 +32,6 @@ vnfd:vnfd-catalog:
             {% if key_filename is defined %}
             key_filename: '{{key_filename}}'  # Value filled by vnfdgen
             {% endif %}
-        connection-point:
-        -   name: xe0
-            type: VPORT
-        -   name: xe1
-            type: VPORT
         vdu:
         -   id: aclvnf-baremetal
             name: aclvnf-baremetal
@@ -44,37 +39,6 @@ vnfd:vnfd-catalog:
             vm-flavor:
                 vcpu-count: '4'
                 memory-mb: '4096'
-            external-interface:
-            -   name: xe0
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe0.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe0.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe0.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe0.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe0
-            -   name: xe1
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe1.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe1.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe1.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe1.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe1.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe1.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe1.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe1.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe1.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe1
             routing_table: {{ routing_table }}
             nd_route_tbl: {{ nd_route_tbl }}
         benchmark:
index b42fb4d..da774cc 100644 (file)
@@ -34,42 +34,10 @@ vnfd:vnfd-catalog:
             {% if key_filename is defined %}
             key_filename: '{{key_filename}}'  # Value filled by vnfdgen
             {% endif %}
-        connection-point:
-        -   name: xe0
-            type: VPORT
-        -   name: xe1
-            type: VPORT
         vdu:
         -   id: cgnaptvnf-baremetal
             name: cgnaptvnf-baremetal
             description: CGNAPT approximation using DPDK
-            external-interface:
-            -   name: xe0
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe0.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe0.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe0
-            -   name: xe1
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe1.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe1.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe1.local_ip }}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe1.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe1.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe1.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe1.dst_mac }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe1
             routing_table: {{ routing_table }}
             nd_route_tbl: {{ nd_route_tbl }}
         benchmark:
index 76eaad8..3b3739f 100644 (file)
@@ -42,22 +42,6 @@ vnfd:vnfd-catalog:
             vm-flavor:
                 vcpu-count: '4'
                 memory-mb: '4096'
-            external-interface:
-            -   name: xe0
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe0.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe0.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe0.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe0.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe0
             routing_table: {{ routing_table }}
             nd_route_tbl: {{ nd_route_tbl }}
         benchmark:
index b02690e..75c16ba 100644 (file)
@@ -44,37 +44,6 @@ vnfd:vnfd-catalog:
             vm-flavor:
                 vcpu-count: '4'
                 memory-mb: '4096'
-            external-interface:
-            -   name: xe0
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe0.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe0.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe0.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe0.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe0
-            -   name: xe1
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe1.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe1.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe1.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe1.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe1.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe1.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe1.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe1.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe1.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe1
             routing_table: {{ routing_table }}
             nd_route_tbl: {{ nd_route_tbl }}
         benchmark:
index 0f8aa55..75c16ba 100644 (file)
@@ -44,67 +44,6 @@ vnfd:vnfd-catalog:
             vm-flavor:
                 vcpu-count: '4'
                 memory-mb: '4096'
-            external-interface:
-            -   name: xe0
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe0.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe0.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe0.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe0.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe0
-            -   name: xe1
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe1.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe1.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe1.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe1.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe1.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe1.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe1.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe1.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe1.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe1
-            -   name: xe2
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe2.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe2.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe2.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe2.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe2.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe2.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe2.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe2.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe2.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe2
-            -   name: xe3
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe3.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe3.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe3.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe3.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe3.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe3.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe3.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe3.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe3.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe3
             routing_table: {{ routing_table }}
             nd_route_tbl: {{ nd_route_tbl }}
         benchmark:
index dee3dd7..d94ddfe 100644 (file)
@@ -32,41 +32,10 @@ vnfd:vnfd-catalog:
             {% if key_filename is defined %}
             key_filename: '{{key_filename}}'  # Value filled by vnfdgen
             {% endif %}
-        connection-point:
-        -   name: xe0
-            type: VPORT
-        -   name: xe1
-            type: VPORT
         vdu:
         -   id: trexgen-baremetal
             name: trexgen-baremetal
             description: TRex stateless traffic verifier
-            external-interface:
-            -   name: xe0
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
-                    local_iface_name: '{{ interfaces.xe0.local_iface_name }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe0.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe0
-            -   name: xe1
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    vpci: '{{ interfaces.xe1.vpci }}' # Value filled by vnfdgen
-                    local_iface_name: '{{ interfaces.xe1.local_iface_name }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe1.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe1.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe1.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe1.local_mac }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe1.dst_mac }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe1
 
         benchmark:
             kpi:
index 33c07a6..659807d 100644 (file)
@@ -35,42 +35,10 @@ vnfd:vnfd-catalog:
             {% if key_filename is defined %}
             key_filename: '{{key_filename}}'  # Value filled by vnfdgen
             {% endif %}
-        connection-point:
-        -   name: xe0
-            type: VPORT
-        -   name: xe1
-            type: VPORT
         vdu:
         -   id: udp_replayvnf-baremetal
             name: udp_replayvnf-baremetal
             description: UdpReplayVnf approximation using DPDK
-            external-interface:
-            -   name: xe0
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe0.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe0.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe0
-            -   name: xe1
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe1.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe1.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe1.local_ip }}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe1.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe1.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe1.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe1.dst_mac }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe1
         benchmark:
             kpi:
                 - packets_in
index 1c272e6..035c733 100644 (file)
@@ -32,11 +32,6 @@ vnfd:vnfd-catalog:
             {% if key_filename is defined %}
             key_filename: '{{key_filename}}'  # Value filled by vnfdgen
             {% endif %}
-        connection-point:
-        -   name: xe0
-            type: VPORT
-        -   name: xe1
-            type: VPORT
         vdu:
         -   id: aclvnf-baremetal
             name: aclvnf-baremetal
@@ -44,37 +39,6 @@ vnfd:vnfd-catalog:
             vm-flavor:
                 vcpu-count: '4'
                 memory-mb: '4096'
-            external-interface:
-            -   name: xe0
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe0.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe0.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe0.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe0.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe0
-            -   name: xe1
-                virtual-interface:
-                    type: PCI-PASSTHROUGH
-                    # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
-                    vpci: '{{ interfaces.xe1.vpci }}' # Value filled by vnfdgen
-                    dpdk_port_num:   '{{ interfaces.xe1.dpdk_port_num }}' # Value filled by vnfdgen
-                    local_ip: '{{ interfaces.xe1.local_ip }}' # Value filled by vnfdgen
-                    driver: '{{ interfaces.xe1.driver}}' # Value filled by vnfdgen
-                    dst_ip: '{{ interfaces.xe1.dst_ip }}' # Value filled by vnfdgen
-                    local_mac: '{{ interfaces.xe1.local_mac }}' # Value filled by vnfdgen
-                    netmask: '{{ interfaces.xe1.netmask }}' # Value filled by vnfdgen
-                    dst_mac: '{{ interfaces.xe1.dst_mac }}' # Value filled by vnfdgen
-                    vld_id:  '{{ interfaces.xe1.vld_id }}' # Value filled by vnfdgen
-                    bandwidth: 10 Gbps
-                vnfd-connection-point-ref: xe1
             routing_table: {{ routing_table }}
             nd_route_tbl: {{ nd_route_tbl }}
         benchmark:
index 582d9ab..d1b5855 100644 (file)
@@ -182,11 +182,17 @@ class HeatContextTestCase(unittest.TestCase):
             u'd-mac_address': u'00:10',
             u'd-device_id': u'dev43',
             u'd-network_id': u'net987',
+            u'e': u'40.30.20.15',
+            u'e-subnet_id': 2,
+            u'e-mac_address': u'00:10',
+            u'e-device_id': u'dev43',
+            u'e-network_id': u'net987',
         }
         server = mock.MagicMock()
         server.ports = OrderedDict([
-            ('a', {'stack_name': 'b', 'port': 'port_a'}),
-            ('c', {'stack_name': 'd', 'port': 'port_c'}),
+            ('a', [{'stack_name': 'b', 'port': 'port_a'}]),
+            ('c', [{'stack_name': 'd', 'port': 'port_c'},
+                   {'stack_name': 'e', 'port': 'port_f'}]),
         ])
 
         expected = {
@@ -205,7 +211,7 @@ class HeatContextTestCase(unittest.TestCase):
         }
         self.test_context.add_server_port(server)
         self.assertEqual(server.private_ip, '10.20.30.45')
-        self.assertEqual(len(server.interfaces), 2)
+        self.assertEqual(len(server.interfaces), 3)
         self.assertDictEqual(server.interfaces['port_a'], expected)
 
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
index 58244b8..8aa9a8c 100644 (file)
@@ -24,6 +24,8 @@ import errno
 import unittest
 import mock
 
+from copy import deepcopy
+
 from tests.unit import STL_MOCKS
 from yardstick.benchmark.scenarios.networking.vnf_generic import \
     SshManager, NetworkServiceTestCase, IncorrectConfig, \
@@ -365,6 +367,24 @@ class TestNetworkServiceTestCase(unittest.TestCase):
         result = '152.16.100.2-152.16.100.254'
         self.assertEqual(result, self.s._get_ip_flow_range({"tg__1": 'xe0'}))
 
+    @mock.patch('yardstick.benchmark.scenarios.networking.vnf_generic.ipaddress')
+    def test__get_ip_flow_range_no_node_data(self, mock_ipaddress):
+        scenario_cfg = deepcopy(self.scenario_cfg)
+        scenario_cfg["traffic_options"]["flow"] = \
+            self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
+
+        mock_ipaddress.ip_network.return_value = ipaddr = mock.Mock()
+        ipaddr.hosts.return_value = []
+
+        expected = '0.0.0.0'
+        result = self.s._get_ip_flow_range({"tg__2": 'xe0'})
+        self.assertEqual(result, expected)
+
+    def test__get_ip_flow_range_no_nodes(self):
+        expected = '0.0.0.0'
+        result = self.s._get_ip_flow_range({})
+        self.assertEqual(result, expected)
+
     def test___get_traffic_flow(self):
         self.scenario_cfg["traffic_options"]["flow"] = \
             self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
@@ -653,12 +673,6 @@ class TestNetworkServiceTestCase(unittest.TestCase):
         res = NetworkServiceTestCase.parse_netdev_info(output)
         assert res == self.SAMPLE_VM_NETDEVS
 
-    def test_sort_dpdk_port_num(self):
-        netdevs = self.SAMPLE_NETDEVS.copy()
-        NetworkServiceTestCase._sort_dpdk_port_num(netdevs)
-        assert netdevs['lan']['dpdk_port_num'] == 0
-        assert netdevs['enp11s0']['dpdk_port_num'] == 1
-
     def test_probe_missing_values(self):
         netdevs = self.SAMPLE_NETDEVS.copy()
         network = {'local_mac': '0a:de:ad:be:ef:f5'}
diff --git a/tests/unit/network_services/helpers/test_dpdkbindnic_helper.py b/tests/unit/network_services/helpers/test_dpdkbindnic_helper.py
new file mode 100644 (file)
index 0000000..dbd8396
--- /dev/null
@@ -0,0 +1,247 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016-2017 Intel Corporation
+#
+# 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.
+
+import mock
+import unittest
+from yardstick.network_services.helpers.dpdknicbind_helper import DpdkBindHelper
+from yardstick.network_services.helpers.dpdknicbind_helper import DpdkBindHelperException
+from yardstick.network_services.helpers.dpdknicbind_helper import NETWORK_KERNEL
+from yardstick.network_services.helpers.dpdknicbind_helper import NETWORK_DPDK
+from yardstick.network_services.helpers.dpdknicbind_helper import CRYPTO_KERNEL
+from yardstick.network_services.helpers.dpdknicbind_helper import CRYPTO_DPDK
+from yardstick.network_services.helpers.dpdknicbind_helper import NETWORK_OTHER
+from yardstick.network_services.helpers.dpdknicbind_helper import CRYPTO_OTHER
+
+pass
+
+
+class MyTestDpdkBindHelper(unittest.TestCase):
+    EXAMPLE_OUTPUT = """
+
+Network devices using DPDK-compatible driver
+============================================
+0000:00:04.0 'Virtio network device' drv=igb_uio unused=
+0000:00:05.0 'Virtio network device' drv=igb_uio unused=
+
+Network devices using kernel driver
+===================================
+0000:00:03.0 'Virtio network device' if=ens3 drv=virtio-pci unused=igb_uio *Active*
+
+Other network devices
+=====================
+<none>
+
+Crypto devices using DPDK-compatible driver
+===========================================
+<none>
+
+Crypto devices using kernel driver
+==================================
+<none>
+
+Other crypto devices
+====================
+<none>
+"""
+
+    PARSED_EXAMPLE = {
+        NETWORK_DPDK: [
+            {'active': False,
+             'dev_type': 'Virtio network device',
+             'driver': 'igb_uio',
+             'iface': None,
+             'unused': '',
+             'vpci': '0000:00:04.0',
+             },
+            {'active': False,
+             'dev_type': 'Virtio network device',
+             'driver': 'igb_uio',
+             'iface': None,
+             'unused': '',
+             'vpci': '0000:00:05.0',
+             }
+        ],
+        NETWORK_KERNEL: [
+            {'active': True,
+             'dev_type': 'Virtio network device',
+             'driver': 'virtio-pci',
+             'iface': 'ens3',
+             'unused': 'igb_uio',
+             'vpci': '0000:00:03.0',
+             }
+        ],
+        CRYPTO_KERNEL: [],
+        CRYPTO_DPDK: [],
+        NETWORK_OTHER: [],
+        CRYPTO_OTHER: [],
+    }
+
+    CLEAN_STATUS = {
+        NETWORK_KERNEL: [],
+        NETWORK_DPDK: [],
+        CRYPTO_KERNEL: [],
+        CRYPTO_DPDK: [],
+        NETWORK_OTHER: [],
+        CRYPTO_OTHER: [],
+    }
+
+    ONE_INPUT_LINE = ("0000:00:03.0 'Virtio network device' if=ens3 "
+                      "drv=virtio-pci unused=igb_uio *Active*")
+
+    ONE_INPUT_LINE_PARSED = [{
+        'vpci': '0000:00:03.0',
+        'dev_type': 'Virtio network device',
+        'iface': 'ens3',
+        'driver': 'virtio-pci',
+        'unused': 'igb_uio',
+        'active': True,
+    }]
+
+    def test___init__(self):
+        conn = mock.Mock()
+        conn.provision_tool = mock.Mock(return_value='path_to_tool')
+
+        dpdk_bind_helper = DpdkBindHelper(conn)
+
+        self.assertEquals(conn, dpdk_bind_helper.ssh_helper)
+        self.assertEquals(self.CLEAN_STATUS, dpdk_bind_helper.dpdk_status)
+        self.assertIsNone(dpdk_bind_helper.status_nic_row_re)
+        self.assertIsNone(dpdk_bind_helper._dpdk_nic_bind_attr)
+        self.assertIsNone(dpdk_bind_helper._status_cmd_attr)
+
+    def test__dpdk_execute(self):
+        conn = mock.Mock()
+        conn.execute = mock.Mock(return_value=(0, 'output', 'error'))
+        conn.provision_tool = mock.Mock(return_value='tool_path')
+        dpdk_bind_helper = DpdkBindHelper(conn)
+        self.assertEquals((0, 'output', 'error'), dpdk_bind_helper._dpdk_execute('command'))
+
+    def test__dpdk_execute_failure(self):
+        conn = mock.Mock()
+        conn.execute = mock.Mock(return_value=(1, 'output', 'error'))
+        conn.provision_tool = mock.Mock(return_value='tool_path')
+        dpdk_bind_helper = DpdkBindHelper(conn)
+        with self.assertRaises(DpdkBindHelperException):
+            dpdk_bind_helper._dpdk_execute('command')
+
+    def test__addline(self):
+        conn = mock.Mock()
+
+        dpdk_bind_helper = DpdkBindHelper(conn)
+
+        dpdk_bind_helper._addline(NETWORK_KERNEL, self.ONE_INPUT_LINE)
+
+        self.assertIsNotNone(dpdk_bind_helper.dpdk_status)
+        self.assertEquals(self.ONE_INPUT_LINE_PARSED, dpdk_bind_helper.dpdk_status[NETWORK_KERNEL])
+
+    def test__switch_active_dict_by_header(self):
+        line = "Crypto devices using DPDK-compatible driver"
+        olddict = 'olddict'
+        self.assertEqual(CRYPTO_DPDK, DpdkBindHelper._switch_active_dict(line, olddict))
+
+    def test__switch_active_dict_by_header_empty(self):
+        line = "<none>"
+        olddict = 'olddict'
+        self.assertEqual(olddict, DpdkBindHelper._switch_active_dict(line, olddict))
+
+    def test_parse_dpdk_status_output(self):
+        conn = mock.Mock()
+
+        dpdk_bind_helper = DpdkBindHelper(conn)
+
+        dpdk_bind_helper.parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
+
+        self.maxDiff = None
+        self.assertEquals(self.PARSED_EXAMPLE, dpdk_bind_helper.dpdk_status)
+
+    def test_read_status(self):
+        conn = mock.Mock()
+        conn.execute = mock.Mock(return_value=(0, self.EXAMPLE_OUTPUT, ''))
+        conn.provision_tool = mock.Mock(return_value='path_to_tool')
+
+        dpdk_bind_helper = DpdkBindHelper(conn)
+
+        self.assertEquals(self.PARSED_EXAMPLE, dpdk_bind_helper.read_status())
+
+    def test__get_bound_pci_addresses(self):
+        conn = mock.Mock()
+
+        dpdk_bind_helper = DpdkBindHelper(conn)
+
+        dpdk_bind_helper.parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
+
+        self.assertEquals(['0000:00:04.0', '0000:00:05.0'],
+                          dpdk_bind_helper._get_bound_pci_addresses(NETWORK_DPDK))
+        self.assertEquals(['0000:00:03.0'],
+                          dpdk_bind_helper._get_bound_pci_addresses(NETWORK_KERNEL))
+
+    def test_interface_driver_map(self):
+        conn = mock.Mock()
+
+        dpdk_bind_helper = DpdkBindHelper(conn)
+
+        dpdk_bind_helper.parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
+
+        self.assertEquals({'0000:00:04.0': 'igb_uio',
+                           '0000:00:03.0': 'virtio-pci',
+                           '0000:00:05.0': 'igb_uio',
+                           },
+                          dpdk_bind_helper.interface_driver_map)
+
+    def test_bind(self):
+        conn = mock.Mock()
+        conn.execute = mock.Mock(return_value=(0, '', ''))
+        conn.provision_tool = mock.Mock(return_value='/opt/nsb_bin/dpdk_nic_bind.py')
+
+        dpdk_bind_helper = DpdkBindHelper(conn)
+        dpdk_bind_helper.read_status = mock.Mock()
+
+        dpdk_bind_helper.bind(['0000:00:03.0', '0000:00:04.0'], 'my_driver')
+
+        conn.execute.assert_called_with('sudo /opt/nsb_bin/dpdk_nic_bind.py --force '
+                                        '-b my_driver 0000:00:03.0 0000:00:04.0')
+        dpdk_bind_helper.read_status.assert_called_once()
+
+    def test_rebind_drivers(self):
+        conn = mock.Mock()
+
+        dpdk_bind_helper = DpdkBindHelper(conn)
+
+        dpdk_bind_helper.bind = mock.Mock()
+        dpdk_bind_helper.used_drivers = {
+            '0000:05:00.0': 'd1',
+            '0000:05:01.0': 'd3',
+        }
+
+        dpdk_bind_helper.rebind_drivers()
+
+        dpdk_bind_helper.bind.assert_any_call('0000:05:00.0', 'd1', True)
+        dpdk_bind_helper.bind.assert_any_call('0000:05:01.0', 'd3', True)
+
+    def test_save_used_drivers(self):
+        conn = mock.Mock()
+        dpdk_bind_helper = DpdkBindHelper(conn)
+        dpdk_bind_helper.dpdk_status = self.PARSED_EXAMPLE
+
+        dpdk_bind_helper.save_used_drivers()
+
+        expected = {
+            '0000:00:04.0': 'igb_uio',
+            '0000:00:05.0': 'igb_uio',
+            '0000:00:03.0': 'virtio-pci',
+        }
+
+        self.assertEqual(expected, dpdk_bind_helper.used_drivers)
index 608f317..3d3f6dc 100644 (file)
 from __future__ import absolute_import
 from __future__ import division
 
-import os
 import unittest
 
 import mock
 
-from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
+from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig, PortPairs
+from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
+
+
+class TestPortPairs(unittest.TestCase):
+    def test_port_pairs_list(self):
+        vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        interfaces = vnfd['vdu'][0]['external-interface']
+        port_pairs = PortPairs(interfaces)
+        self.assertEqual(port_pairs.port_pair_list, [("xe0", "xe1")])
+
+    def test_valid_networks(self):
+        vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        interfaces = vnfd['vdu'][0]['external-interface']
+        port_pairs = PortPairs(interfaces)
+        self.assertEqual(port_pairs.valid_networks, [("private_0", "public_0")])
+
+    def test_all_ports(self):
+        vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        interfaces = vnfd['vdu'][0]['external-interface']
+        port_pairs = PortPairs(interfaces)
+        self.assertEqual(set(port_pairs.all_ports), {"xe0", "xe1"})
+
+    def test_priv_ports(self):
+        vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        interfaces = vnfd['vdu'][0]['external-interface']
+        port_pairs = PortPairs(interfaces)
+        self.assertEqual(port_pairs.priv_ports, ["xe0"])
+
+    def test_pub_ports(self):
+        vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        interfaces = vnfd['vdu'][0]['external-interface']
+        port_pairs = PortPairs(interfaces)
+        self.assertEqual(port_pairs.pub_ports, ["xe1"])
 
 
 class TestMultiPortConfig(unittest.TestCase):
-    VNFD = {'vnfd:vnfd-catalog':
-                {'vnfd':
-                     [{'short-name': 'VpeVnf',
-                       'vdu':
-                           [{'routing_table':
-                                 [{'network': '152.16.100.20',
-                                   'netmask': '255.255.255.0',
-                                   'gateway': '152.16.100.20',
-                                   'if': 'xe0'},
-                                  {'network': '152.16.40.20',
-                                   'netmask': '255.255.255.0',
-                                   'gateway': '152.16.40.20',
-                                   'if': 'xe1'}],
-                             'description': 'VPE approximation using DPDK',
-                             'name': 'vpevnf-baremetal',
-                             'nd_route_tbl':
-                                 [{'network': '0064:ff9b:0:0:0:0:9810:6414',
-                                   'netmask': '112',
-                                   'gateway': '0064:ff9b:0:0:0:0:9810:6414',
-                                   'if': 'xe0'},
-                                  {'network': '0064:ff9b:0:0:0:0:9810:2814',
-                                   'netmask': '112',
-                                   'gateway': '0064:ff9b:0:0:0:0:9810:2814',
-                                   'if': 'xe1'}],
-                             'id': 'vpevnf-baremetal',
-                             'external-interface':
-                                 [
-                                     {'virtual-interface':
-                                         {
-                                             'dst_mac': '00:00:00:00:00:04',
-                                             'vpci': '0000:05:00.0',
-                                             'local_ip': '152.16.100.19',
-                                             'type': 'PCI-PASSTHROUGH',
-                                             'netmask': '255.255.255.0',
-                                             'dpdk_port_num': '0',
-                                             'bandwidth': '10 Gbps',
-                                             'driver': "i40e",
-                                             'dst_ip': '152.16.100.20',
-                                             'ifname': 'xe0',
-                                             'local_iface_name': 'eth0',
-                                             'local_mac': '00:00:00:00:00:02',
-                                             'vld_id': 'private_1',
-                                         },
-                                         'vnfd-connection-point-ref': 'xe0',
-                                         'name': 'xe0'},
-                                     {'virtual-interface':
-                                         {
-                                             'dst_mac': '00:00:00:00:00:03',
-                                             'vpci': '0000:05:00.1',
-                                             'local_ip': '152.16.40.19',
-                                             'type': 'PCI-PASSTHROUGH',
-                                             'driver': "i40e",
-                                             'netmask': '255.255.255.0',
-                                             'dpdk_port_num': '1',
-                                             'bandwidth': '10 Gbps',
-                                             'dst_ip': '152.16.40.20',
-                                             'ifname': 'xe1',
-                                             'local_iface_name': 'eth1',
-                                             'local_mac': '00:00:00:00:00:01',
-                                             'vld_id': 'public_1',
-                                         },
-                                         'vnfd-connection-point-ref': 'xe1',
-                                         'name': 'xe1'}
-                                 ]}],
-                       'description': 'Vpe approximation using DPDK',
-                       'mgmt-interface':
-                           {'vdu-id': 'vpevnf-baremetal',
-                            'host': '1.2.1.1',
-                            'password': 'r00t',
-                            'user': 'root',
-                            'ip': '1.2.1.1'},
-                       'benchmark':
-                           {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
-                       'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
-                                            {'type': 'VPORT', 'name': 'xe1'}],
-                       'id': 'AclApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+    VNFD_0 = {'short-name': 'VpeVnf',
+              'vdu':
+                  [{'routing_table':
+                        [{'network': '152.16.100.20',
+                          'netmask': '255.255.255.0',
+                          'gateway': '152.16.100.20',
+                          'if': 'xe0'},
+                         {'network': '152.16.40.20',
+                          'netmask': '255.255.255.0',
+                          'gateway': '152.16.40.20',
+                          'if': 'xe1'}],
+                    'description': 'VPE approximation using DPDK',
+                    'name': 'vpevnf-baremetal',
+                    'nd_route_tbl':
+                        [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+                          'netmask': '112',
+                          'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+                          'if': 'xe0'},
+                         {'network': '0064:ff9b:0:0:0:0:9810:2814',
+                          'netmask': '112',
+                          'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+                          'if': 'xe1'}],
+                    'id': 'vpevnf-baremetal',
+                    'external-interface':
+                        [
+                            {'virtual-interface':
+                                {
+                                    'dst_mac': '00:00:00:00:00:04',
+                                    'vpci': '0000:05:00.0',
+                                    'local_ip': '152.16.100.19',
+                                    'type': 'PCI-PASSTHROUGH',
+                                    'netmask': '255.255.255.0',
+                                    'dpdk_port_num': 0,
+                                    'bandwidth': '10 Gbps',
+                                    'driver': "i40e",
+                                    'dst_ip': '152.16.100.20',
+                                    'ifname': 'xe0',
+                                    'local_iface_name': 'eth0',
+                                    'local_mac': '00:00:00:00:00:02',
+                                    'vld_id': 'private_0',
+                                },
+                                'vnfd-connection-point-ref': 'xe0',
+                                'name': 'xe0'},
+                            {'virtual-interface':
+                                {
+                                    'dst_mac': '00:00:00:00:00:03',
+                                    'vpci': '0000:05:00.1',
+                                    'local_ip': '152.16.40.19',
+                                    'type': 'PCI-PASSTHROUGH',
+                                    'driver': "i40e",
+                                    'netmask': '255.255.255.0',
+                                    'dpdk_port_num': 1,
+                                    'bandwidth': '10 Gbps',
+                                    'dst_ip': '152.16.40.20',
+                                    'ifname': 'xe1',
+                                    'local_iface_name': 'eth1',
+                                    'local_mac': '00:00:00:00:00:01',
+                                    'vld_id': 'public_0',
+                                },
+                                'vnfd-connection-point-ref': 'xe1',
+                                'name': 'xe1'}
+                        ]}],
+              'description': 'Vpe approximation using DPDK',
+              'mgmt-interface':
+                  {'vdu-id': 'vpevnf-baremetal',
+                   'host': '1.2.1.1',
+                   'password': 'r00t',
+                   'user': 'root',
+                   'ip': '1.2.1.1'},
+              'benchmark':
+                  {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+              'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+                                   {'type': 'VPORT', 'name': 'xe1'}],
+              'id': 'AclApproxVnf', 'name': 'VPEVnfSsh'}
+
+    VNFD = {
+        'vnfd:vnfd-catalog': {
+            'vnfd': [
+                VNFD_0,
+            ]
+        }
+    }
+
+    def test_validate_ip_and_prefixlen(self):
+        ip_addr, prefix_len = MultiPortConfig.validate_ip_and_prefixlen('10.20.30.40', '16')
+        self.assertEqual(ip_addr, '10.20.30.40')
+        self.assertEqual(prefix_len, 16)
+
+        ip_addr, prefix_len = MultiPortConfig.validate_ip_and_prefixlen('::1', '40')
+        self.assertEqual(ip_addr, '0000:0000:0000:0000:0000:0000:0000:0001')
+        self.assertEqual(prefix_len, 40)
+
+    def test_validate_ip_and_prefixlen_negative(self):
+        with self.assertRaises(AttributeError):
+            MultiPortConfig.validate_ip_and_prefixlen('', '')
+
+        with self.assertRaises(AttributeError):
+            MultiPortConfig.validate_ip_and_prefixlen('10.20.30.400', '16')
+
+        with self.assertRaises(AttributeError):
+            MultiPortConfig.validate_ip_and_prefixlen('10.20.30.40', '33')
+
+        with self.assertRaises(AttributeError):
+            MultiPortConfig.validate_ip_and_prefixlen('::1', '129')
 
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.open')
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.os')
@@ -111,11 +172,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         self.assertEqual(0, opnfv_vnf.swq)
         mock_os.path = mock.MagicMock()
         mock_os.path.isfile = mock.Mock(return_value=False)
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         self.assertEqual(0, opnfv_vnf.swq)
 
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.open')
@@ -125,7 +187,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -139,7 +202,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = VnfdHelper(self.VNFD_0)
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -148,7 +212,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         self.assertIsNotNone(opnfv_vnf.generate_script(self.VNFD))
         opnfv_vnf.lb_config = 'HW'
         self.assertIsNotNone(opnfv_vnf.generate_script(self.VNFD))
@@ -160,12 +224,13 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
         opnfv_vnf.update_write_parser = mock.MagicMock()
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.vnf_type = 'ACL'
         opnfv_vnf.generate_link_config = mock.Mock()
         opnfv_vnf.generate_arp_config = mock.Mock()
@@ -181,7 +246,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -190,7 +256,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'ACL'
         opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
@@ -212,7 +278,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -221,7 +288,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'VFW'
         opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
@@ -239,7 +306,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -248,7 +316,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'VFW'
         opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
@@ -268,7 +336,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -277,7 +346,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'VFW'
         opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
@@ -297,7 +366,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -306,7 +376,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'VFW'
         opnfv_vnf.txrx_pipeline = ''
@@ -323,7 +393,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -332,7 +403,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'VFW'
         opnfv_vnf.txrx_pipeline = ''
@@ -349,7 +420,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -358,7 +430,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'VFW'
         opnfv_vnf.txrx_pipeline = ''
@@ -375,7 +447,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -384,7 +457,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'VFW'
         opnfv_vnf.txrx_pipeline = ''
@@ -401,7 +474,9 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -410,7 +485,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.get_port_pairs = mock.Mock()
         opnfv_vnf.vnf_type = 'VFW'
         opnfv_vnf.txrx_pipeline = ''
@@ -418,7 +493,11 @@ class TestMultiPortConfig(unittest.TestCase):
         opnfv_vnf.get_ports_gateway6 = mock.Mock()
         opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
-        self.assertIsNotNone(opnfv_vnf.generate_link_config())
+        opnfv_vnf.all_ports = ['32', '1', '987']
+        opnfv_vnf.validate_ip_and_prefixlen = mock.Mock(return_value=('10.20.30.40', 16))
+
+        result = opnfv_vnf.generate_link_config()
+        self.assertEqual(len(result.splitlines()), 9)
 
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.open')
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.os')
@@ -427,7 +506,8 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.get_config_tpl_data = mock.MagicMock()
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
@@ -436,7 +516,7 @@ class TestMultiPortConfig(unittest.TestCase):
             mock.Mock(return_value={'link_config': 0, 'arp_config': '',
                                     'arp_config6': '', 'actions': '',
                                     'rules': ''})
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.get_ports_gateway6 = mock.Mock()
@@ -459,10 +539,11 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -482,10 +563,11 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -505,10 +587,11 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -533,10 +616,11 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -556,10 +640,11 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -581,10 +666,11 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -614,10 +700,11 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -649,10 +736,10 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = VnfdHelper(self.VNFD_0)
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -666,10 +753,12 @@ class TestMultiPortConfig(unittest.TestCase):
         opnfv_vnf.worker_config = '1t'
         opnfv_vnf.start_core = 0
         opnfv_vnf.lb_count = 1
+        opnfv_vnf._port_pairs = PortPairs(vnfd_mock.interfaces)
+        opnfv_vnf.port_pair_list = opnfv_vnf._port_pairs.port_pair_list
         result = opnfv_vnf.generate_lb_to_port_pair_mapping()
         self.assertEqual(None, result)
         result = opnfv_vnf.set_priv_to_pub_mapping()
-        self.assertEqual('(0, 1)', result)
+        self.assertEqual('(0,1)', result)
 
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.open')
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.os')
@@ -680,11 +769,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = VnfdHelper(self.VNFD_0)
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+        opnfv_vnf.port_pairs = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -701,6 +791,43 @@ class TestMultiPortConfig(unittest.TestCase):
         result = opnfv_vnf.set_priv_que_handler()
         self.assertEqual(None, result)
 
+    @mock.patch('yardstick.network_services.helpers.samplevnf_helper.open')
+    @mock.patch('yardstick.network_services.helpers.samplevnf_helper.ConfigParser')
+    def test_generate_arp_route_tbl(self, *_):
+        topology_file = mock.Mock()
+        config_tpl = mock.Mock()
+        tmp_file = mock.Mock()
+        vnfd_mock = mock.MagicMock()
+        vnfd_mock.port_num.side_effect = ['32', '1', '987']
+        vnfd_mock.find_interface.side_effect = [
+            {
+                'virtual-interface': {
+                    'dst_ip': '10.20.30.40',
+                    'netmask': '20',
+                },
+            },
+            {
+                'virtual-interface': {
+                    'dst_ip': '10.200.30.40',
+                    'netmask': '24',
+                },
+            },
+            {
+                'virtual-interface': {
+                    'dst_ip': '10.20.3.40',
+                    'netmask': '8',
+                },
+            },
+        ]
+
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
+        opnfv_vnf.all_ports = [3, 2, 5]
+
+        expected = '(0a141000,fffff000,32,0a141e28) (0ac81e00,ffffff00,1,0ac81e28) ' \
+                   '(0a000000,ff000000,987,0a140328)'
+        result = opnfv_vnf.generate_arp_route_tbl()
+        self.assertEqual(result, expected)
+
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.open')
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.os')
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.ConfigParser')
@@ -710,11 +837,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+        opnfv_vnf.port_pairs = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -754,11 +882,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+        opnfv_vnf.port_pairs = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -795,11 +924,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+        opnfv_vnf.port_pairs = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -848,11 +978,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+        opnfv_vnf.port_pairs = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -884,11 +1015,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+        opnfv_vnf.port_pairs = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -932,11 +1064,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = VnfdHelper(self.VNFD_0)
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+        opnfv_vnf.port_pairs = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
@@ -982,62 +1115,12 @@ class TestMultiPortConfig(unittest.TestCase):
         opnfv_vnf.loadb_tpl = mock.MagicMock()
         opnfv_vnf.vnf_type = 'CGNAPT'
         opnfv_vnf.update_timer = mock.Mock()
-        opnfv_vnf.port_pair_list = [[[0], [1], [2]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1"), ("xe0", "xe2")]
         opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
         opnfv_vnf.generate_arpicmp_data = mock.Mock()
         result = opnfv_vnf.generate_config_data()
         self.assertIsNone(result)
 
-    @mock.patch('yardstick.network_services.helpers.samplevnf_helper.open')
-    @mock.patch('yardstick.network_services.helpers.samplevnf_helper.os')
-    @mock.patch('yardstick.network_services.helpers.samplevnf_helper.ConfigParser')
-    @mock.patch('yardstick.network_services.helpers.samplevnf_helper.OrderedDict')
-    def test_get_port_pairs(self, mock_open, mock_os, ConfigParser,
-                            OrderedDict):
-        topology_file = mock.Mock()
-        config_tpl = mock.Mock()
-        tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
-        opnfv_vnf.socket = 0
-        opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
-        opnfv_vnf.txrx_pipeline = ''
-        opnfv_vnf.rules = ''
-        opnfv_vnf.write_parser = mock.MagicMock()
-        opnfv_vnf.read_parser = mock.MagicMock()
-        opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
-        opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
-        opnfv_vnf.write_parser.set = mock.Mock()
-        opnfv_vnf.write_parser.add_section = mock.Mock()
-        opnfv_vnf.read_parser.items = mock.MagicMock()
-        opnfv_vnf.pipeline_counter = 0
-        opnfv_vnf.worker_config = '1t'
-        opnfv_vnf.start_core = 0
-        opnfv_vnf.lb_count = 1
-        opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
-        opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
-        opnfv_vnf.lb_index = 1
-        opnfv_vnf.ports_len = 1
-        opnfv_vnf.pktq_out = ['1', '2']
-        opnfv_vnf.prv_que_handler = 0
-        opnfv_vnf.init_write_parser_template = mock.Mock()
-        opnfv_vnf.arpicmp_tpl = mock.MagicMock()
-        opnfv_vnf.txrx_tpl = mock.MagicMock()
-        opnfv_vnf.loadb_tpl = mock.MagicMock()
-        opnfv_vnf.vnf_tpl = {'public_ip_port_range': '98164810 (1,65535)',
-                             'vnf_set': '(2,4,5)'}
-        opnfv_vnf.generate_vnf_data = mock.Mock(return_value={})
-        opnfv_vnf.update_write_parser = mock.Mock()
-
-        curr_path = os.path.dirname(os.path.abspath(__file__))
-        opnfv_vnf.topology_file = \
-            os.path.join(curr_path, 'acl_vnf_topology_ixia.yaml')
-        opnfv_vnf.lb_count = 10
-        result = opnfv_vnf.get_port_pairs(opnfv_vnf.interfaces)
-        self.assertEqual(result[0], [('xe0', 'xe1')])
-
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.open')
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.os')
     @mock.patch('yardstick.network_services.helpers.samplevnf_helper.ConfigParser')
@@ -1047,11 +1130,12 @@ class TestMultiPortConfig(unittest.TestCase):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
-        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file)
+        vnfd_mock = mock.MagicMock()
+        opnfv_vnf = MultiPortConfig(topology_file, config_tpl, tmp_file, vnfd_mock)
         opnfv_vnf.socket = 0
         opnfv_vnf.start_core = 0
-        opnfv_vnf.port_pair_list = [[[0], [1]]]
-        opnfv_vnf.port_pairs = [[[0], [1]]]
+        opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+        opnfv_vnf.port_pairs = [("xe0", "xe1")]
         opnfv_vnf.txrx_pipeline = ''
         opnfv_vnf.rules = ''
         opnfv_vnf.write_parser = mock.MagicMock()
index 7fe8340..ea2f9c3 100644 (file)
@@ -268,7 +268,7 @@ class TestIxNextgen(unittest.TestCase):
 
     def test_add_ip_header_v4(self):
         static_traffic_params = {
-            "private_1": {
+            "private_0": {
                 "id": 1,
                 "bidir": "False",
                 "duration": 60,
@@ -308,7 +308,7 @@ class TestIxNextgen(unittest.TestCase):
                 },
                 "traffic_type": "continuous"
             },
-            "public_1": {
+            "public_0": {
                 "id": 2,
                 "bidir": "False",
                 "duration": 60,
@@ -366,7 +366,7 @@ class TestIxNextgen(unittest.TestCase):
 
     def test_add_ip_header_v4_nothing_to_do(self):
         static_traffic_params = {
-            "private_1": {
+            "private_0": {
                 "id": 1,
                 "bidir": "False",
                 "duration": 60,
@@ -406,7 +406,7 @@ class TestIxNextgen(unittest.TestCase):
                 },
                 "traffic_type": "continuous"
             },
-            "public_1": {
+            "public_0": {
                 "id": 2,
                 "bidir": "False",
                 "duration": 60,
@@ -464,7 +464,7 @@ class TestIxNextgen(unittest.TestCase):
 
     def test_add_ip_header_v6(self):
         static_traffic_profile = {
-            "private_1": {
+            "private_0": {
                 "id": 1,
                 "bidir": "False",
                 "duration": 60,
@@ -497,7 +497,7 @@ class TestIxNextgen(unittest.TestCase):
                 },
                 "traffic_type": "continuous"
             },
-            "public_1": {
+            "public_0": {
                 "id": 2,
                 "bidir": "False",
                 "duration": 60,
@@ -547,7 +547,7 @@ class TestIxNextgen(unittest.TestCase):
 
     def test_add_ip_header_v6_nothing_to_do(self):
         static_traffic_params = {
-            "private_1": {
+            "private_0": {
                 "id": 1,
                 "bidir": "False",
                 "duration": 60,
@@ -579,7 +579,7 @@ class TestIxNextgen(unittest.TestCase):
                 },
                 "traffic_type": "continuous"
             },
-            "public_1": {
+            "public_0": {
                 "id": 2,
                 "bidir": "False",
                 "duration": 60,
@@ -684,7 +684,7 @@ class TestIxNextgen(unittest.TestCase):
 
     def test_ix_update_ether(self):
         static_traffic_params = {
-            "private_1": {
+            "private_0": {
                 "id": 1,
                 "bidir": "False",
                 "duration": 60,
@@ -723,7 +723,7 @@ class TestIxNextgen(unittest.TestCase):
                 },
                 "traffic_type": "continuous"
             },
-            "public_1": {
+            "public_0": {
                 "id": 2,
                 "bidir": "False",
                 "duration": 60,
@@ -787,7 +787,7 @@ class TestIxNextgen(unittest.TestCase):
 
     def test_ix_update_ether_nothing_to_do(self):
         static_traffic_params = {
-            "private_1": {
+            "private_0": {
                 "id": 1,
                 "bidir": "False",
                 "duration": 60,
@@ -820,7 +820,7 @@ class TestIxNextgen(unittest.TestCase):
                 },
                 "traffic_type": "continuous"
             },
-            "public_1": {
+            "public_0": {
                 "id": 2,
                 "bidir": "False",
                 "duration": 60,
index 21beba8..1c2c1f3 100644 (file)
@@ -54,7 +54,7 @@ class TestResourceProfile(unittest.TestCase):
                     'local_ip': '172.16.100.19',
                     'type': 'PCI-PASSTHROUGH',
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '0',
+                    'dpdk_port_num': 0,
                     'bandwidth': '10 Gbps',
                     'dst_ip': '172.16.100.20',
                     'local_mac': '3c:fd:fe:a1:2b:80'},
@@ -66,7 +66,7 @@ class TestResourceProfile(unittest.TestCase):
                     'local_ip': '172.16.40.19',
                     'type': 'PCI-PASSTHROUGH',
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '1',
+                    'dpdk_port_num': 1,
                     'bandwidth': '10 Gbps',
                     'dst_ip': '172.16.40.20',
                     'local_mac': '3c:fd:fe:a1:2b:81'},
index 72b097b..2906103 100644 (file)
@@ -48,7 +48,7 @@ class TestTrafficProfile(unittest.TestCase):
 
     def test_execute(self):
         traffic_profile = TrafficProfile(self.TRAFFIC_PROFILE)
-        self.assertRaises(NotImplementedError, traffic_profile.execute, {})
+        self.assertRaises(NotImplementedError, traffic_profile.execute_traffic, {})
 
     def test_get(self):
         traffic_profile = TrafficProfile(self.TRAFFIC_PROFILE)
index 8484317..eb182a2 100644 (file)
@@ -74,7 +74,7 @@ class TestFixedProfile(unittest.TestCase):
                     'local_ip': '152.16.100.19',
                     'type': 'PCI-PASSTHROUGH',
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '0',
+                    'dpdk_port_num': 0,
                     'bandwidth': '10 Gbps',
                     'dst_ip': '152.16.100.20',
                     'local_mac': '00:00:00:00:00:01'},
@@ -86,7 +86,7 @@ class TestFixedProfile(unittest.TestCase):
                     'local_ip': '152.16.40.19',
                     'type': 'PCI-PASSTHROUGH',
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '1',
+                    'dpdk_port_num': 1,
                     'bandwidth': '10 Gbps',
                     'dst_ip': '152.16.40.20',
                     'local_mac': '00:00:00:00:00:02'},
index 846bfa3..6566236 100644 (file)
@@ -20,6 +20,8 @@ from __future__ import division
 import unittest
 import mock
 
+from copy import deepcopy
+
 from tests.unit import STL_MOCKS
 
 STLClient = mock.MagicMock()
@@ -35,6 +37,7 @@ if stl_patch:
 
 
 class TestIXIARFC2544Profile(unittest.TestCase):
+
     TRAFFIC_PROFILE = {
         "schema": "isb:traffic_profile:0.1",
         "name": "fixed",
@@ -43,7 +46,9 @@ class TestIXIARFC2544Profile(unittest.TestCase):
             "traffic_type": "FixedTraffic",
             "frame_rate": 100,  # pps
             "flow_number": 10,
-            "frame_size": 64}}
+            "frame_size": 64,
+        },
+    }
 
     PROFILE = {'description': 'Traffic profile to run RFC2544 latency',
                'name': 'rfc2544',
@@ -178,7 +183,6 @@ class TestIXIARFC2544Profile(unittest.TestCase):
                           self.PROFILE, mac, xfile="tmp",
                           static_traffic=STATIC_TRAFFIC)
 
-
     @mock.patch("yardstick.network_services.traffic_profile.ixia_rfc2544.open")
     def test_get_ixia_traffic_profile(self, mock_open):
         traffic_generator = mock.Mock(autospec=TrexProfile)
@@ -435,11 +439,19 @@ class TestIXIARFC2544Profile(unittest.TestCase):
             profile_data, mac, static_traffic=STATIC_TRAFFIC)
         self.assertIsNotNone(result)
 
+    def test__get_ixia_traffic_profile_default_args(self):
+        r_f_c2544_profile = IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+
+        expected = {}
+        result = r_f_c2544_profile._get_ixia_traffic_profile({})
+        self.assertDictEqual(result, expected)
+
     def test__ixia_traffic_generate(self):
         traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.my_ports = [0, 1]
-        traffic_generator.priv_ports = [-1]
-        traffic_generator.pub_ports = [1]
+        traffic_generator.networks = {
+            "private_0": ["xe0"],
+            "public_0": ["xe1"],
+        }
         traffic_generator.client = \
             mock.Mock(return_value=True)
         traffic = {"public": {'iload': 10},
@@ -451,12 +463,12 @@ class TestIXIARFC2544Profile(unittest.TestCase):
                                                           traffic, ixia_obj)
         self.assertIsNone(result)
 
-
     def test_execute(self):
         traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.my_ports = [0, 1]
-        traffic_generator.priv_ports = [-1]
-        traffic_generator.pub_ports = [1]
+        traffic_generator.networks = {
+            "private_0": ["xe0"],
+            "public_0": ["xe1"],
+        }
         traffic_generator.client = \
             mock.Mock(return_value=True)
         r_f_c2544_profile = IXIARFC2544Profile(self.TRAFFIC_PROFILE)
@@ -470,14 +482,40 @@ class TestIXIARFC2544Profile(unittest.TestCase):
         r_f_c2544_profile.get_multiplier = mock.Mock()
         r_f_c2544_profile._ixia_traffic_generate = mock.Mock()
         ixia_obj = mock.MagicMock()
-        self.assertEqual(None, r_f_c2544_profile.execute(traffic_generator,
-                                                         ixia_obj))
+        self.assertEqual(None, r_f_c2544_profile.execute_traffic(traffic_generator, ixia_obj))
+
+    def test_update_traffic_profile(self):
+        traffic_generator = mock.Mock(autospec=TrexProfile)
+        traffic_generator.networks = {
+            "private_0": ["xe0"],  # private, one value for intfs
+            "public_0": ["xe1", "xe2"],  # public, two values for intfs
+            "public_1": ["xe3"],  # not in TRAFFIC PROFILE
+            "tenant_0": ["xe4"],  # not public or private
+        }
+
+        ports_expected = [8, 3, 5]
+        traffic_generator.vnfd_helper.port_num.side_effect = ports_expected
+        traffic_generator.client.return_value = True
+
+        traffic_profile = deepcopy(self.TRAFFIC_PROFILE)
+        traffic_profile.update({
+            "private_0": ["xe0"],
+            "public_0": ["xe1", "xe2"],
+        })
+
+        r_f_c2544_profile = IXIARFC2544Profile(traffic_profile)
+        r_f_c2544_profile.full_profile = {}
+        r_f_c2544_profile.get_streams = mock.Mock()
+
+        self.assertIsNone(r_f_c2544_profile.update_traffic_profile(traffic_generator))
+        self.assertEqual(r_f_c2544_profile.ports, ports_expected)
 
     def test_get_drop_percentage(self):
         traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.my_ports = [0, 1]
-        traffic_generator.priv_ports = [0]
-        traffic_generator.pub_ports = [1]
+        traffic_generator.networks = {
+            "private_0": ["xe0"],
+            "public_0": ["xe1"],
+        }
         traffic_generator.client = \
             mock.Mock(return_value=True)
         r_f_c2544_profile = IXIARFC2544Profile(self.TRAFFIC_PROFILE)
@@ -584,9 +622,10 @@ class TestIXIARFC2544Profile(unittest.TestCase):
 
     def test_start_ixia_latency(self):
         traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.my_ports = [0, 1]
-        traffic_generator.priv_ports = [0]
-        traffic_generator.pub_ports = [1]
+        traffic_generator.networks = {
+            "private_0": ["xe0"],
+            "public_0": ["xe1"],
+        }
         traffic_generator.client = \
             mock.Mock(return_value=True)
         r_f_c2544_profile = IXIARFC2544Profile(self.TRAFFIC_PROFILE)
index aef0b93..b63a805 100644 (file)
@@ -50,7 +50,7 @@ class TestRFC2544Profile(unittest.TestCase):
                'name': 'rfc2544',
                'traffic_profile': {'traffic_type': 'RFC2544Profile',
                                    'frame_rate': 100},
-               'public_1': {'ipv4':
+               'public_0': {'ipv4':
                           {'outer_l2': {'framesize':
                                         {'64B': '100', '1518B': '0',
                                          '128B': '0', '1400B': '0',
@@ -62,7 +62,7 @@ class TestRFC2544Profile(unittest.TestCase):
                                           'dscp': 0, 'ttl': 32, 'count': 1},
                            'outer_l4': {'srcport': '2001',
                                'dsrport': '1234', 'count': 1}}},
-               'private_1': {'ipv4':
+               'private_0': {'ipv4':
                            {'outer_l2': {'framesize':
                                          {'64B': '100', '1518B': '0',
                                           '128B': '0', '1400B': '0',
@@ -82,27 +82,29 @@ class TestRFC2544Profile(unittest.TestCase):
 
     def test_execute(self):
         traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.my_ports = [0, 1]
-        traffic_generator.priv_ports = [-1]
-        traffic_generator.pub_ports = [1]
+        traffic_generator.networks = {
+            "private_0": ["xe0"],
+            "public_0": ["xe1"],
+        }
         traffic_generator.client = \
             mock.Mock(return_value=True)
         r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
         r_f_c2544_profile.params = self.PROFILE
         r_f_c2544_profile.first_run = True
-        self.assertEqual(None, r_f_c2544_profile.execute(traffic_generator))
+        self.assertEqual(None, r_f_c2544_profile.execute_traffic(traffic_generator))
 
     def test_get_drop_percentage(self):
         traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.my_ports = [0, 1]
-        traffic_generator.priv_ports = [0]
-        traffic_generator.pub_ports = [1]
+        traffic_generator.networks = {
+            "private_0": ["xe0"],
+            "public_0": ["xe1"],
+        }
         traffic_generator.client = mock.Mock(return_value=True)
 
         r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
         r_f_c2544_profile.params = self.PROFILE
         r_f_c2544_profile.register_generator(traffic_generator)
-        self.assertIsNone(r_f_c2544_profile.execute(traffic_generator))
+        self.assertIsNone(r_f_c2544_profile.execute_traffic(traffic_generator))
 
         samples = {}
         for ifname in range(1):
@@ -140,15 +142,16 @@ class TestRFC2544Profile(unittest.TestCase):
 
     def test_get_drop_percentage_update(self):
         traffic_generator = mock.Mock(autospec=RFC2544Profile)
-        traffic_generator.my_ports = [0, 1]
-        traffic_generator.priv_ports = [0]
-        traffic_generator.pub_ports = [1]
+        traffic_generator.networks = {
+            "private_0": ["xe0"],
+            "public_0": ["xe1"],
+        }
         traffic_generator.client = mock.Mock(return_value=True)
 
         r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
         r_f_c2544_profile.params = self.PROFILE
         r_f_c2544_profile.register_generator(traffic_generator)
-        self.assertIsNone(r_f_c2544_profile.execute())
+        self.assertIsNone(r_f_c2544_profile.execute_traffic())
 
         samples = {}
         for ifname in range(1):
@@ -187,14 +190,15 @@ class TestRFC2544Profile(unittest.TestCase):
 
     def test_get_drop_percentage_div_zero(self):
         traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.my_ports = [0, 1]
-        traffic_generator.priv_ports = [0]
-        traffic_generator.pub_ports = [1]
+        traffic_generator.networks = {
+            "private_0": ["xe0"],
+            "public_0": ["xe1"],
+        }
         traffic_generator.client = \
             mock.Mock(return_value=True)
         r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
         r_f_c2544_profile.params = self.PROFILE
-        self.assertEqual(None, r_f_c2544_profile.execute(traffic_generator))
+        self.assertEqual(None, r_f_c2544_profile.execute_traffic(traffic_generator))
         samples = {}
         for ifname in range(1):
             name = "xe{}".format(ifname)
index 55e7d48..e0b0ce8 100644 (file)
@@ -136,11 +136,6 @@ class TestTrexProfile(unittest.TestCase):
             TrexProfile(TrafficProfile)
         self.assertEqual(trex_profile.pps, 100)
 
-    def test_execute(self):
-        trex_profile = \
-            TrexProfile(TrafficProfile)
-        self.assertEqual(None, trex_profile.execute({}))
-
     def test_qinq(self):
         qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
                 "C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
@@ -239,7 +234,7 @@ class TestTrexProfile(unittest.TestCase):
 
         ether_range = "00:00:00:00:00:01-00:00:00:00:00:02"
         ip_range = "1.1.1.2-1.1.1.10"
-        ipv6_range =  '0064:ff9b:0:0:0:0:9810:6414-0064:ff9b:0:0:0:0:9810:6420'
+        ipv6_range = '0064:ff9b:0:0:0:0:9810:6414-0064:ff9b:0:0:0:0:9810:6420'
 
         trex_profile._set_proto_addr(ETHERNET, SRC, ether_range)
         trex_profile._set_proto_addr(ETHERNET, DST, ether_range)
@@ -249,6 +244,3 @@ class TestTrexProfile(unittest.TestCase):
         trex_profile._set_proto_addr(IPv6, DST, ipv6_range)
         trex_profile._set_proto_addr(UDP, SRC_PORT, "5060-5090")
         trex_profile._set_proto_addr(UDP, DST_PORT, "5060")
-
-
-
index 2e83353..f47da37 100644 (file)
@@ -75,7 +75,7 @@ class TestAclApproxVnf(unittest.TestCase):
                     'local_ip': '152.16.100.19',
                     'type': 'PCI-PASSTHROUGH',
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '0',
+                    'dpdk_port_num': 0,
                     'bandwidth': '10 Gbps',
                     'driver': "i40e",
                     'dst_ip': '152.16.100.20',
@@ -90,7 +90,7 @@ class TestAclApproxVnf(unittest.TestCase):
                     'type': 'PCI-PASSTHROUGH',
                     'driver': "i40e",
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '1',
+                    'dpdk_port_num': 1,
                     'bandwidth': '10 Gbps',
                     'dst_ip': '152.16.40.20',
                     'local_iface_name': 'xe1',
index e1c69e7..478ce18 100644 (file)
@@ -150,7 +150,7 @@ class TestGenericVNF(unittest.TestCase):
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.100.20',
                             'local_mac': '00:00:00:00:00:01'
@@ -165,7 +165,7 @@ class TestGenericVNF(unittest.TestCase):
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
                             'local_mac': '00:00:00:00:00:02'
index e550369..c21beab 100644 (file)
@@ -21,6 +21,8 @@ import os
 import unittest
 import mock
 
+from copy import deepcopy
+
 from tests.unit import STL_MOCKS
 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
 
@@ -66,15 +68,22 @@ link 1 up
 """
         header = "This is a header"
 
-        out = CgnaptApproxSetupEnvHelper._update_cgnat_script_file(header, sample.splitlines(), "")
+        out = CgnaptApproxSetupEnvHelper._update_cgnat_script_file(header, sample.splitlines())
         self.assertNotIn("This is a header", out)
 
-    def test__get_cgnapt_confgi(self):
+    def test__get_cgnapt_config(self):
+        vnfd_helper = mock.Mock()
+        vnfd_helper.port_pairs.priv_ports = [{"name": 'a'}, {"name": "b"}, {"name": "c"}]
+
+        helper = CgnaptApproxSetupEnvHelper(vnfd_helper, mock.Mock(), mock.Mock())
+        helper._get_ports_gateway = mock.Mock(side_effect=[3, 5, 2])
+        result = helper._get_cgnapt_config([{"name": 'a'}, {}, {"name": "b"}, {}, {"name": "c"}])
+        self.assertEqual(result, [3, 5, 2])
 
-        c = CgnaptApproxSetupEnvHelper(mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
-        c._get_ports_gateway = mock.Mock(return_value=3)
-        ret = c._get_cgnapt_config([{"name": 'a'}, {}, {"name": "b"}, {}, {"name": "c"}])
-        self.assertEqual(ret, [3, 3, 3])
+    def test_scale(self):
+        helper = CgnaptApproxSetupEnvHelper(mock.Mock(), mock.Mock(), mock.Mock())
+        with self.assertRaises(NotImplementedError):
+            helper.scale()
 
 
 @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
@@ -111,7 +120,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
                     'local_ip': '152.16.100.19',
                     'type': 'PCI-PASSTHROUGH',
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '0',
+                    'dpdk_port_num': 0,
                     'bandwidth': '10 Gbps',
                     'driver': "i40e",
                     'dst_ip': '152.16.100.20',
@@ -126,7 +135,7 @@ class TestCgnaptApproxVnf(unittest.TestCase):
                     'type': 'PCI-PASSTHROUGH',
                     'driver': "i40e",
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '1',
+                    'dpdk_port_num': 1,
                     'bandwidth': '10 Gbps',
                     'dst_ip': '152.16.40.20',
                     'local_iface_name': 'xe1',
@@ -146,31 +155,48 @@ class TestCgnaptApproxVnf(unittest.TestCase):
                                     {'type': 'VPORT', 'name': 'xe1'}],
                'id': 'CgnaptApproxVnf', 'name': 'VPEVnfSsh'}]}}
 
-    scenario_cfg = {'options': {'packetsize': 64, 'traffic_type': 4,
-                                'rfc2544': {'allowed_drop_rate': '0.8 - 1'},
-                                'vnf__1': {'rules': 'acl_1rule.yaml',
-                                           'vnf_config': {'lb_config': 'SW',
-                                                          'lb_count': 1,
-                                                          'worker_config':
-                                                          '1C/1T',
-                                                          'worker_threads': 1}}
-                                },
-                    'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
-                    'task_path': '/tmp',
-                    'tc': 'tc_ipv4_1Mflow_64B_packetsize',
-                    'runner': {'object': 'NetworkServiceTestCase',
-                               'interval': 35,
-                               'output_filename': '/tmp/yardstick.out',
-                               'runner_id': 74476, 'duration': 400,
-                               'type': 'Duration'},
-                    'traffic_profile': 'ipv4_throughput_acl.yaml',
-                    'traffic_options': {'flow': 'ipv4_Packets_acl.yaml',
-                                        'imix': 'imix_voice.yaml'},
-                    'type': 'ISB',
-                    'nodes': {'tg__2': 'trafficgen_2.yardstick',
-                              'tg__1': 'trafficgen_1.yardstick',
-                              'vnf__1': 'vnf.yardstick'},
-                    'topology': 'vpe-tg-topology-baremetal.yaml'}
+    SCENARIO_CFG = {
+        'options': {
+            'packetsize': 64,
+            'traffic_type': 4,
+            'rfc2544': {
+                'allowed_drop_rate': '0.8 - 1',
+            },
+            'vnf__1': {
+                'napt': 'dynamic',
+                'vnf_config': {
+                    'lb_config': 'SW',
+                    'lb_count': 1,
+                    'worker_config':
+                    '1C/1T',
+                    'worker_threads': 1,
+                },
+            },
+        },
+        'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
+        'task_path': '/tmp',
+        'tc': 'tc_ipv4_1Mflow_64B_packetsize',
+        'runner': {
+            'object': 'NetworkServiceTestCase',
+            'interval': 35,
+            'output_filename': '/tmp/yardstick.out',
+            'runner_id': 74476,
+            'duration': 400,
+            'type': 'Duration',
+        },
+        'traffic_profile': 'ipv4_throughput_acl.yaml',
+        'traffic_options': {
+            'flow': 'ipv4_Packets_acl.yaml',
+            'imix': 'imix_voice.yaml',
+        },
+        'type': 'ISB',
+        'nodes': {
+            'tg__2': 'trafficgen_2.yardstick',
+            'tg__1': 'trafficgen_1.yardstick',
+            'vnf__1': 'vnf.yardstick',
+        },
+        'topology': 'vpe-tg-topology-baremetal.yaml',
+    }
 
     context_cfg = {'nodes': {'tg__2':
                              {'member-vnf-index': '3',
@@ -277,14 +303,16 @@ class TestCgnaptApproxVnf(unittest.TestCase):
                               'password': 'r00t',
                               'VNF model': 'cgnapt_vnf.yaml'}}}
 
+    def setUp(self):
+        self.scenario_cfg = deepcopy(self.SCENARIO_CFG)
+
     def test___init__(self, mock_process):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
         self.assertIsNone(cgnapt_approx_vnf._vnf_process)
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
     @mock.patch(SSH_HELPER)
-    def test_collect_kpi(self, ssh, mock_time, mock_process):
+    def test_collect_kpi(self, ssh, mock_process):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
@@ -296,9 +324,8 @@ class TestCgnaptApproxVnf(unittest.TestCase):
         result = {'packets_dropped': 0, 'packets_fwd': 0, 'packets_in': 0}
         self.assertEqual(result, cgnapt_approx_vnf.collect_kpi())
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
     @mock.patch(SSH_HELPER)
-    def test_vnf_execute_command(self, ssh, mock_time, mock_process):
+    def test_vnf_execute_command(self, ssh, mock_process):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
@@ -386,9 +413,24 @@ class TestCgnaptApproxVnf(unittest.TestCase):
         self.assertEqual(None, cgnapt_approx_vnf.terminate())
 
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.cgnapt_vnf.time")
     @mock.patch(SSH_HELPER)
-    def test__vnf_up_post(self, ssh, mock_time, mock_cgnapt_time, mock_process):
+    def test__vnf_up_post(self, ssh, mock_time, mock_process):
+        mock_ssh(ssh)
+
+        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        self.scenario_cfg['options'][name]['napt'] = 'static'
+
+        cgnapt_approx_vnf = CgnaptApproxVnf(name, vnfd)
+        cgnapt_approx_vnf._vnf_process = mock.MagicMock()
+        cgnapt_approx_vnf._vnf_process.terminate = mock.Mock()
+        cgnapt_approx_vnf.vnf_execute = mock.MagicMock()
+        cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
+        cgnapt_approx_vnf._resource_collect_stop = mock.Mock()
+        cgnapt_approx_vnf._vnf_up_post()
+
+    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+    @mock.patch(SSH_HELPER)
+    def test__vnf_up_post_short(self, ssh, mock_time, mock_process):
         mock_ssh(ssh)
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
@@ -399,7 +441,6 @@ class TestCgnaptApproxVnf(unittest.TestCase):
         cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
         cgnapt_approx_vnf._resource_collect_stop = mock.Mock()
         cgnapt_approx_vnf._vnf_up_post()
-        cgnapt_approx_vnf.vnf_execute.assert_called_once()
 
 
 if __name__ == '__main__':
index cba3d44..821c10f 100644 (file)
@@ -17,6 +17,7 @@
 
 from __future__ import absolute_import
 
+import copy
 import os
 import socket
 import unittest
@@ -25,6 +26,7 @@ from contextlib import contextmanager
 import mock
 
 from tests.unit import STL_MOCKS
+from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
 
 STLClient = mock.MagicMock()
 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
@@ -634,6 +636,111 @@ class TestProxSocketHelper(unittest.TestCase):
 
 
 class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
+
+    VNFD0 = {
+        'short-name': 'ProxVnf',
+        'vdu': [
+            {
+                'routing_table': [
+                    {
+                        'network': '152.16.100.20',
+                        'netmask': '255.255.255.0',
+                        'gateway': '152.16.100.20',
+                        'if': 'xe0',
+                    },
+                    {
+                        'network': '152.16.40.20',
+                        'netmask': '255.255.255.0',
+                        'gateway': '152.16.40.20',
+                        'if': 'xe1',
+                    },
+                ],
+                'description': 'PROX approximation using DPDK',
+                'name': 'proxvnf-baremetal',
+                'nd_route_tbl': [
+                    {
+                        'network': '0064:ff9b:0:0:0:0:9810:6414',
+                        'netmask': '112',
+                        'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+                        'if': 'xe0',
+                    },
+                    {
+                        'network': '0064:ff9b:0:0:0:0:9810:2814',
+                        'netmask': '112',
+                        'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+                        'if': 'xe1',
+                    },
+                ],
+                'id': 'proxvnf-baremetal',
+                'external-interface': [
+                    {
+                        'virtual-interface': {
+                            'dst_mac': '00:00:00:00:00:04',
+                            'vpci': '0000:05:00.0',
+                            'local_ip': '152.16.100.19',
+                            'type': 'PCI-PASSTHROUGH',
+                            'vld_id': 'private_0',
+                            'netmask': '255.255.255.0',
+                            'dpdk_port_num': 0,
+                            'bandwidth': '10 Gbps',
+                            'driver': "i40e",
+                            'dst_ip': '152.16.100.19',
+                            'local_iface_name': 'xe0',
+                            'local_mac': '00:00:00:00:00:02',
+                            'ifname': 'xe0',
+                        },
+                        'vnfd-connection-point-ref': 'xe0',
+                        'name': 'xe0',
+                    },
+                    {
+                        'virtual-interface': {
+                            'dst_mac': '00:00:00:00:00:03',
+                            'vpci': '0000:05:00.1',
+                            'local_ip': '152.16.40.19',
+                            'type': 'PCI-PASSTHROUGH',
+                            'vld_id': 'public_0',
+                            'driver': "i40e",
+                            'netmask': '255.255.255.0',
+                            'dpdk_port_num': 1,
+                            'bandwidth': '10 Gbps',
+                            'dst_ip': '152.16.40.20',
+                            'local_iface_name': 'xe1',
+                            'local_mac': '00:00:00:00:00:01',
+                            'ifname': 'xe1',
+                        },
+                        'vnfd-connection-point-ref': 'xe1',
+                        'name': 'xe1',
+                    },
+                ],
+            },
+        ],
+        'description': 'PROX approximation using DPDK',
+        'mgmt-interface': {
+            'vdu-id': 'proxvnf-baremetal',
+            'host': '1.2.1.1',
+            'password': 'r00t',
+            'user': 'root',
+            'ip': '1.2.1.1',
+        },
+        'benchmark': {
+            'kpi': [
+                'packets_in',
+                'packets_fwd',
+                'packets_dropped',
+            ],
+        },
+        'id': 'ProxApproxVnf',
+        'name': 'ProxVnf',
+    }
+
+    VNFD = {
+        'vnfd:vnfd-catalog': {
+            'vnfd': [
+                VNFD0,
+            ],
+        },
+    }
+
     def test__replace_quoted_with_value(self):
         # empty string
         input_str = ''
@@ -751,33 +858,6 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         result = ProxDpdkVnfSetupEnvHelper.write_prox_config(input_data)
         self.assertEqual(result, expected)
 
-    def test_rebind_drivers(self):
-        def find_drivers(*args, **kwargs):
-            setup_helper.used_drivers = used_drivers
-
-        used_drivers = {
-            'a': (1, 'b'),
-            'c': (2, 'd'),
-        }
-
-        vnfd_helper = mock.MagicMock()
-        ssh_helper = mock.MagicMock()
-        scenario_helper = mock.MagicMock()
-        setup_helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        setup_helper._find_used_drivers = mock_find = mock.MagicMock(side_effect=find_drivers)
-
-        setup_helper.rebind_drivers()
-        self.assertEqual(mock_find.call_count, 1)
-        self.assertEqual(ssh_helper.execute.call_count, 2)
-        self.assertIn('--force', ssh_helper.execute.call_args[0][0])
-
-        mock_find.reset_mock()
-        ssh_helper.execute.reset_mock()
-        setup_helper.rebind_drivers(False)
-        self.assertEqual(mock_find.call_count, 0)
-        self.assertEqual(ssh_helper.execute.call_count, 2)
-        self.assertNotIn('--force', ssh_helper.execute.call_args[0][0])
-
     @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.find_relative_file')
     def test_build_config_file_no_additional_file(self, mock_find_path):
         vnf1 = {
@@ -931,8 +1011,7 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
 
         mock_parser_type.side_effect = init
 
-        vnfd_helper = mock.MagicMock()
-        vnfd_helper.interfaces = []
+        vnfd_helper = VnfdHelper(self.VNFD0)
         ssh_helper = mock.MagicMock()
         scenario_helper = mock.MagicMock()
 
@@ -946,23 +1025,6 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
         helper.additional_files = {"ipv4.lua": "/tmp/ipv4.lua"}
 
         helper.remote_prox_file_name = 'remote'
-        vnfd_helper.interfaces = [
-            {
-                'virtual-interface': {
-                    'dst_mac': '00:00:00:de:ad:88',
-                },
-            },
-            {
-                'virtual-interface': {
-                    'dst_mac': '00:00:00:de:ad:ee',
-                },
-            },
-            {
-                'virtual-interface': {
-                    'dst_mac': '00:00:00:de:ad:ff',
-                },
-            },
-        ]
         sections_data = [
             [
                 'lua',
@@ -975,7 +1037,7 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
                 [
                     ['ip', ''],
                     ['mac', 'foo'],
-                    ['dst mac', '@@2'],
+                    ['dst mac', '@@1'],
                     ['tx port', '1'],
                 ],
             ],
@@ -1004,7 +1066,7 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
                 [
                     ['ip', ''],
                     ['mac', 'hardware'],
-                    ['dst mac', '00:00:00:de:ad:ff'],
+                    ['dst mac', '00:00:00:00:00:03'],
                     ['tx port', '1'],
                 ],
             ],
@@ -1012,7 +1074,7 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
                 'port 2',
                 [
                     ['ip', ''],
-                    ['$sut_mac0', '00 00 00 de ad 88'],
+                    ['$sut_mac0', '00 00 00 00 00 04'],
                     ['tx port', '0'],
                     ['single', '@'],
                     ['user_table', 'dofile("/tmp/ipv4.lua")'],
@@ -1079,48 +1141,26 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
             helper.generate_prox_config_file('a/b')
 
     def test_generate_prox_lua_file(self):
-        vnfd_helper = mock.MagicMock()
-        vnfd_helper.interfaces = []
+        vnfd_helper = VnfdHelper(self.VNFD0)
         ssh_helper = mock.MagicMock()
         scenario_helper = mock.MagicMock()
 
         helper = ProxDpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
         helper.LUA_PARAMETER_NAME = 'sut'
 
-        expected = ''
-        result = helper.generate_prox_lua_file()
-        self.assertEqual(result, expected)
-
-        vnfd_helper.interfaces = [
-            {
-                'local_ip': '10.20.30.40',
-                'dst_ip': '10.11.12.13',
-                'virtual-interface': {
-                    'dpdk_port_num': 3,
-                },
-            },
-            {
-                'local_ip': '10.20.30.45',
-                'dst_ip': '10.11.12.19',
-                'virtual-interface': {
-                    'dpdk_port_num': 7,
-                },
-            },
+        expected = [
+            'sut_hex_ip_port_0:"98 10 64 13"',
+            'sut_ip_port_0:"152.16.100.19"',
+            'gen_hex_ip_port_0:"98 10 64 13"',
+            'gen_ip_port_0:"152.16.100.19"',
+
+            'sut_hex_ip_port_1:"98 10 28 13"',
+            'sut_ip_port_1:"152.16.40.19"',
+            'gen_hex_ip_port_1:"98 10 28 14"',
+            'gen_ip_port_1:"152.16.40.20"',
         ]
-
-        expected = os.linesep.join([
-            'sut_hex_ip_port_3:"0a 14 1e 28"',
-            'sut_ip_port_3:"10.20.30.40"',
-            'gen_hex_ip_port_3:"0a 0b 0c 0d"',
-            'gen_ip_port_3:"10.11.12.13"',
-
-            'sut_hex_ip_port_7:"0a 14 1e 2d"',
-            'sut_ip_port_7:"10.20.30.45"',
-            'gen_hex_ip_port_7:"0a 0b 0c 13"',
-            'gen_ip_port_7:"10.11.12.19"',
-        ])
         result = helper.generate_prox_lua_file()
-        self.assertEqual(result, expected)
+        self.assertListEqual(result.splitlines(), expected)
 
     def test_upload_prox_lua(self):
         def identity(*args):
@@ -1198,6 +1238,111 @@ class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
 
 
 class TestProxResourceHelper(unittest.TestCase):
+
+    VNFD0 = {
+        'short-name': 'ProxVnf',
+        'vdu': [
+            {
+                'routing_table': [
+                    {
+                        'network': '152.16.100.20',
+                        'netmask': '255.255.255.0',
+                        'gateway': '152.16.100.20',
+                        'if': 'xe0',
+                    },
+                    {
+                        'network': '152.16.40.20',
+                        'netmask': '255.255.255.0',
+                        'gateway': '152.16.40.20',
+                        'if': 'xe1',
+                    },
+                ],
+                'description': 'PROX approximation using DPDK',
+                'name': 'proxvnf-baremetal',
+                'nd_route_tbl': [
+                    {
+                        'network': '0064:ff9b:0:0:0:0:9810:6414',
+                        'netmask': '112',
+                        'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+                        'if': 'xe0',
+                    },
+                    {
+                        'network': '0064:ff9b:0:0:0:0:9810:2814',
+                        'netmask': '112',
+                        'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+                        'if': 'xe1',
+                    },
+                ],
+                'id': 'proxvnf-baremetal',
+                'external-interface': [
+                    {
+                        'virtual-interface': {
+                            'dst_mac': '00:00:00:00:00:04',
+                            'vpci': '0000:05:00.0',
+                            'local_ip': '152.16.100.19',
+                            'type': 'PCI-PASSTHROUGH',
+                            'vld_id': 'private_0',
+                            'netmask': '255.255.255.0',
+                            'dpdk_port_num': 0,
+                            'bandwidth': '10 Gbps',
+                            'driver': "i40e",
+                            'dst_ip': '152.16.100.19',
+                            'local_iface_name': 'xe0',
+                            'local_mac': '00:00:00:00:00:02',
+                            'ifname': 'xe0',
+                        },
+                        'vnfd-connection-point-ref': 'xe0',
+                        'name': 'xe0',
+                    },
+                    {
+                        'virtual-interface': {
+                            'dst_mac': '00:00:00:00:00:03',
+                            'vpci': '0000:05:00.1',
+                            'local_ip': '152.16.40.19',
+                            'type': 'PCI-PASSTHROUGH',
+                            'vld_id': 'public_0',
+                            'driver': "i40e",
+                            'netmask': '255.255.255.0',
+                            'dpdk_port_num': 1,
+                            'bandwidth': '10 Gbps',
+                            'dst_ip': '152.16.40.20',
+                            'local_iface_name': 'xe1',
+                            'local_mac': '00:00:00:00:00:01',
+                            'ifname': 'xe1',
+                        },
+                        'vnfd-connection-point-ref': 'xe1',
+                        'name': 'xe1',
+                    },
+                ],
+            },
+        ],
+        'description': 'PROX approximation using DPDK',
+        'mgmt-interface': {
+            'vdu-id': 'proxvnf-baremetal',
+            'host': '1.2.1.1',
+            'password': 'r00t',
+            'user': 'root',
+            'ip': '1.2.1.1',
+        },
+        'benchmark': {
+            'kpi': [
+                'packets_in',
+                'packets_fwd',
+                'packets_dropped',
+            ],
+        },
+        'id': 'ProxApproxVnf',
+        'name': 'ProxVnf',
+    }
+
+    VNFD = {
+        'vnfd:vnfd-catalog': {
+            'vnfd': [
+                VNFD0,
+            ],
+        },
+    }
+
     def test_line_rate_to_pps(self):
         expected = 0.25 * 1e8
         result = ProxResourceHelper.line_rate_to_pps(180, 4)
@@ -1603,8 +1748,30 @@ class TestProxResourceHelper(unittest.TestCase):
         def measure(*args, **kwargs):
             yield stats
 
+        bad_vnfd = copy.deepcopy(self.VNFD0)
+        bad_vnfd['vdu'][0]['external-interface'].append({
+            'virtual-interface': {
+                'dst_mac': '00:00:00:00:00:05',
+                'vpci': '0000:06:00.0',
+                'local_ip': '152.16.100.20',
+                'type': 'PCI-PASSTHROUGH',
+                'vld_id': 'private_1',
+                'netmask': '255.255.255.0',
+                'dpdk_port_num': 0,
+                'bandwidth': '10 Gbps',
+                'driver': "i40e",
+                'dst_ip': '152.16.100.20',
+                'local_iface_name': 'xe2',
+                'local_mac': '00:00:00:00:00:07',
+                'ifname': 'xe2',
+            },
+            'vnfd-connection-point-ref': 'xe2',
+            'name': 'xe2',
+        })
+
+        bad_vnfd_helper = VnfdHelper(bad_vnfd)
         setup_helper = mock.MagicMock()
-        setup_helper.vnfd_helper.interfaces = []
+        setup_helper.vnfd_helper = bad_vnfd_helper
 
         stats = {
             'delta': TotStatsTuple(6, 7, 8, 9),
@@ -1622,25 +1789,21 @@ class TestProxResourceHelper(unittest.TestCase):
         with self.assertRaises(AssertionError):
             helper.run_test(980, 15, 45)
 
-        setup_helper.vnfd_helper.interfaces = [
-            {'name': 'a', 'virtual-interface': {'vpci': 'z'}},
-            {'name': 'b', 'virtual-interface': {'vpci': 'y'}},
-            {'name': 'c', 'virtual-interface': {'vpci': 'x'}},
-            {'name': 'd', 'virtual-interface': {'vpci': 'w'}},
-        ]
+        vnfd_helper = VnfdHelper(self.VNFD0)
+        setup_helper.vnfd_helper = vnfd_helper
+        helper = ProxResourceHelper(setup_helper)
+        helper.client = client
+        helper.get_latency = mock.MagicMock(return_value=[3.3, 3.6, 3.8])
         helper._test_cores = [3, 4]
 
-        expected_test_data = ProxTestDataTuple(0.0, 2.0, 6, 7, 8, [3.3, 3.6, 3.8], 6, 7, 1.3e7)
+        expected_test_data = ProxTestDataTuple(0.0, 2.0, 6, 7, 8, [3.3, 3.6, 3.8], 6, 7, 6.5e6)
         expected_port_samples = {
-            'a': {'in_packets': 6, 'out_packets': 7},
-            'b': {'in_packets': 6, 'out_packets': 7},
-            'c': {'in_packets': 6, 'out_packets': 7},
-            'd': {'in_packets': 6, 'out_packets': 7},
+            'xe0': {'in_packets': 6, 'out_packets': 7},
+            'xe1': {'in_packets': 6, 'out_packets': 7},
         }
         test_data, port_samples = helper.run_test(230, 60, 65)
-        self.assertEqual(test_data, expected_test_data, '\n'.join(str(x) for x in test_data))
-        self.assertEqual(port_samples, expected_port_samples,
-                         '\n'.join(str(x) for x in port_samples))
+        self.assertTupleEqual(test_data, expected_test_data)
+        self.assertDictEqual(port_samples, expected_port_samples)
 
     def test_get_latency(self):
         setup_helper = mock.MagicMock()
index 4b115f2..2e83caf 100644 (file)
@@ -87,7 +87,7 @@ class TestProxApproxVnf(unittest.TestCase):
                             'type': 'PCI-PASSTHROUGH',
                             'vld_id': '',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'driver': "i40e",
                             'dst_ip': '152.16.100.20',
@@ -106,7 +106,7 @@ class TestProxApproxVnf(unittest.TestCase):
                             'vld_id': '',
                             'driver': "i40e",
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
                             'local_iface_name': 'xe1',
index 983c21e..fa73348 100644 (file)
@@ -98,10 +98,12 @@ class TestVnfSshHelper(unittest.TestCase):
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.100.20',
-                            'local_mac': '00:00:00:00:00:01'
+                            'local_mac': '00:00:00:00:00:01',
+                            'vld_id': 'private_0',
+                            'ifname': 'xe0',
                         },
                         'vnfd-connection-point-ref': 'xe0',
                         'name': 'xe0'
@@ -113,10 +115,12 @@ class TestVnfSshHelper(unittest.TestCase):
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
-                            'local_mac': '00:00:00:00:00:02'
+                            'local_mac': '00:00:00:00:00:02',
+                            'vld_id': 'public_0',
+                            'ifname': 'xe1',
                         },
                         'vnfd-connection-point-ref': 'xe1',
                         'name': 'xe1'
@@ -292,10 +296,12 @@ class TestSetupEnvHelper(unittest.TestCase):
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.100.20',
-                            'local_mac': '00:00:00:00:00:01'
+                            'local_mac': '00:00:00:00:00:01',
+                            'vld_id': 'private_0',
+                            'ifname': 'xe0',
                         },
                         'vnfd-connection-point-ref': 'xe0',
                         'name': 'xe0'
@@ -307,10 +313,12 @@ class TestSetupEnvHelper(unittest.TestCase):
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
-                            'local_mac': '00:00:00:00:00:02'
+                            'local_mac': '00:00:00:00:00:02',
+                            'vld_id': 'public_0',
+                            'ifname': 'xe1',
                         },
                         'vnfd-connection-point-ref': 'xe1',
                         'name': 'xe1'
@@ -414,12 +422,11 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
                         'virtual-interface': {
                             'dst_mac': '00:00:00:00:00:03',
                             'vpci': '0000:05:00.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'driver': 'i40e',
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.100.20',
                             'local_mac': '00:00:00:00:00:01',
@@ -433,12 +440,11 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
                         'virtual-interface': {
                             'dst_mac': '00:00:00:00:00:04',
                             'vpci': '0000:05:00.1',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'driver': 'ixgbe',
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
                             'local_mac': '00:00:00:00:00:02',
@@ -549,7 +555,8 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
         call_args_iter = (args[0][0] for args in ssh_helper.execute.call_args_list)
         self.assertIsNone(result)
         self.assertEqual(ssh_helper.execute.call_count, 3)
-        for expect_start, expect_in, arg0 in zip(expect_start_list, expect_in_list, call_args_iter):
+        for expect_start, expect_in, arg0 in zip(expect_start_list, expect_in_list,
+                                                 call_args_iter):
             self.assertTrue(arg0.startswith(expect_start))
             self.assertIn(expect_in, arg0)
 
@@ -566,19 +573,11 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
         call_args_iter = (args[0][0] for args in ssh_helper.execute.call_args_list)
         self.assertIsNone(result)
         self.assertEqual(ssh_helper.execute.call_count, 3)
-        for expect_start, expect_in, arg0 in zip(expect_start_list, expect_in_list, call_args_iter):
+        for expect_start, expect_in, arg0 in zip(expect_start_list, expect_in_list,
+                                                 call_args_iter):
             self.assertTrue(arg0.startswith(expect_start))
             self.assertIn(expect_in, arg0)
 
-    def test__get_dpdk_port_num(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        expected = '0'
-        result = dpdk_setup_helper._get_dpdk_port_num('xe0')
-        self.assertEqual(result, expected)
-
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open')
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.find_relative_file')
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig')
@@ -590,7 +589,6 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
         scenario_helper.vnf_cfg = {}
         scenario_helper.all_options = {}
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        dpdk_setup_helper.all_ports = []
 
         dpdk_setup_helper.PIPELINE_COMMAND = expected = 'pipeline command'
         result = dpdk_setup_helper.build_config()
@@ -614,7 +612,7 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
         expected = {
             'cfg_file': 'config',
             'script': 'script',
-            'ports_len_hex': '0xf',
+            'port_mask_hex': '0x3',
             'tool_path': 'tool_path',
         }
         dpdk_setup_helper._build_pipeline_kwargs()
@@ -725,73 +723,24 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
         result = dpdk_setup_helper._validate_cpu_cfg()
         self.assertEqual(result, expected)
 
-    def test__find_used_drivers(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        stdout = '''
-00:01.2 foo drv=name1
-00:01.4 drv foo=name2
-00:02.2 drv=name3
-00:02.3 drv=name4
-'''
-        ssh_helper.execute.return_value = 0, stdout, ''
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        dpdk_setup_helper.used_drivers = None
-        dpdk_setup_helper._dpdk_nic_bind = ''
-        dpdk_setup_helper.bound_pci = [
-            'pci 00:01.2',
-            'pci 00:02.3',
-        ]
+    @mock.patch('yardstick.ssh.SSH')
+    def test_setup_vnf_environment(self, _):
+        def execute(cmd, *args, **kwargs):
+            if cmd.startswith('which '):
+                return exec_failure
+            return exec_success
 
-        expected = {
-            '00:01.2': (0, 'name1'),
-            '00:02.3': (2, 'name4'),
-        }
-        dpdk_setup_helper._find_used_drivers()
-        self.assertEqual(dpdk_setup_helper.used_drivers, expected)
+        exec_success = (0, 'good output', '')
+        exec_failure = (1, 'bad output', 'error output')
 
-    def test_dpdk_nic_bind(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
-        ssh_helper.provision_tool.return_value = nic_bind = object()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        ssh_helper.execute = execute
 
-        self.assertIsNone(dpdk_setup_helper._dpdk_nic_bind)
-        self.assertIs(dpdk_setup_helper.dpdk_nic_bind, nic_bind)
-        self.assertIs(dpdk_setup_helper.dpdk_nic_bind, nic_bind)
-        self.assertEqual(ssh_helper.provision_tool.call_count, 1)
+        dpdk_vnf_setup_env_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, mock.Mock())
+        dpdk_vnf_setup_env_helper._validate_cpu_cfg = mock.Mock(return_value=[])
 
-        # ensure provision tool is not called a second time
-        self.assertIs(dpdk_setup_helper.dpdk_nic_bind, nic_bind)
-        self.assertEqual(ssh_helper.provision_tool.call_count, 1)
-
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
-    @mock.patch('yardstick.ssh.SSH')
-    def test_setup_vnf_environment(self, _, mock_time):
-        cores = ['3', '4']
-
-        vnfd_helper = VnfdHelper(deepcopy(self.VNFD_0))
-        ssh_helper = mock.Mock()
-        ssh_helper.execute.return_value = 1, 'bad output', 'error output'
-        ssh_helper.join_bin_path.return_value = 'joined_path'
-        ssh_helper.provision_tool.return_value = 'provision string'
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        dpdk_setup_helper._setup_hugepages = mock.Mock()
-        dpdk_setup_helper._validate_cpu_cfg = mock.Mock(return_value=cores)
-        dpdk_setup_helper._find_used_drivers = mock.Mock()
-        dpdk_setup_helper.used_drivers = {
-            '0000:05:00.0': (1, ''),
-            '0000:05:01.0': (3, ''),
-        }
-
-        result = dpdk_setup_helper.setup_vnf_environment()
-        self.assertIsInstance(result, ResourceProfile)
-        self.assertEqual(result.cores, cores)
-        self.assertEqual(vnfd_helper.interfaces[0]['dpdk_port_num'], 1)
-        self.assertNotIn('dpdk_port_num', vnfd_helper.interfaces[1])
+        self.assertIsInstance(dpdk_vnf_setup_env_helper.setup_vnf_environment(), ResourceProfile)
 
     def test__setup_dpdk_early_success(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
@@ -851,83 +800,146 @@ class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
         self.assertIsInstance(result, ResourceProfile)
         self.assertEqual(dpdk_setup_helper.socket, 1)
 
-    def test__bind_dpdk_unforced(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-
-        dpdk_setup_helper._bind_dpdk('x', 'y', force=False)
-        self.assertNotIn('--force', ssh_helper.execute.call_args_list[0][0][0])
-
-    def test__detect_and_bind_dpdk_short(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        ssh_helper.execute.return_value = 0, 'output', ''
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-
-        self.assertIsNone(dpdk_setup_helper._detect_and_bind_dpdk('a', 'b'))
-        self.assertEqual(ssh_helper.execute.call_count, 1)
-
-    def test__detect_and_bind_dpdk_fail_to_bind(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
+    def test__detect_and_bind_drivers(self):
+        vnfd_helper = VnfdHelper(deepcopy(self.VNFD_0))
         ssh_helper = mock.Mock()
-        ssh_helper.execute.return_value = 1, 'bad output', 'error output'
+        # ssh_helper.execute = mock.Mock(return_value = (0, 'text', ''))
+        # ssh_helper.execute.return_value = 0, 'output', ''
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        dpdk_setup_helper._bind_dpdk = mock.Mock()
-
-        self.assertIsNone(dpdk_setup_helper._detect_and_bind_dpdk('a', 'b'))
-        self.assertEqual(ssh_helper.execute.call_count, 2)
+        rv = ['0000:05:00.1', '0000:05:00.0']
 
-    def test__detect_and_bind_dpdk(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        ssh_helper.execute.side_effect = iter([
-            (1, 'bad output', 'error output'),
-            (0, 'output', ''),
-        ])
-        scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        dpdk_setup_helper._bind_dpdk = mock.Mock()
-
-        self.assertEqual(dpdk_setup_helper._detect_and_bind_dpdk('a', 'b'), 'output')
-        self.assertEqual(ssh_helper.execute.call_count, 2)
+        dpdk_setup_helper.dpdk_bind_helper._get_bound_pci_addresses = mock.Mock(return_value=rv)
+        dpdk_setup_helper.dpdk_bind_helper.bind = mock.Mock()
+        dpdk_setup_helper.dpdk_bind_helper.read_status = mock.Mock()
 
-    def test__bind_kernel_devices(self):
-        bind_iter = iter([
-            None,
-            'output',
-        ])
+        self.assertIsNone(dpdk_setup_helper._detect_and_bind_drivers())
 
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        dpdk_setup_helper._detect_and_bind_dpdk = mock.Mock(side_effect=bind_iter)
-
-        self.assertIsNone(dpdk_setup_helper._bind_kernel_devices())
+        intf_0 = vnfd_helper.vdu[0]['external-interface'][0]['virtual-interface']
+        intf_1 = vnfd_helper.vdu[0]['external-interface'][1]['virtual-interface']
+        self.assertEquals(0, intf_0['dpdk_port_num'])
+        self.assertEquals(1, intf_1['dpdk_port_num'])
 
     def test_tear_down(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        dpdk_setup_helper._dpdk_nic_bind = 'a'
-        dpdk_setup_helper.used_drivers = {
-            '0000:05:00.0': (1, 'd1'),
-            '0000:05:01.0': (3, 'd3'),
+        dpdk_setup_helper.dpdk_bind_helper.bind = mock.Mock()
+        dpdk_setup_helper.dpdk_bind_helper.used_drivers = {
+            '0000:05:00.0': 'd1',
+            '0000:05:01.0': 'd3',
         }
 
         self.assertIsNone(dpdk_setup_helper.tear_down())
+        dpdk_setup_helper.dpdk_bind_helper.bind.assert_any_call('0000:05:00.0', 'd1', True)
+        dpdk_setup_helper.dpdk_bind_helper.bind.assert_any_call('0000:05:01.0', 'd3', True)
 
 
 class TestResourceHelper(unittest.TestCase):
 
+    VNFD_0 = {
+        'short-name': 'VpeVnf',
+        'vdu': [
+            {
+                'routing_table': [
+                    {
+                        'network': '152.16.100.20',
+                        'netmask': '255.255.255.0',
+                        'gateway': '152.16.100.20',
+                        'if': 'xe0'
+                    },
+                    {
+                        'network': '152.16.40.20',
+                        'netmask': '255.255.255.0',
+                        'gateway': '152.16.40.20',
+                        'if': 'xe1'
+                    },
+                ],
+                'description': 'VPE approximation using DPDK',
+                'name': 'vpevnf-baremetal',
+                'nd_route_tbl': [
+                    {
+                        'network': '0064:ff9b:0:0:0:0:9810:6414',
+                        'netmask': '112',
+                        'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+                        'if': 'xe0'
+                    },
+                    {
+                        'network': '0064:ff9b:0:0:0:0:9810:2814',
+                        'netmask': '112',
+                        'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+                        'if': 'xe1'
+                    },
+                ],
+                'id': 'vpevnf-baremetal',
+                'external-interface': [
+                    {
+                        'virtual-interface': {
+                            'dst_mac': '00:00:00:00:00:03',
+                            'vpci': '0000:05:00.0',
+                            'driver': 'i40e',
+                            'local_ip': '152.16.100.19',
+                            'type': 'PCI-PASSTHROUGH',
+                            'netmask': '255.255.255.0',
+                            'dpdk_port_num': 0,
+                            'bandwidth': '10 Gbps',
+                            'dst_ip': '152.16.100.20',
+                            'local_mac': '00:00:00:00:00:01'
+                        },
+                        'vnfd-connection-point-ref': 'xe0',
+                        'name': 'xe0'
+                    },
+                    {
+                        'virtual-interface': {
+                            'dst_mac': '00:00:00:00:00:04',
+                            'vpci': '0000:05:00.1',
+                            'driver': 'ixgbe',
+                            'local_ip': '152.16.40.19',
+                            'type': 'PCI-PASSTHROUGH',
+                            'netmask': '255.255.255.0',
+                            'dpdk_port_num': 1,
+                            'bandwidth': '10 Gbps',
+                            'dst_ip': '152.16.40.20',
+                            'local_mac': '00:00:00:00:00:02'
+                        },
+                        'vnfd-connection-point-ref': 'xe1',
+                        'name': 'xe1'
+                    },
+                ],
+            },
+        ],
+        'description': 'Vpe approximation using DPDK',
+        'mgmt-interface': {
+            'vdu-id': 'vpevnf-baremetal',
+            'host': '1.1.1.1',
+            'password': 'r00t',
+            'user': 'root',
+            'ip': '1.1.1.1'
+        },
+        'benchmark': {
+            'kpi': [
+                'packets_in',
+                'packets_fwd',
+                'packets_dropped',
+            ],
+        },
+        'connection-point': [
+            {
+                'type': 'VPORT',
+                'name': 'xe0',
+            },
+            {
+                'type': 'VPORT',
+                'name': 'xe1',
+            },
+        ],
+        'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+    }
+
     def test_setup(self):
         resource = object()
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -938,7 +950,7 @@ class TestResourceHelper(unittest.TestCase):
         self.assertIs(resource_helper.resource, resource)
 
     def test_generate_cfg(self):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -947,7 +959,7 @@ class TestResourceHelper(unittest.TestCase):
         self.assertIsNone(resource_helper.generate_cfg())
 
     def test_stop_collect(self):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -957,7 +969,7 @@ class TestResourceHelper(unittest.TestCase):
         self.assertIsNone(resource_helper.stop_collect())
 
     def test_stop_collect_none(self):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -966,6 +978,7 @@ class TestResourceHelper(unittest.TestCase):
 
         self.assertIsNone(resource_helper.stop_collect())
 
+
 class TestClientResourceHelper(unittest.TestCase):
 
     VNFD_0 = {
@@ -1012,10 +1025,12 @@ class TestClientResourceHelper(unittest.TestCase):
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.100.20',
-                            'local_mac': '00:00:00:00:00:01'
+                            'local_mac': '00:00:00:00:00:01',
+                            'vld_id': 'private_0',
+                            'ifname': 'xe0',
                         },
                         'vnfd-connection-point-ref': 'xe0',
                         'name': 'xe0'
@@ -1028,10 +1043,12 @@ class TestClientResourceHelper(unittest.TestCase):
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
-                            'local_mac': '00:00:00:00:00:02'
+                            'local_mac': '00:00:00:00:00:02',
+                            'vld_id': 'public_0',
+                            'ifname': 'xe1',
                         },
                         'vnfd-connection-point-ref': 'xe1',
                         'name': 'xe1'
@@ -1044,7 +1061,7 @@ class TestClientResourceHelper(unittest.TestCase):
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 2,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.30',
                             'local_mac': '00:00:00:00:00:11'
@@ -1095,7 +1112,7 @@ class TestClientResourceHelper(unittest.TestCase):
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.STLError',
                 new_callable=lambda: MockError)
     def test_get_stats_not_connected(self, mock_state_error, mock_logger):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -1151,16 +1168,9 @@ class TestClientResourceHelper(unittest.TestCase):
                 "in_packets": 0,
                 "out_packets": 48791,
             },
-            'xe2': {
-                "rx_throughput_fps": 0.0,
-                "tx_throughput_fps": 0.0,
-                "rx_throughput_mbps": 0.0,
-                "tx_throughput_mbps": 0.0,
-                "in_packets": 0,
-                "out_packets": 0,
-            },
         }
-        result = client_resource_helper.generate_samples()
+        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
+        result = client_resource_helper.generate_samples(ports)
         self.assertDictEqual(result, expected)
 
     def test_generate_samples_with_key(self):
@@ -1211,7 +1221,8 @@ class TestClientResourceHelper(unittest.TestCase):
                 "out_packets": 48791,
             },
         }
-        result = client_resource_helper.generate_samples('key_name')
+        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
+        result = client_resource_helper.generate_samples(ports, 'key_name')
         self.assertDictEqual(result, expected)
 
     def test_generate_samples_with_key_and_default(self):
@@ -1261,11 +1272,12 @@ class TestClientResourceHelper(unittest.TestCase):
                 "out_packets": 48791,
             },
         }
-        result = client_resource_helper.generate_samples('key_name', 'default')
+        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
+        result = client_resource_helper.generate_samples(ports, 'key_name', 'default')
         self.assertDictEqual(result, expected)
 
     def test_clear_stats(self):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -1276,7 +1288,7 @@ class TestClientResourceHelper(unittest.TestCase):
         self.assertEqual(client_resource_helper.client.clear_stats.call_count, 1)
 
     def test_clear_stats_of_ports(self):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -1287,7 +1299,7 @@ class TestClientResourceHelper(unittest.TestCase):
         self.assertEqual(client_resource_helper.client.clear_stats.call_count, 1)
 
     def test_start(self):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -1298,7 +1310,7 @@ class TestClientResourceHelper(unittest.TestCase):
         self.assertEqual(client_resource_helper.client.start.call_count, 1)
 
     def test_start_ports(self):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -1309,7 +1321,7 @@ class TestClientResourceHelper(unittest.TestCase):
         self.assertEqual(client_resource_helper.client.start.call_count, 1)
 
     def test_collect_kpi_with_queue(self):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -1332,7 +1344,7 @@ class TestClientResourceHelper(unittest.TestCase):
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.STLError',
                 new_callable=lambda: MockError)
     def test__connect_with_failures(self, mock_error, mock_logger, mock_time):
-        vnfd_helper = VnfdHelper({})
+        vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
@@ -1667,7 +1679,7 @@ class TestSampleVnf(unittest.TestCase):
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.100.20',
                             'local_mac': '00:00:00:00:00:01'
@@ -1682,7 +1694,7 @@ class TestSampleVnf(unittest.TestCase):
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
                             'local_mac': '00:00:00:00:00:02'
@@ -1757,7 +1769,6 @@ class TestSampleVnf(unittest.TestCase):
         class MySetupEnvHelper(SetupEnvHelper):
             pass
 
-
         class MyResourceHelper(ResourceHelper):
             pass
 
@@ -1895,6 +1906,16 @@ class TestSampleVnf(unittest.TestCase):
 
         self.assertEqual(sample_vnf.wait_for_instantiate(), 0)
 
+    def test__build_ports(self):
+        vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+        sample_vnf = SampleVNF('vnf1', vnfd)
+
+        self.assertIsNone(sample_vnf._build_ports())
+        self.assertIsNotNone(sample_vnf.networks)
+        self.assertIsNotNone(sample_vnf.priv_ports)
+        self.assertIsNotNone(sample_vnf.pub_ports)
+        self.assertIsNotNone(sample_vnf.my_ports)
+
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
     def test_vnf_execute_with_queue_data(self, mock_time):
         queue_size_list = [
@@ -2022,7 +2043,7 @@ class TestSampleVNFTrafficGen(unittest.TestCase):
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.100.20',
                             'local_mac': '00:00:00:00:00:01'
@@ -2038,7 +2059,7 @@ class TestSampleVNFTrafficGen(unittest.TestCase):
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
                             'local_mac': '00:00:00:00:00:02'
@@ -2046,22 +2067,6 @@ class TestSampleVNFTrafficGen(unittest.TestCase):
                         'vnfd-connection-point-ref': 'xe1',
                         'name': 'xe1'
                     },
-                    {
-                        'virtual-interface': {
-                            'dst_mac': '00:00:00:00:00:13',
-                            'vpci': '0000:05:00.2',
-                            'driver': 'ixgbe',
-                            'local_ip': '152.16.40.19',
-                            'type': 'PCI-PASSTHROUGH',
-                            'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
-                            'bandwidth': '10 Gbps',
-                            'dst_ip': '152.16.40.30',
-                            'local_mac': '00:00:00:00:00:11'
-                        },
-                        'vnfd-connection-point-ref': 'xe2',
-                        'name': 'xe2'
-                    },
                 ],
             },
         ],
@@ -2174,7 +2179,7 @@ class TestSampleVNFTrafficGen(unittest.TestCase):
 
         mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
-        mock_traffic_profile.execute.return_value = "64"
+        mock_traffic_profile.execute_traffic.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
         sample_vnf_tg = SampleVNFTrafficGen('tg1', self.VNFD_0)
index c65c0ab..e6e4b88 100644 (file)
@@ -70,7 +70,7 @@ class TestIxLoadTrafficGen(unittest.TestCase):
                     'local_ip': '152.16.100.19',
                     'type': 'PCI-PASSTHROUGH',
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '0',
+                    'dpdk_port_num': 0,
                     'bandwidth': '10 Gbps',
                     'driver': "i40e",
                     'dst_ip': '152.16.100.20',
@@ -85,7 +85,7 @@ class TestIxLoadTrafficGen(unittest.TestCase):
                     'type': 'PCI-PASSTHROUGH',
                     'driver': "i40e",
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '1',
+                    'dpdk_port_num': 1,
                     'bandwidth': '10 Gbps',
                     'dst_ip': '152.16.40.20',
                     'local_iface_name': 'xe1',
index 45bbfae..c1b2d27 100644 (file)
@@ -20,6 +20,7 @@ from __future__ import absolute_import
 import unittest
 import mock
 from multiprocessing import Queue
+import multiprocessing
 
 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
 from tests.unit import STL_MOCKS
@@ -31,11 +32,40 @@ stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
 stl_patch.start()
 
 if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.tg_ping import PingParser, PingTrafficGen
-    from yardstick.network_services.traffic_profile.base import TrafficProfile
+    from yardstick.network_services.vnf_generic.vnf.tg_ping import PingParser
+    from yardstick.network_services.vnf_generic.vnf.tg_ping import PingTrafficGen
+    from yardstick.network_services.vnf_generic.vnf.tg_ping import PingResourceHelper
+    from yardstick.network_services.vnf_generic.vnf.tg_ping import PingSetupEnvHelper
     from yardstick.network_services.vnf_generic.vnf.sample_vnf import VnfSshHelper
 
 
+class TestPingResourceHelper(unittest.TestCase):
+    def test___init__(self):
+        setup_helper = mock.Mock()
+        helper = PingResourceHelper(setup_helper)
+
+        self.assertIsInstance(helper._queue, multiprocessing.queues.Queue)
+        self.assertIsInstance(helper._parser, PingParser)
+
+    def test_run_traffic(self):
+        setup_helper = mock.Mock()
+        traffic_profile = mock.Mock()
+        traffic_profile.params = {
+            'traffic_profile': {
+                'frame_size': 64,
+            },
+        }
+
+        helper = PingResourceHelper(setup_helper)
+        helper.cmd_kwargs = {'target_ip': '10.0.0.2',
+                             'local_ip': '10.0.0.1',
+                             'local_if_name': 'eth0',
+                             }
+        helper.ssh_helper = mock.Mock()
+        helper.run_traffic(traffic_profile)
+        helper.ssh_helper.run.called_with('ping-s 64 10.0.0.2')
+
+
 class TestPingParser(unittest.TestCase):
     def test___init__(self):
         q_out = Queue()
@@ -69,7 +99,6 @@ class TestPingParser(unittest.TestCase):
 
 
 class TestPingTrafficGen(unittest.TestCase):
-
     VNFD_0_EXT_IF_0 = {
         'virtual-interface': {
             'dst_mac': '00:00:00:00:00:04',
@@ -77,7 +106,6 @@ class TestPingTrafficGen(unittest.TestCase):
             'local_ip': u'152.16.100.19',
             'type': 'PCI-PASSTHROUGH',
             'netmask': '255.255.255.0',
-            'dpdk_port_num': '0',
             'bandwidth': '10 Gbps',
             'driver': "i40e",
             'dst_ip': u'152.16.100.20',
@@ -96,14 +124,13 @@ class TestPingTrafficGen(unittest.TestCase):
             'type': 'PCI-PASSTHROUGH',
             'driver': "i40e",
             'netmask': '255.255.255.0',
-            'dpdk_port_num': '1',
             'bandwidth': '10 Gbps',
             'dst_ip': u'152.16.40.20',
             'local_iface_name': 'xe1',
             'local_mac': '00:00:00:00:00:01',
         },
-       'vnfd-connection-point-ref': 'xe1',
-       'name': 'xe1',
+        'vnfd-connection-point-ref': 'xe1',
+        'name': 'xe1',
     }
 
     VNFD_0_EXT_IF_LIST = [
@@ -151,7 +178,7 @@ class TestPingTrafficGen(unittest.TestCase):
         ],
         'description': 'Vpe approximation using DPDK',
         'mgmt-interface': {
-        'vdu-id': 'vpevnf-baremetal',
+            'vdu-id': 'vpevnf-baremetal',
             'host': '1.1.1.1',
             'password': 'r00t',
             'user': 'root',
@@ -198,11 +225,20 @@ class TestPingTrafficGen(unittest.TestCase):
         },
     }
 
+    CMD_KWARGS = {
+        'target_ip': u'152.16.100.20',
+        'local_ip': u'152.16.100.19',
+        'local_if_name': u'xe0',
+    }
+
     @mock.patch("yardstick.ssh.SSH")
     def test___init__(self, ssh):
         ssh.from_node.return_value.execute.return_value = 0, "success", ""
         ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
-        self.assertIsNotNone(ping_traffic_gen._queue)
+
+        self.assertIsInstance(ping_traffic_gen.setup_helper, PingSetupEnvHelper)
+        self.assertIsInstance(ping_traffic_gen.resource_helper, PingResourceHelper)
+        self.assertEquals(ping_traffic_gen._result, {})
 
     @mock.patch("yardstick.ssh.SSH")
     def test__bind_device_kernel_with_failure(self, ssh):
@@ -234,35 +270,23 @@ class TestPingTrafficGen(unittest.TestCase):
         mock_ssh(ssh, spec=VnfSshHelper, exec_result=(0, "success", ""))
         ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
         ping_traffic_gen.setup_helper.ssh_helper = mock.MagicMock(
-            **{"execute.return_value": (0, "", "")})
+            **{"execute.return_value": (0, "success", "")})
         self.assertIsInstance(ping_traffic_gen.ssh_helper, mock.Mock)
         self.assertEqual(ping_traffic_gen._result, {})
+
         self.assertIsNone(ping_traffic_gen.instantiate({}, {}))
+
+        self.assertEqual(
+            ping_traffic_gen.vnfd_helper.interfaces[0]['virtual-interface']['local_iface_name'],
+            'success')
+        self.assertEqual(self.CMD_KWARGS, ping_traffic_gen.resource_helper.cmd_kwargs)
         self.assertIsNotNone(ping_traffic_gen._result)
 
     @mock.patch("yardstick.ssh.SSH")
     def test_listen_traffic(self, ssh):
-        ssh.from_node.return_value.execute.return_value = 0, "success", ""
         ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
         self.assertIsNone(ping_traffic_gen.listen_traffic({}))
 
-    @mock.patch(SSH_HELPER)
-    def test_run_traffic_process(self, ssh):
-        mock_ssh(ssh)
-
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
-        mock_traffic_profile.get_traffic_definition.return_value = "64"
-        mock_traffic_profile.params = self.TRAFFIC_PROFILE
-
-        ssh.from_node.return_value.execute.return_value = 0, "success", ""
-        ssh.from_node.return_value.run.return_value = 0, "success", ""
-
-        sut = PingTrafficGen('vnf1', self.VNFD_0)
-        sut._traffic_runner(mock_traffic_profile)
-        sut.ssh_helper.run.assert_called_with(
-            "ping -s 64 152.16.100.20",
-            stdout=sut._parser, keep_stdin_open=True, pty=True)
-
     @mock.patch("yardstick.ssh.SSH")
     def test_scale_negative(self, ssh):
         ssh.from_node.return_value.execute.return_value = 0, "success", ""
@@ -277,4 +301,4 @@ class TestPingTrafficGen(unittest.TestCase):
         ssh.from_node.return_value.run.return_value = 0, "success", ""
 
         ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
-        self.assertIsNone(ping_traffic_gen.terminate())
\ No newline at end of file
+        self.assertIsNone(ping_traffic_gen.terminate())
index a12abb6..d1f2470 100644 (file)
@@ -80,7 +80,7 @@ class TestProxTrafficGen(unittest.TestCase):
                             'type': 'PCI-PASSTHROUGH',
                             'vld_id': '',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'driver': "i40e",
                             'dst_ip': '152.16.100.20',
@@ -99,7 +99,7 @@ class TestProxTrafficGen(unittest.TestCase):
                             'vld_id': '',
                             'driver': "i40e",
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
                             'local_iface_name': 'xe1',
@@ -349,8 +349,10 @@ class TestProxTrafficGen(unittest.TestCase):
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
         prox_traffic_gen = ProxTrafficGen(NAME, vnfd)
-        prox_traffic_gen.ssh_helper = mock.MagicMock(
+        ssh_helper = mock.MagicMock(
             **{"execute.return_value": (0, "", ""), "bin_path": ""})
+        prox_traffic_gen.ssh_helper = ssh_helper
+        prox_traffic_gen.setup_helper.dpdk_bind_helper.ssh_helper = ssh_helper
         prox_traffic_gen.setup_helper._setup_resources = mock.MagicMock()
         prox_traffic_gen.setup_hugepages = mock.MagicMock()
         prox_traffic_gen.generate_prox_config_file = mock.MagicMock()
@@ -384,7 +386,7 @@ class TestProxTrafficGen(unittest.TestCase):
 
         mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
-        mock_traffic_profile.execute.return_value = "64"
+        mock_traffic_profile.execute_traffic.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
index 3c5ccef..0e303dc 100644 (file)
@@ -23,7 +23,6 @@ import mock
 
 from tests.unit import STL_MOCKS
 
-
 STLClient = mock.MagicMock()
 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
 stl_patch.start()
@@ -36,13 +35,11 @@ if stl_patch:
 
 TEST_FILE_YAML = 'nsb_test_case.yaml'
 
-
 NAME = "tg__1"
 
 
 @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.IxNextgen")
 class TestIxiaResourceHelper(unittest.TestCase):
-
     def test___init___with_custom_rfc_helper(self, mock_ix_nextgen):
         class MyRfcHelper(IxiaRfc2544Helper):
             pass
@@ -63,71 +60,71 @@ class TestIxiaResourceHelper(unittest.TestCase):
 @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.IxNextgen")
 class TestIXIATrafficGen(unittest.TestCase):
     VNFD = {'vnfd:vnfd-catalog':
-            {'vnfd':
-             [{'short-name': 'VpeVnf',
-               'vdu':
-               [{'routing_table':
-                 [{'network': '152.16.100.20',
-                   'netmask': '255.255.255.0',
-                   'gateway': '152.16.100.20',
-                   'if': 'xe0'},
-                  {'network': '152.16.40.20',
-                   'netmask': '255.255.255.0',
-                   'gateway': '152.16.40.20',
-                   'if': 'xe1'}],
-                 'description': 'VPE approximation using DPDK',
-                 'name': 'vpevnf-baremetal',
-                 'nd_route_tbl':
-                 [{'network': '0064:ff9b:0:0:0:0:9810:6414',
-                   'netmask': '112',
-                   'gateway': '0064:ff9b:0:0:0:0:9810:6414',
-                   'if': 'xe0'},
-                  {'network': '0064:ff9b:0:0:0:0:9810:2814',
-                   'netmask': '112',
-                   'gateway': '0064:ff9b:0:0:0:0:9810:2814',
-                   'if': 'xe1'}],
-                 'id': 'vpevnf-baremetal',
-                 'external-interface':
-                 [{'virtual-interface':
-                   {'dst_mac': '00:00:00:00:00:04',
-                    'vpci': '0000:05:00.0',
-                    'local_ip': '152.16.100.19',
-                    'type': 'PCI-PASSTHROUGH',
-                    'netmask': '255.255.255.0',
-                    'dpdk_port_num': '0',
-                    'bandwidth': '10 Gbps',
-                    'driver': "i40e",
-                    'dst_ip': '152.16.100.20',
-                    'local_iface_name': 'xe0',
-                    'local_mac': '00:00:00:00:00:02'},
-                   'vnfd-connection-point-ref': 'xe0',
-                   'name': 'xe0'},
-                  {'virtual-interface':
-                   {'dst_mac': '00:00:00:00:00:03',
-                    'vpci': '0000:05:00.1',
-                    'local_ip': '152.16.40.19',
-                    'type': 'PCI-PASSTHROUGH',
-                    'driver': "i40e",
-                    'netmask': '255.255.255.0',
-                    'dpdk_port_num': '1',
-                    'bandwidth': '10 Gbps',
-                    'dst_ip': '152.16.40.20',
-                    'local_iface_name': 'xe1',
-                    'local_mac': '00:00:00:00:00:01'},
-                   'vnfd-connection-point-ref': 'xe1',
-                   'name': 'xe1'}]}],
-               'description': 'Vpe approximation using DPDK',
-               'mgmt-interface':
-                   {'vdu-id': 'vpevnf-baremetal',
-                    'host': '1.1.1.1',
-                    'password': 'r00t',
-                    'user': 'root',
-                    'ip': '1.1.1.1'},
-               'benchmark':
-                   {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
-               'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
-                                    {'type': 'VPORT', 'name': 'xe1'}],
-               'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
+                {'vnfd':
+                     [{'short-name': 'VpeVnf',
+                       'vdu':
+                           [{'routing_table':
+                                 [{'network': '152.16.100.20',
+                                   'netmask': '255.255.255.0',
+                                   'gateway': '152.16.100.20',
+                                   'if': 'xe0'},
+                                  {'network': '152.16.40.20',
+                                   'netmask': '255.255.255.0',
+                                   'gateway': '152.16.40.20',
+                                   'if': 'xe1'}],
+                             'description': 'VPE approximation using DPDK',
+                             'name': 'vpevnf-baremetal',
+                             'nd_route_tbl':
+                                 [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+                                   'netmask': '112',
+                                   'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+                                   'if': 'xe0'},
+                                  {'network': '0064:ff9b:0:0:0:0:9810:2814',
+                                   'netmask': '112',
+                                   'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+                                   'if': 'xe1'}],
+                             'id': 'vpevnf-baremetal',
+                             'external-interface':
+                                 [{'virtual-interface':
+                                       {'dst_mac': '00:00:00:00:00:04',
+                                        'vpci': '0000:05:00.0',
+                                        'local_ip': '152.16.100.19',
+                                        'type': 'PCI-PASSTHROUGH',
+                                        'netmask': '255.255.255.0',
+                                        'dpdk_port_num': 0,
+                                        'bandwidth': '10 Gbps',
+                                        'driver': "i40e",
+                                        'dst_ip': '152.16.100.20',
+                                        'local_iface_name': 'xe0',
+                                        'local_mac': '00:00:00:00:00:02'},
+                                   'vnfd-connection-point-ref': 'xe0',
+                                   'name': 'xe0'},
+                                  {'virtual-interface':
+                                       {'dst_mac': '00:00:00:00:00:03',
+                                        'vpci': '0000:05:00.1',
+                                        'local_ip': '152.16.40.19',
+                                        'type': 'PCI-PASSTHROUGH',
+                                        'driver': "i40e",
+                                        'netmask': '255.255.255.0',
+                                        'dpdk_port_num': 1,
+                                        'bandwidth': '10 Gbps',
+                                        'dst_ip': '152.16.40.20',
+                                        'local_iface_name': 'xe1',
+                                        'local_mac': '00:00:00:00:00:01'},
+                                   'vnfd-connection-point-ref': 'xe1',
+                                   'name': 'xe1'}]}],
+                       'description': 'Vpe approximation using DPDK',
+                       'mgmt-interface':
+                           {'vdu-id': 'vpevnf-baremetal',
+                            'host': '1.1.1.1',
+                            'password': 'r00t',
+                            'user': 'root',
+                            'ip': '1.1.1.1'},
+                       'benchmark':
+                           {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+                       'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+                                            {'type': 'VPORT', 'name': 'xe1'}],
+                       'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
 
     TRAFFIC_PROFILE = {
         "schema": "isb:traffic_profile:0.1",
@@ -140,12 +137,12 @@ class TestIXIATrafficGen(unittest.TestCase):
             "frame_size": 64}}
 
     TC_YAML = {'scenarios': [{'tc_options':
-                              {'rfc2544': {'allowed_drop_rate': '0.8 - 1'}},
+                                  {'rfc2544': {'allowed_drop_rate': '0.8 - 1'}},
                               'runner': {'duration': 400,
                                          'interval': 35, 'type': 'Duration'},
                               'traffic_options':
-                              {'flow': 'ipv4_1flow_Packets_vpe.yaml',
-                               'imix': 'imix_voice.yaml'},
+                                  {'flow': 'ipv4_1flow_Packets_vpe.yaml',
+                                   'imix': 'imix_voice.yaml'},
                               'vnf_options': {'vpe': {'cfg': 'vpe_config'}},
                               'traffic_profile': 'ipv4_throughput_vpe.yaml',
                               'type': 'NSPerf',
@@ -195,7 +192,7 @@ class TestIXIATrafficGen(unittest.TestCase):
                                                         'vnf_config': {'lb_config': 'SW',
                                                                        'lb_count': 1,
                                                                        'worker_config':
-                                                                       '1C/1T',
+                                                                           '1C/1T',
                                                                        'worker_threads': 1}}
                                              }})
             ixnet_traffic_gen.topology = ""
@@ -255,6 +252,7 @@ class TestIXIATrafficGen(unittest.TestCase):
         mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
+        mock_traffic_profile.ports = [0, 1]
 
         mock_ssh_instance = mock.Mock(autospec=mock_ssh.SSH)
         mock_ssh_instance.execute.return_value = 0, "", ""
@@ -306,11 +304,10 @@ class TestIXIATrafficGen(unittest.TestCase):
             },
         ]
 
-        mock_traffic_profile.execute.return_value = ['Completed', samples]
+        mock_traffic_profile.execute_traffic.return_value = ['Completed', samples]
         mock_traffic_profile.get_drop_percentage.return_value = ['Completed', samples]
 
         sut = IxiaTrafficGen(name, vnfd)
-        sut.tg_port_pairs = [[[0], [1]]]
         sut.vnf_port_pairs = [[[0], [1]]]
         sut.tc_file_name = self._get_file_abspath(TEST_FILE_YAML)
         sut.topology = ""
@@ -349,7 +346,8 @@ class TestIXIATrafficGen(unittest.TestCase):
             'task_path': '/path/to/task'
         }
 
-        with mock.patch('yardstick.benchmark.scenarios.networking.vnf_generic.open', create=True) as mock_open:
+        with mock.patch('yardstick.benchmark.scenarios.networking.vnf_generic.open',
+                        create=True) as mock_open:
             mock_open.return_value = mock.MagicMock()
             result = sut._traffic_runner(mock_traffic_profile)
             self.assertIsNone(result)
index 6f2a944..0fe0c3d 100644 (file)
@@ -24,7 +24,6 @@ from tests.unit import STL_MOCKS
 SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
 
 
-
 STLClient = mock.MagicMock()
 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
 stl_patch.start()
@@ -101,8 +100,8 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
                             'netmask': '255.255.255.0',
-                            'vld_id': 'private_1',
-                            'dpdk_port_num': '0',
+                            'vld_id': 'private_0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'driver': "i40e",
                             'dst_ip': '152.16.100.20',
@@ -121,8 +120,8 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
                             'type': 'PCI-PASSTHROUGH',
                             'driver': "i40e",
                             'netmask': '255.255.255.0',
-                            'vld_id': 'public_1',
-                            'dpdk_port_num': '1',
+                            'vld_id': 'public_0',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
                             'local_iface_name': 'xe1',
index 9d1ce15..4fd4c4c 100644 (file)
@@ -25,7 +25,6 @@ SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper
 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
 from tests.unit import STL_MOCKS
 
-
 NAME = 'vnf_1'
 
 STLClient = mock.MagicMock()
@@ -34,77 +33,77 @@ stl_patch.start()
 
 if stl_patch:
     from yardstick.network_services.vnf_generic.vnf.tg_trex import \
-    TrexTrafficGen, TrexResourceHelper
+        TrexTrafficGen, TrexResourceHelper
     from yardstick.network_services.traffic_profile.base import TrafficProfile
 
 
 class TestTrexTrafficGen(unittest.TestCase):
     VNFD = {'vnfd:vnfd-catalog':
-            {'vnfd':
-             [{'short-name': 'VpeVnf',
-               'vdu':
-               [{'routing_table':
-                 [{'network': '152.16.100.20',
-                   'netmask': '255.255.255.0',
-                   'gateway': '152.16.100.20',
-                   'if': 'xe0'},
-                  {'network': '152.16.40.20',
-                   'netmask': '255.255.255.0',
-                   'gateway': '152.16.40.20',
-                   'if': 'xe1'}],
-                 'description': 'VPE approximation using DPDK',
-                 'name': 'vpevnf-baremetal',
-                 'nd_route_tbl':
-                 [{'network': '0064:ff9b:0:0:0:0:9810:6414',
-                   'netmask': '112',
-                   'gateway': '0064:ff9b:0:0:0:0:9810:6414',
-                   'if': 'xe0'},
-                  {'network': '0064:ff9b:0:0:0:0:9810:2814',
-                   'netmask': '112',
-                   'gateway': '0064:ff9b:0:0:0:0:9810:2814',
-                   'if': 'xe1'}],
-                 'id': 'vpevnf-baremetal',
-                 'external-interface':
-                 [{'virtual-interface':
-                   {'dst_mac': '00:00:00:00:00:04',
-                    'vpci': '0000:05:00.0',
-                    'local_ip': '152.16.100.19',
-                    'type': 'PCI-PASSTHROUGH',
-                    'netmask': '255.255.255.0',
-                    'dpdk_port_num': '0',
-                    'bandwidth': '10 Gbps',
-                    'driver': "i40e",
-                    'dst_ip': '152.16.100.20',
-                    'local_iface_name': 'xe0',
-                    'local_mac': '00:00:00:00:00:02'},
-                   'vnfd-connection-point-ref': 'xe0',
-                   'name': 'xe0'},
-                  {'virtual-interface':
-                   {'dst_mac': '00:00:00:00:00:03',
-                    'vpci': '0000:05:00.1',
-                    'local_ip': '152.16.40.19',
-                    'type': 'PCI-PASSTHROUGH',
-                    'driver': "i40e",
-                    'netmask': '255.255.255.0',
-                    'dpdk_port_num': '1',
-                    'bandwidth': '10 Gbps',
-                    'dst_ip': '152.16.40.20',
-                    'local_iface_name': 'xe1',
-                    'local_mac': '00:00:00:00:00:01'},
-                   'vnfd-connection-point-ref': 'xe1',
-                   'name': 'xe1'}]}],
-               'description': 'Vpe approximation using DPDK',
-               'mgmt-interface':
-                   {'vdu-id': 'vpevnf-baremetal',
-                    'host': '1.1.1.1',
-                    'password': 'r00t',
-                    'user': 'root',
-                    'ip': '1.1.1.1'},
-               'benchmark':
-                   {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
-               'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
-                                    {'type': 'VPORT', 'name': 'xe1'}],
-               'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
+                {'vnfd':
+                     [{'short-name': 'VpeVnf',
+                       'vdu':
+                           [{'routing_table':
+                                 [{'network': '152.16.100.20',
+                                   'netmask': '255.255.255.0',
+                                   'gateway': '152.16.100.20',
+                                   'if': 'xe0'},
+                                  {'network': '152.16.40.20',
+                                   'netmask': '255.255.255.0',
+                                   'gateway': '152.16.40.20',
+                                   'if': 'xe1'}],
+                             'description': 'VPE approximation using DPDK',
+                             'name': 'vpevnf-baremetal',
+                             'nd_route_tbl':
+                                 [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+                                   'netmask': '112',
+                                   'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+                                   'if': 'xe0'},
+                                  {'network': '0064:ff9b:0:0:0:0:9810:2814',
+                                   'netmask': '112',
+                                   'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+                                   'if': 'xe1'}],
+                             'id': 'vpevnf-baremetal',
+                             'external-interface':
+                                 [{'virtual-interface':
+                                       {'dst_mac': '00:00:00:00:00:04',
+                                        'vpci': '0000:05:00.0',
+                                        'local_ip': '152.16.100.19',
+                                        'type': 'PCI-PASSTHROUGH',
+                                        'netmask': '255.255.255.0',
+                                        'dpdk_port_num': 0,
+                                        'bandwidth': '10 Gbps',
+                                        'driver': "i40e",
+                                        'dst_ip': '152.16.100.20',
+                                        'local_iface_name': 'xe0',
+                                        'local_mac': '00:00:00:00:00:02'},
+                                   'vnfd-connection-point-ref': 'xe0',
+                                   'name': 'xe0'},
+                                  {'virtual-interface':
+                                       {'dst_mac': '00:00:00:00:00:03',
+                                        'vpci': '0000:05:00.1',
+                                        'local_ip': '152.16.40.19',
+                                        'type': 'PCI-PASSTHROUGH',
+                                        'driver': "i40e",
+                                        'netmask': '255.255.255.0',
+                                        'dpdk_port_num': 1,
+                                        'bandwidth': '10 Gbps',
+                                        'dst_ip': '152.16.40.20',
+                                        'local_iface_name': 'xe1',
+                                        'local_mac': '00:00:00:00:00:01'},
+                                   'vnfd-connection-point-ref': 'xe1',
+                                   'name': 'xe1'}]}],
+                       'description': 'Vpe approximation using DPDK',
+                       'mgmt-interface':
+                           {'vdu-id': 'vpevnf-baremetal',
+                            'host': '1.1.1.1',
+                            'password': 'r00t',
+                            'user': 'root',
+                            'ip': '1.1.1.1'},
+                       'benchmark':
+                           {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+                       'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+                                            {'type': 'VPORT', 'name': 'xe1'}],
+                       'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
 
     TRAFFIC_PROFILE = {
         "schema": "isb:traffic_profile:0.1",
@@ -295,8 +294,6 @@ class TestTrexTrafficGen(unittest.TestCase):
         }
     }
 
-
-
     @mock.patch(SSH_HELPER)
     def test___init__(self, ssh):
         mock_ssh(ssh)
@@ -367,7 +364,7 @@ class TestTrexTrafficGen(unittest.TestCase):
 
         mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
-        mock_traffic_profile.execute.return_value = "64"
+        mock_traffic_profile.execute_traffic.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
@@ -432,5 +429,6 @@ class TestTrexTrafficGen(unittest.TestCase):
         client.connect = mock.Mock(return_value=0)
         self.assertIsNotNone(trex_traffic_gen.resource_helper._connect(client))
 
+
 if __name__ == '__main__':
     unittest.main()
index c4ced30..95bc08b 100644 (file)
@@ -31,6 +31,7 @@ stl_patch.start()
 
 if stl_patch:
     from yardstick.network_services.vnf_generic.vnf.udp_replay import UdpReplayApproxVnf
+    from yardstick.network_services.nfvi.resource import ResourceProfile
     from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
 
 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
@@ -73,10 +74,12 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
                             'local_ip': '152.16.100.19',
                             'local_mac': '00:00:00:00:00:02',
                             'vpci': '0000:05:00.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'netmask': '255.255.255.0',
                             'dst_ip': '152.16.100.20',
                             'type': 'PCI-PASSTHROUGH',
+                            'vld_id': 'private_0',
+                            'ifname': 'xe0',
                         },
                         'vnfd-connection-point-ref': 'xe0',
                         'name': 'xe0',
@@ -90,10 +93,12 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
                             'local_ip': '152.16.40.19',
                             'local_mac': '00:00:00:00:00:01',
                             'vpci': '0000:05:00.1',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'netmask': '255.255.255.0',
                             'dst_ip': '152.16.40.20',
                             'type': 'PCI-PASSTHROUGH',
+                            'vld_id': 'public_0',
+                            'ifname': 'xe1',
                         },
                         'vnfd-connection-point-ref': 'xe1',
                         'name': 'xe1',
@@ -342,21 +347,12 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
         udp_replay_approx_vnf.q_in = mock.MagicMock()
         udp_replay_approx_vnf.q_out = mock.MagicMock()
         udp_replay_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
-        udp_replay_approx_vnf.all_ports = [0, 1]
+        udp_replay_approx_vnf.all_ports = ["xe0", "xe1"]
         udp_replay_approx_vnf.get_stats = mock.Mock(return_value=result)
         result = {'collect_stats': {}, 'packets_dropped': 0,
                   'packets_fwd': 14748451, 'packets_in': 14748472}
         self.assertEqual(result, udp_replay_approx_vnf.collect_kpi())
 
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
-    @mock.patch(SSH_HELPER)
-    def test_vnf_execute_command(self, ssh, mock_time, _):
-        mock_ssh(ssh)
-
-        udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
-        cmd = "quit"
-        self.assertEqual("", udp_replay_approx_vnf.vnf_execute(cmd))
-
     @mock.patch(SSH_HELPER)
     def test_get_stats(self, ssh, _):
         mock_ssh(ssh)
@@ -378,7 +374,6 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
         file_path = os.path.join(curr_path, filename)
         return file_path
 
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.udp_replay.open')
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
     @mock.patch(SSH_HELPER)
     def test__build_config(self, ssh, mock_context, *_):
@@ -389,14 +384,14 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
         udp_replay_approx_vnf.nfvi_context = mock_context
         udp_replay_approx_vnf.nfvi_context.attrs = {'nfvi_type': 'baremetal'}
         udp_replay_approx_vnf.setup_helper.bound_pci = []
-        udp_replay_approx_vnf.all_ports = [0, 1]
         udp_replay_approx_vnf.ssh_helper.provision_tool = mock.MagicMock(return_value="tool_path")
         udp_replay_approx_vnf.scenario_helper = ScenarioHelper(name='vnf__1')
         udp_replay_approx_vnf.scenario_helper.scenario_cfg = self.SCENARIO_CFG
 
         cmd_line = udp_replay_approx_vnf._build_config()
 
-        expected = "sudo tool_path -c 0x7 -n 4 -w  --  -p 0x3 --config='(0, 0, 1)(1, 0, 2)'"
+        expected = \
+            "sudo tool_path --log-level=5 -c 0x7 -n 4 -w  --  -p 0x3 --config='(0,0,1),(1,0,2)'"
         self.assertEqual(cmd_line, expected)
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.udp_replay.open')
@@ -404,14 +399,11 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
     @mock.patch(SSH_HELPER)
     def test__build_pipeline_kwargs(self, ssh, mock_context, *_):
         mock_ssh(ssh)
-
         udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
-        udp_replay_approx_vnf._build_config = mock.MagicMock()
-        udp_replay_approx_vnf.queue_wrapper = mock.MagicMock()
         udp_replay_approx_vnf.nfvi_context = mock_context
         udp_replay_approx_vnf.nfvi_context.attrs = {'nfvi_type': 'baremetal'}
-        udp_replay_approx_vnf.setup_helper.bound_pci = []
-        udp_replay_approx_vnf.all_ports = [0, 1]
+        udp_replay_approx_vnf.setup_helper.bound_pci = ['0000:00:0.1', '0000:00:0.3']
+        udp_replay_approx_vnf.all_ports = ["xe0", "xe1"]
         udp_replay_approx_vnf.ssh_helper.provision_tool = mock.MagicMock(return_value="tool_path")
         udp_replay_approx_vnf.scenario_helper = ScenarioHelper(name='vnf__1')
         udp_replay_approx_vnf.scenario_helper.scenario_cfg = self.SCENARIO_CFG
@@ -419,12 +411,12 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
         udp_replay_approx_vnf._build_pipeline_kwargs()
 
         self.assertEqual(udp_replay_approx_vnf.pipeline_kwargs, {
-            'config': '(0, 0, 1)(1, 0, 2)',
+            'config': '(0,0,1),(1,0,2)',
             'cpu_mask_hex': '0x7',
             'hw_csum': '',
-            'ports_len_hex': '0x3',
+            'port_mask_hex': '0x3',
             'tool_path': 'tool_path',
-            'whitelist': ''
+            'whitelist': '0000:00:0.1 -w 0000:00:0.3'
         })
 
     @mock.patch(SSH_HELPER)
@@ -444,13 +436,14 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
     def test_instantiate(self, ssh, *_):
         mock_ssh(ssh)
 
+        resource = mock.Mock(autospec=ResourceProfile)
+
         udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
         udp_replay_approx_vnf.q_out.put("Replay>")
         udp_replay_approx_vnf.WAIT_TIME = 0
         udp_replay_approx_vnf.setup_helper.setup_vnf_environment = mock.Mock()
 
-        self.assertIsNone(udp_replay_approx_vnf.instantiate(self.SCENARIO_CFG,
-                                                     self.CONTEXT_CFG))
+        self.assertIsNone(udp_replay_approx_vnf.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG))
 
         udp_replay_approx_vnf._vnf_process.is_alive = mock.Mock(return_value=1)
         udp_replay_approx_vnf._vnf_process.exitcode = 0
@@ -484,8 +477,7 @@ class TestUdpReplayApproxVnf(unittest.TestCase):
         udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
         udp_replay_approx_vnf._vnf_process = mock.MagicMock()
         udp_replay_approx_vnf._vnf_process.terminate = mock.Mock()
-        udp_replay_approx_vnf.used_drivers = {"01:01.0": "i40e",
-                                       "01:01.1": "i40e"}
+        udp_replay_approx_vnf.used_drivers = {"01:01.0": "i40e", "01:01.1": "i40e"}
         udp_replay_approx_vnf.dpdk_nic_bind = "dpdk_nic_bind.py"
         self.assertEqual(None, udp_replay_approx_vnf.terminate())
 
index c3d53ff..38cc177 100644 (file)
@@ -73,7 +73,7 @@ class TestFWApproxVnf(unittest.TestCase):
                     'local_ip': '152.16.100.19',
                     'type': 'PCI-PASSTHROUGH',
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '0',
+                    'dpdk_port_num': 0,
                     'bandwidth': '10 Gbps',
                     'driver': "i40e",
                     'dst_ip': '152.16.100.20',
@@ -88,7 +88,7 @@ class TestFWApproxVnf(unittest.TestCase):
                     'type': 'PCI-PASSTHROUGH',
                     'driver': "i40e",
                     'netmask': '255.255.255.0',
-                    'dpdk_port_num': '1',
+                    'dpdk_port_num': 1,
                     'bandwidth': '10 Gbps',
                     'dst_ip': '152.16.40.20',
                     'local_iface_name': 'xe1',
index ffd0d53..e210aa0 100644 (file)
@@ -36,8 +36,8 @@ stl_patch.start()
 if stl_patch:
     from yardstick.network_services.vnf_generic.vnf.vpe_vnf import ConfigCreate
     from yardstick.network_services.nfvi.resource import ResourceProfile
-    from yardstick.network_services.vnf_generic.vnf import vpe_vnf
-    from yardstick.network_services.vnf_generic.vnf.vpe_vnf import VpeApproxVnf
+    from yardstick.network_services.vnf_generic.vnf.vpe_vnf import \
+        VpeApproxVnf, VpeApproxSetupEnvHelper
 
 from tests.unit.network_services.vnf_generic.vnf.test_base import FileAbsPath
 from tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
@@ -185,14 +185,15 @@ class TestVpeApproxVnf(unittest.TestCase):
                             'vpci': '0000:05:00.0',
                             'local_ip': '152.16.100.19',
                             'type': 'PCI-PASSTHROUGH',
-                            'vld_id': '',
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '0',
+                            'dpdk_port_num': 0,
                             'bandwidth': '10 Gbps',
                             'driver': "i40e",
                             'dst_ip': '152.16.100.20',
                             'local_iface_name': 'xe0',
                             'local_mac': '00:00:00:00:00:02',
+                            'vld_id': 'private_0',
+                            'ifname': 'xe0',
                         },
                         'vnfd-connection-point-ref': 'xe0',
                         'name': 'xe0',
@@ -203,14 +204,15 @@ class TestVpeApproxVnf(unittest.TestCase):
                             'vpci': '0000:05:00.1',
                             'local_ip': '152.16.40.19',
                             'type': 'PCI-PASSTHROUGH',
-                            'vld_id': '',
                             'driver': "i40e",
                             'netmask': '255.255.255.0',
-                            'dpdk_port_num': '1',
+                            'dpdk_port_num': 1,
                             'bandwidth': '10 Gbps',
                             'dst_ip': '152.16.40.20',
                             'local_iface_name': 'xe1',
                             'local_mac': '00:00:00:00:00:01',
+                            'vld_id': 'public_0',
+                            'ifname': 'xe1',
                         },
                         'vnfd-connection-point-ref': 'xe1',
                         'name': 'xe1',
@@ -258,7 +260,7 @@ class TestVpeApproxVnf(unittest.TestCase):
     SCENARIO_CFG = {
         'options': {
             'packetsize': 64,
-            'traffic_type': 4 ,
+            'traffic_type': 4,
             'rfc2544': {
                 'allowed_drop_rate': '0.8 - 1',
             },
@@ -499,6 +501,40 @@ class TestVpeApproxVnf(unittest.TestCase):
 
         vpe_approx_vnf = VpeApproxVnf(NAME, self.VNFD_0)
         vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
+        vpe_approx_vnf.vnf_cfg = {
+            'lb_config': 'SW',
+            'lb_count': 1,
+            'worker_config': '1C/1T',
+            'worker_threads': 1,
+        }
+        vpe_approx_vnf.scenario_helper.scenario_cfg = {
+            'options': {
+                NAME: {
+                    'traffic_type': '4',
+                    'topology': 'nsb_test_case.yaml',
+                    'vnf_config': 'vpe_config',
+                }
+            }
+        }
+        vpe_approx_vnf.topology = "nsb_test_case.yaml"
+        vpe_approx_vnf.nfvi_type = "baremetal"
+        vpe_approx_vnf._provide_config_file = mock.Mock()
+        vpe_approx_vnf._build_config = mock.MagicMock()
+
+        self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
+        self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
+        self.assertIsNone(vpe_approx_vnf._run())
+
+    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig")
+    @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
+    @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.ConfigCreate")
+    @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.open")
+    @mock.patch(SSH_HELPER)
+    def test_build_config(self, mock_mul, mock_context, mock_config, mock_open, ssh, _):
+        mock_ssh(ssh)
+        vpe_approx_vnf = VpeApproxSetupEnvHelper(mock.MagicMock(),
+                                                 mock.MagicMock, mock.MagicMock)
+        vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
         vpe_approx_vnf.generate_port_pairs = mock.Mock()
         vpe_approx_vnf.tg_port_pairs = [[[0], [1]]]
         vpe_approx_vnf.vnf_port_pairs = [[[0], [1]]]
@@ -513,6 +549,7 @@ class TestVpeApproxVnf(unittest.TestCase):
                 NAME: {
                     'traffic_type': '4',
                     'topology': 'nsb_test_case.yaml',
+                    'vnf_config': 'vpe_config',
                 }
             }
         }
@@ -520,8 +557,12 @@ class TestVpeApproxVnf(unittest.TestCase):
         vpe_approx_vnf.nfvi_type = "baremetal"
         vpe_approx_vnf._provide_config_file = mock.Mock()
 
-        self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
-        self.assertIsNone(vpe_approx_vnf._run())
+        vpe_approx_vnf.ssh_helper = mock.MagicMock()
+        vpe_approx_vnf.scenario_helper = mock.MagicMock()
+        vpe_approx_vnf.ssh_helper.bin_path = mock.Mock()
+        vpe_approx_vnf.ssh_helper.upload_config_file = mock.MagicMock()
+        self.assertIsNone(vpe_approx_vnf._build_vnf_ports())
+        self.assertIsNotNone(vpe_approx_vnf.build_config())
 
     @mock.patch(SSH_HELPER)
     def test_wait_for_instantiate(self, ssh, _):
index 94a3824..a4bec63 100644 (file)
@@ -83,9 +83,14 @@ class HeatContext(Context):
         external_network = os.environ.get("EXTERNAL_NETWORK", "net04_ext")
 
         have_external_network = any(net.get("external_network") for net in networks.values())
-        if sorted_networks and not have_external_network:
-            # no external net defined, assign it to first network using os.environ
-            sorted_networks[0][1]["external_network"] = external_network
+        if not have_external_network:
+            # try looking for mgmt network first
+            try:
+                networks['mgmt']["external_network"] = external_network
+            except KeyError:
+                if sorted_networks:
+                    # otherwise assign it to first network using os.environ
+                    sorted_networks[0][1]["external_network"] = external_network
 
         return sorted_networks
 
@@ -328,16 +333,21 @@ class HeatContext(Context):
         print("Context '%s' deployed" % self.name)
 
     def add_server_port(self, server):
-        # TODO(hafe) can only handle one internal network for now
-        # use private ip from first port
-        private_port = next(iter(server.ports.values()))
+        # use private ip from first port in first network
+        try:
+            private_port = next(iter(server.ports.values()))[0]
+        except IndexError:
+            LOG.exception("Unable to find first private port in %s", server.ports)
+            raise
         server.private_ip = self.stack.outputs[private_port["stack_name"]]
         server.interfaces = {}
-        for network_name, port in server.ports.items():
-            # port['port'] is either port name from mapping or default network_name
-            server.interfaces[port['port']] = self.make_interface_dict(network_name, port['port'],
-                                                                       port['stack_name'],
-                                                                       self.stack.outputs)
+        for network_name, ports in server.ports.items():
+            for port in ports:
+                # port['port'] is either port name from mapping or default network_name
+                server.interfaces[port['port']] = self.make_interface_dict(network_name,
+                                                                           port['port'],
+                                                                           port['stack_name'],
+                                                                           self.stack.outputs)
 
     def make_interface_dict(self, network_name, port, stack_name, outputs):
         private_ip = outputs[stack_name]
index da2b74e..facfab8 100644 (file)
 
 """
 from __future__ import absolute_import
+
+import six
+import logging
 from six.moves import range
 
 
+LOG = logging.getLogger(__name__)
+
+
 class Object(object):
     """Base class for classes in the logical model
     Contains common attributes and methods
@@ -257,44 +263,51 @@ class Server(Object):     # pragma: no cover
             # if explicit mapping skip unused networks
             if self.network_ports:
                 try:
-                    port = self.network_ports[network.name]
+                    ports = self.network_ports[network.name]
                 except KeyError:
                     # no port for this network
                     continue
+                else:
+                    if isinstance(ports, six.string_types):
+                        if ports.startswith('-'):
+                            LOG.warning("possible YAML error, port name starts with - '%s", ports)
+                        ports = [ports]
             # otherwise add a port for every network with port name as network name
             else:
-                port = network.name
-            port_name = "{0}-{1}-port".format(server_name, port)
-            self.ports[network.name] = {"stack_name": port_name, "port": port}
-            # we can't use secgroups if port_security_enabled is False
-            if network.port_security_enabled is False:
-                sec_group_id = None
-            else:
-                # if port_security_enabled is None we still need to add to secgroup
-                sec_group_id = self.secgroup_name
-            # don't refactor to pass in network object, that causes JSON
-            # circular ref encode errors
-            template.add_port(port_name, network.stack_name, network.subnet_stack_name,
-                              network.vnic_type, sec_group_id=sec_group_id,
-                              provider=network.provider,
-                              allowed_address_pairs=network.allowed_address_pairs)
-            port_name_list.append(port_name)
-
-            if self.floating_ip:
-                external_network = self.floating_ip["external_network"]
-                if network.has_route_to(external_network):
-                    self.floating_ip["stack_name"] = server_name + "-fip"
-                    template.add_floating_ip(self.floating_ip["stack_name"],
-                                             external_network,
-                                             port_name,
-                                             network.router.stack_if_name,
-                                             sec_group_id)
-                    self.floating_ip_assoc["stack_name"] = \
-                        server_name + "-fip-assoc"
-                    template.add_floating_ip_association(
-                        self.floating_ip_assoc["stack_name"],
-                        self.floating_ip["stack_name"],
-                        port_name)
+                ports = [network.name]
+            for port in ports:
+                port_name = "{0}-{1}-port".format(server_name, port)
+                self.ports.setdefault(network.name, []).append(
+                    {"stack_name": port_name, "port": port})
+                # we can't use secgroups if port_security_enabled is False
+                if network.port_security_enabled is False:
+                    sec_group_id = None
+                else:
+                    # if port_security_enabled is None we still need to add to secgroup
+                    sec_group_id = self.secgroup_name
+                # don't refactor to pass in network object, that causes JSON
+                # circular ref encode errors
+                template.add_port(port_name, network.stack_name, network.subnet_stack_name,
+                                  network.vnic_type, sec_group_id=sec_group_id,
+                                  provider=network.provider,
+                                  allowed_address_pairs=network.allowed_address_pairs)
+                port_name_list.append(port_name)
+
+                if self.floating_ip:
+                    external_network = self.floating_ip["external_network"]
+                    if network.has_route_to(external_network):
+                        self.floating_ip["stack_name"] = server_name + "-fip"
+                        template.add_floating_ip(self.floating_ip["stack_name"],
+                                                 external_network,
+                                                 port_name,
+                                                 network.router.stack_if_name,
+                                                 sec_group_id)
+                        self.floating_ip_assoc["stack_name"] = \
+                            server_name + "-fip-assoc"
+                        template.add_floating_ip_association(
+                            self.floating_ip_assoc["stack_name"],
+                            self.floating_ip["stack_name"],
+                            port_name)
         if self.flavor:
             if isinstance(self.flavor, dict):
                 self.flavor["name"] = \
index 0e6ceab..ada9212 100644 (file)
@@ -25,7 +25,6 @@ import re
 from itertools import chain
 
 import six
-from operator import itemgetter
 from collections import defaultdict
 
 from yardstick.benchmark.scenarios import base
@@ -134,6 +133,7 @@ class NetworkServiceTestCase(base.Scenario):
         self.vnfs = []
         self.collector = None
         self.traffic_profile = None
+        self.node_netdevs = {}
 
     def _get_ip_flow_range(self, ip_start_range):
 
@@ -168,15 +168,17 @@ class NetworkServiceTestCase(base.Scenario):
     def _get_traffic_flow(self):
         flow = {}
         try:
+            # TODO: should be .0  or .1 so we can use list
+            # but this also roughly matches private_0, public_0
             fflow = self.scenario_cfg["options"]["flow"]
             for index, src in enumerate(fflow.get("src_ip", [])):
-                flow["src_ip{}".format(index)] = self._get_ip_flow_range(src)
+                flow["src_ip_{}".format(index)] = self._get_ip_flow_range(src)
 
             for index, dst in enumerate(fflow.get("dst_ip", [])):
-                flow["dst_ip{}".format(index)] = self._get_ip_flow_range(dst)
+                flow["dst_ip_{}".format(index)] = self._get_ip_flow_range(dst)
 
-            for index, publicip in enumerate(fflow.get("publicip", [])):
-                flow["public_ip{}".format(index)] = publicip
+            for index, publicip in enumerate(fflow.get("public_ip", [])):
+                flow["public_ip_{}".format(index)] = publicip
 
             flow["count"] = fflow["count"]
         except KeyError:
@@ -263,7 +265,6 @@ class NetworkServiceTestCase(base.Scenario):
                 node0_if["node_name"] = node0_name
                 node1_if["node_name"] = node1_name
 
-                vld_networks = self.get_vld_networks(self.context_cfg["networks"])
                 node0_if["vld_id"] = vld["id"]
                 node1_if["vld_id"] = vld["id"]
 
@@ -276,6 +277,7 @@ class NetworkServiceTestCase(base.Scenario):
                 node1_if["peer_ifname"] = node0_if_name
 
                 # just load the network
+                vld_networks = self.get_vld_networks(self.context_cfg["networks"])
                 node0_if["network"] = vld_networks.get(vld["id"], {})
                 node1_if["network"] = vld_networks.get(vld["id"], {})
 
@@ -325,16 +327,15 @@ class NetworkServiceTestCase(base.Scenario):
             vnfd = self._find_vnfd_from_vnf_idx(vnf_idx)
             self.context_cfg["nodes"][vnf_name].update(vnfd)
 
-    @staticmethod
-    def _sort_dpdk_port_num(netdevs):
-        # dpdk_port_num is PCI BUS ID ordering, lowest first
-        s = sorted(netdevs.values(), key=itemgetter('pci_bus_id'))
-        for dpdk_port_num, netdev in enumerate(s):
-            netdev['dpdk_port_num'] = dpdk_port_num
+    def _probe_netdevs(self, node, node_dict, timeout=120):
+        try:
+            return self.node_netdevs[node]
+        except KeyError:
+            pass
 
-    def _probe_netdevs(self, node, node_dict):
-        cmd = "PATH=$PATH:/sbin:/usr/sbin ip addr show"
         netdevs = {}
+        cmd = "PATH=$PATH:/sbin:/usr/sbin ip addr show"
+
         with SshManager(node_dict) as conn:
             if conn:
                 exit_status = conn.execute(cmd)[0]
@@ -346,6 +347,8 @@ class NetworkServiceTestCase(base.Scenario):
                     raise IncorrectSetup(
                         "Cannot find netdev info in sysfs" % node)
                 netdevs = node_dict['netdevs'] = self.parse_netdev_info(stdout)
+
+        self.node_netdevs[node] = netdevs
         return netdevs
 
     @classmethod
@@ -458,10 +461,22 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
                               (expected_name, classes_found))
 
     @staticmethod
-    def update_interfaces_from_node(vnfd, node):
-        for intf in vnfd["vdu"][0]["external-interface"]:
-            node_intf = node['interfaces'][intf['name']]
-            intf['virtual-interface'].update(node_intf)
+    def create_interfaces_from_node(vnfd, node):
+        ext_intfs = vnfd["vdu"][0]["external-interface"] = []
+        # have to sort so xe0 goes first
+        for intf_name, intf in sorted(node['interfaces'].items()):
+            if intf.get('vld_id'):
+                # force dpkd_port_num to int so we can do reverse lookup
+                try:
+                    intf['dpdk_port_num'] = int(intf['dpdk_port_num'])
+                except KeyError:
+                    pass
+                ext_intf = {
+                    "name": intf_name,
+                    "virtual-interface": intf,
+                    "vnfd-connection-point-ref": intf_name,
+                }
+                ext_intfs.append(ext_intf)
 
     def load_vnf_models(self, scenario_cfg=None, context_cfg=None):
         """ Create VNF objects based on YAML descriptors
@@ -491,7 +506,7 @@ printf "%s/driver:" $1 ; basename $(readlink -s $1/device/driver); } \
             vnfd = vnfdgen.generate_vnfd(vnf_model, node)
             # TODO: here add extra context_cfg["nodes"] regardless of template
             vnfd = vnfd["vnfd:vnfd-catalog"]["vnfd"][0]
-            self.update_interfaces_from_node(vnfd, node)
+            self.create_interfaces_from_node(vnfd, node)
             vnf_impl = self.get_vnf_impl(vnfd['id'])
             vnf_instance = vnf_impl(node_name, vnfd)
             vnfs.append(vnf_instance)
diff --git a/yardstick/network_services/helpers/dpdknicbind_helper.py b/yardstick/network_services/helpers/dpdknicbind_helper.py
new file mode 100644 (file)
index 0000000..605d08d
--- /dev/null
@@ -0,0 +1,145 @@
+# Copyright (c) 2016-2017 Intel Corporation
+#
+# 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.
+import re
+import itertools
+
+NETWORK_KERNEL = 'network_kernel'
+NETWORK_DPDK = 'network_dpdk'
+NETWORK_OTHER = 'network_other'
+CRYPTO_KERNEL = 'crypto_kernel'
+CRYPTO_DPDK = 'crypto_dpdk'
+CRYPTO_OTHER = 'crypto_other'
+
+
+class DpdkBindHelperException(Exception):
+    pass
+
+
+class DpdkBindHelper(object):
+    DPDK_STATUS_CMD = "{dpdk_nic_bind} --status"
+    DPDK_BIND_CMD = "sudo {dpdk_nic_bind} {force} -b {driver} {vpci}"
+
+    NIC_ROW_RE = re.compile("([^ ]+) '([^']+)' (?:if=([^ ]+) )?drv=([^ ]+) "
+                            "unused=([^ ]*)(?: (\*Active\*))?")
+    SKIP_RE = re.compile('(====|<none>|^$)')
+    NIC_ROW_FIELDS = ['vpci', 'dev_type', 'iface', 'driver', 'unused', 'active']
+
+    HEADER_DICT_PAIRS = [
+        (re.compile('^Network.*DPDK.*$'), NETWORK_DPDK),
+        (re.compile('^Network.*kernel.*$'), NETWORK_KERNEL),
+        (re.compile('^Other network.*$'), NETWORK_OTHER),
+        (re.compile('^Crypto.*DPDK.*$'), CRYPTO_DPDK),
+        (re.compile('^Crypto.*kernel$'), CRYPTO_KERNEL),
+        (re.compile('^Other crypto.*$'), CRYPTO_OTHER),
+    ]
+
+    def clean_status(self):
+        self.dpdk_status = {
+            NETWORK_KERNEL: [],
+            NETWORK_DPDK: [],
+            CRYPTO_KERNEL: [],
+            CRYPTO_DPDK: [],
+            NETWORK_OTHER: [],
+            CRYPTO_OTHER: [],
+        }
+
+    def __init__(self, ssh_helper):
+        self.dpdk_status = None
+        self.status_nic_row_re = None
+        self._dpdk_nic_bind_attr = None
+        self._status_cmd_attr = None
+
+        self.ssh_helper = ssh_helper
+        self.clean_status()
+
+    def _dpdk_execute(self, *args, **kwargs):
+        res = self.ssh_helper.execute(*args, **kwargs)
+        if res[0] != 0:
+            raise DpdkBindHelperException('{} command failed with rc={}'.format(
+                self._dpdk_nic_bind, res[0]))
+        return res
+
+    @property
+    def _dpdk_nic_bind(self):
+        if self._dpdk_nic_bind_attr is None:
+            self._dpdk_nic_bind_attr = self.ssh_helper.provision_tool(tool_file="dpdk-devbind.py")
+        return self._dpdk_nic_bind_attr
+
+    @property
+    def _status_cmd(self):
+        if self._status_cmd_attr is None:
+            self._status_cmd_attr = self.DPDK_STATUS_CMD.format(dpdk_nic_bind=self._dpdk_nic_bind)
+        return self._status_cmd_attr
+
+    def _addline(self, active_list, line):
+        if active_list is None:
+            return
+        res = self.NIC_ROW_RE.match(line)
+        if res is None:
+            return
+        new_data = {k: v for k, v in zip(self.NIC_ROW_FIELDS, res.groups())}
+        new_data['active'] = bool(new_data['active'])
+        self.dpdk_status[active_list].append(new_data)
+
+    @classmethod
+    def _switch_active_dict(cls, a_row, active_dict):
+        for regexp, a_dict in cls.HEADER_DICT_PAIRS:
+            if regexp.match(a_row):
+                return a_dict
+        return active_dict
+
+    def parse_dpdk_status_output(self, input):
+        active_dict = None
+        self.clean_status()
+        for a_row in input.splitlines():
+            if self.SKIP_RE.match(a_row):
+                continue
+            active_dict = self._switch_active_dict(a_row, active_dict)
+            self._addline(active_dict, a_row)
+        return self.dpdk_status
+
+    def _get_bound_pci_addresses(self, active_dict):
+        return [iface['vpci'] for iface in self.dpdk_status[active_dict]]
+
+    @property
+    def dpdk_bound_pci_addresses(self):
+        return self._get_bound_pci_addresses(NETWORK_DPDK)
+
+    @property
+    def kernel_bound_pci_addresses(self):
+        return self._get_bound_pci_addresses(NETWORK_KERNEL)
+
+    @property
+    def interface_driver_map(self):
+        return {interface['vpci']: interface['driver']
+                for interface in itertools.chain(*self.dpdk_status.values())}
+
+    def read_status(self):
+        return self.parse_dpdk_status_output(self._dpdk_execute(self._status_cmd)[1])
+
+    def bind(self, pci, driver, force=True):
+        cmd = self.DPDK_BIND_CMD.format(dpdk_nic_bind=self._dpdk_nic_bind,
+                                        driver=driver,
+                                        vpci=' '.join(list(pci)),
+                                        force='--force' if force else '')
+        self._dpdk_execute(cmd)
+        # update the inner status dict
+        self.read_status()
+
+    def save_used_drivers(self):
+        self.used_drivers = self.interface_driver_map
+
+    def rebind_drivers(self, force=True):
+        for vpci, driver in self.used_drivers.items():
+            self.bind(vpci, driver, force)
index 9d89d41..7054b92 100644 (file)
@@ -19,7 +19,7 @@ import logging
 import os
 import sys
 from collections import OrderedDict, defaultdict
-from itertools import chain
+from itertools import chain, repeat
 
 import six
 from six.moves.configparser import ConfigParser
@@ -62,6 +62,97 @@ SCRIPT_TPL = """
 """
 
 
+class PortPairs(object):
+
+    PUBLIC = "public"
+    PRIVATE = "private"
+
+    def __init__(self, interfaces):
+        super(PortPairs, self).__init__()
+        self.interfaces = interfaces
+        self._all_ports = None
+        self._priv_ports = None
+        self._pub_ports = None
+        self._networks = None
+        self._port_pair_list = None
+        self._valid_networks = None
+
+    @property
+    def networks(self):
+        if self._networks is None:
+            self._networks = {}
+            for intf in self.interfaces:
+                vintf = intf['virtual-interface']
+                try:
+                    vld_id = vintf['vld_id']
+                except KeyError:
+                    # probably unused port?
+                    LOG.warning("intf without vld_id, %s", vintf)
+                else:
+                    self._networks.setdefault(vld_id, []).append(vintf["ifname"])
+        return self._networks
+
+    @classmethod
+    def get_public_id(cls, vld_id):
+        # partition returns a tuple
+        parts = list(vld_id.partition(cls.PRIVATE))
+        if parts[0]:
+            # 'private' was not in or not leftmost in the string
+            return
+        parts[1] = cls.PUBLIC
+        public_id = ''.join(parts)
+        return public_id
+
+    @property
+    # this only works for vnfs that have both private and public visible
+    def valid_networks(self):
+        if self._valid_networks is None:
+            self._valid_networks = []
+            for vld_id in self.networks:
+                public_id = self.get_public_id(vld_id)
+                if public_id in self.networks:
+                    self._valid_networks.append((vld_id, public_id))
+        return self._valid_networks
+
+    @property
+    def all_ports(self):
+        if self._all_ports is None:
+            self._all_ports = sorted(set(self.priv_ports + self.pub_ports))
+        return self._all_ports
+
+    @property
+    def priv_ports(self):
+        if self._priv_ports is None:
+            intfs = chain.from_iterable(
+                intfs for vld_id, intfs in self.networks.items() if
+                vld_id.startswith(self.PRIVATE))
+            self._priv_ports = sorted(set(intfs))
+        return self._priv_ports
+
+    @property
+    def pub_ports(self):
+        if self._pub_ports is None:
+            intfs = chain.from_iterable(
+                intfs for vld_id, intfs in self.networks.items() if vld_id.startswith(self.PUBLIC))
+            self._pub_ports = sorted(set(intfs))
+        return self._pub_ports
+
+    @property
+    def port_pair_list(self):
+        if self._port_pair_list is None:
+            self._port_pair_list = []
+
+            for priv, pub in self.valid_networks:
+                for private_intf in self.networks[priv]:
+                    # only VNFs have private, public peers
+                    peer_intfs = self.networks.get(pub, [])
+                    if peer_intfs:
+                        for public_intf in peer_intfs:
+                            port_pair = private_intf, public_intf
+                            self._port_pair_list.append(port_pair)
+        return self._port_pair_list
+
+
 class MultiPortConfig(object):
 
     HW_LB = "HW"
@@ -108,7 +199,7 @@ class MultiPortConfig(object):
         ip_addr = cls.make_ip_addr(ip_addr, prefixlen)
         return ip_addr.ip.exploded, ip_addr.network.prefixlen
 
-    def __init__(self, topology_file, config_tpl, tmp_file, interfaces=None,
+    def __init__(self, topology_file, config_tpl, tmp_file, vnfd_helper,
                  vnf_type='CGNAT', lb_count=2, worker_threads=3,
                  worker_config='1C/1T', lb_config='SW', socket=0):
 
@@ -118,8 +209,7 @@ class MultiPortConfig(object):
         self.worker_threads = self.get_worker_threads(worker_threads)
         self.vnf_type = vnf_type
         self.pipe_line = 0
-        self.interfaces = interfaces if interfaces else {}
-        self.networks = {}
+        self.vnfd_helper = vnfd_helper
         self.write_parser = ConfigParser()
         self.read_parser = ConfigParser()
         self.read_parser.read(config_tpl)
@@ -138,6 +228,8 @@ class MultiPortConfig(object):
         self.start_core = ""
         self.pipeline_counter = ""
         self.txrx_pipeline = ""
+        self._port_pairs = None
+        self.all_ports = []
         self.port_pair_list = []
         self.lb_to_port_pair_mapping = {}
         self.init_eal()
@@ -145,12 +237,11 @@ class MultiPortConfig(object):
         self.lb_index = None
         self.mul = 0
         self.port_pairs = []
-        self.port_pair_list = []
         self.ports_len = 0
         self.prv_que_handler = None
         self.vnfd = None
         self.rules = None
-        self.pktq_out = ''
+        self.pktq_out = []
 
     @staticmethod
     def gen_core(core):
@@ -160,18 +251,19 @@ class MultiPortConfig(object):
         return str(core)
 
     def make_port_pairs_iter(self, operand, iterable):
-        return (operand(x[-1], y) for y in iterable for x in chain(*self.port_pairs))
+        return (operand(self.vnfd_helper.port_num(x), y) for y in iterable for x in
+                chain.from_iterable(self.port_pairs))
 
     def make_range_port_pairs_iter(self, operand, start, end):
         return self.make_port_pairs_iter(operand, range(start, end))
 
     def init_eal(self):
-        vpci = [v['virtual-interface']["vpci"] for v in self.interfaces]
+        lines = ['[EAL]\n']
+        vpci = (v['virtual-interface']["vpci"] for v in self.vnfd_helper.interfaces)
+        lines.extend('w = {0}\n'.format(item) for item in vpci)
+        lines.append('\n')
         with open(self.tmp_file, 'w') as fh:
-            fh.write('[EAL]\n')
-            for item in vpci:
-                fh.write('w = {0}\n'.format(item))
-            fh.write('\n')
+            fh.writelines(lines)
 
     def update_timer(self):
         timer_tpl = self.get_config_tpl_data('TIMER')
@@ -226,40 +318,6 @@ class MultiPortConfig(object):
         except ValueError:
             self.start_core = int(self.start_core[:-1]) + 1
 
-    @staticmethod
-    def get_port_pairs(interfaces):
-        port_pair_list = []
-        networks = {}
-        for private_intf in interfaces:
-            vintf = private_intf['virtual-interface']
-            try:
-                vld_id = vintf['vld_id']
-            except KeyError:
-                pass
-            else:
-                networks.setdefault(vld_id, []).append(vintf)
-
-        for name, net in networks.items():
-            # partition returns a tuple
-            parts = list(name.partition('private'))
-            if parts[0]:
-                # 'private' was not in or not leftmost in the string
-                continue
-            parts[1] = 'public'
-            public_id = ''.join(parts)
-            for private_intf in net:
-                try:
-                    public_peer_intfs = networks[public_id]
-                except KeyError:
-                    LOG.warning("private network without peer %s, %s not found", name, public_id)
-                    continue
-
-                for public_intf in public_peer_intfs:
-                    port_pair = private_intf["ifname"], public_intf["ifname"]
-                    port_pair_list.append(port_pair)
-
-        return port_pair_list, networks
-
     def get_lb_count(self):
         self.lb_count = int(min(len(self.port_pair_list), self.lb_count))
 
@@ -267,50 +325,51 @@ class MultiPortConfig(object):
         self.lb_to_port_pair_mapping = defaultdict(int)
         port_pair_count = len(self.port_pair_list)
         lb_pair_count = int(port_pair_count / self.lb_count)
-        for i in range(self.lb_count):
-            self.lb_to_port_pair_mapping[i + 1] = lb_pair_count
-        for i in range(port_pair_count % self.lb_count):
-            self.lb_to_port_pair_mapping[i + 1] += 1
+        extra = port_pair_count % self.lb_count
+        extra_iter = repeat(lb_pair_count + 1, extra)
+        norm_iter = repeat(lb_pair_count, port_pair_count - extra)
+        new_values = {i: v for i, v in enumerate(chain(extra_iter, norm_iter), 1)}
+        self.lb_to_port_pair_mapping.update(new_values)
 
     def set_priv_to_pub_mapping(self):
-        return "".join(str(y) for y in [(int(x[0][-1]), int(x[1][-1])) for x in
-                                        self.port_pair_list])
+        port_nums = [tuple(self.vnfd_helper.port_nums(x)) for x in self.port_pair_list]
+        return "".join(str(y).replace(" ", "") for y in
+                       port_nums)
 
     def set_priv_que_handler(self):
         # iterated twice, can't be generator
-        priv_to_pub_map = [(int(x[0][-1]), int(x[1][-1])) for x in self.port_pairs]
+        priv_to_pub_map = [tuple(self.vnfd_helper.port_nums(x)) for x in self.port_pairs]
         # must be list to use .index()
         port_list = list(chain.from_iterable(priv_to_pub_map))
         priv_ports = (x[0] for x in priv_to_pub_map)
         self.prv_que_handler = '({})'.format(
-            ",".join((str(port_list.index(x)) for x in priv_ports)))
+            "".join(("{},".format(port_list.index(x)) for x in priv_ports)))
 
     def generate_arp_route_tbl(self):
-        arp_config = []
         arp_route_tbl_tmpl = "({port0_dst_ip_hex},{port0_netmask_hex},{port_num}," \
                              "{next_hop_ip_hex})"
-        for port_pair in self.port_pair_list:
-            for port in port_pair:
-                port_num = int(port[-1])
-                interface = self.interfaces[port_num]
-                # We must use the dst because we are on the VNF and we need to
-                # reach the TG.
-                dst_port0_ip = \
-                    ipaddress.ip_interface(six.text_type(
-                        "%s/%s" % (interface["virtual-interface"]["dst_ip"],
-                                   interface["virtual-interface"]["netmask"])))
-                arp_vars = {
-                    "port0_dst_ip_hex": ip_to_hex(dst_port0_ip.network.network_address.exploded),
-                    "port0_netmask_hex": ip_to_hex(dst_port0_ip.network.netmask.exploded),
-                    # this is the port num that contains port0 subnet and next_hop_ip_hex
-                    "port_num": port_num,
-                    # next hop is dst in this case
-                    # must be within subnet
-                    "next_hop_ip_hex": ip_to_hex(dst_port0_ip.ip.exploded),
-                }
-                arp_config.append(arp_route_tbl_tmpl.format(**arp_vars))
-
-        return ' '.join(arp_config)
+
+        def build_arp_config(port):
+            dpdk_port_num = self.vnfd_helper.port_num(port)
+            interface = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
+            # We must use the dst because we are on the VNF and we need to
+            # reach the TG.
+            dst_port0_ip = ipaddress.ip_interface(six.text_type(
+                "%s/%s" % (interface["dst_ip"], interface["netmask"])))
+
+            arp_vars = {
+                "port0_dst_ip_hex": ip_to_hex(dst_port0_ip.network.network_address.exploded),
+                "port0_netmask_hex": ip_to_hex(dst_port0_ip.network.netmask.exploded),
+                # this is the port num that contains port0 subnet and next_hop_ip_hex
+                # this is LINKID which should be based on DPDK port number
+                "port_num": dpdk_port_num,
+                # next hop is dst in this case
+                # must be within subnet
+                "next_hop_ip_hex": ip_to_hex(dst_port0_ip.ip.exploded),
+            }
+            return arp_route_tbl_tmpl.format(**arp_vars)
+
+        return ' '.join(build_arp_config(port) for port in self.all_ports)
 
     def generate_arpicmp_data(self):
         swq_in_str = self.make_range_str('SWQ{}', self.swq, offset=self.lb_count)
@@ -318,9 +377,11 @@ class MultiPortConfig(object):
         swq_out_str = self.make_range_str('SWQ{}', self.swq, offset=self.lb_count)
         self.swq += self.lb_count
         # ports_mac_list is disabled for some reason
-        # mac_iter = (self.interfaces[int(x[-1])]['virtual-interface']['local_mac']
-        #             for port_pair in self.port_pair_list for x in port_pair)
-        pktq_in_iter = ('RXQ{}'.format(float(x[0][-1])) for x in self.port_pair_list)
+
+        # mac_iter = (self.vnfd_helper.find_interface(name=port)['virtual-interface']['local_mac']
+        #             for port in self.all_ports)
+        pktq_in_iter = ('RXQ{}.0'.format(self.vnfd_helper.port_num(x[0])) for x in
+                        self.port_pair_list)
 
         arpicmp_data = {
             'core': self.gen_core(self.start_core),
@@ -505,7 +566,10 @@ class MultiPortConfig(object):
             self.vnf_tpl = self.get_config_tpl_data(self.vnf_type)
 
     def generate_config(self):
-        self.port_pair_list, self.networks = self.get_port_pairs(self.interfaces)
+        self._port_pairs = PortPairs(self.vnfd_helper.interfaces)
+        self.port_pair_list = self._port_pairs.port_pair_list
+        self.all_ports = self._port_pairs.all_ports
+
         self.get_lb_count()
         self.generate_lb_to_port_pair_mapping()
         self.generate_config_data()
@@ -514,18 +578,16 @@ class MultiPortConfig(object):
             self.write_parser.write(tfh)
 
     def generate_link_config(self):
+        def build_args(port):
+            # lookup interface by name
+            virtual_interface = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
+            local_ip = virtual_interface["local_ip"]
+            netmask = virtual_interface["netmask"]
+            port_num = self.vnfd_helper.port_num(port)
+            port_ip, prefix_len = self.validate_ip_and_prefixlen(local_ip, netmask)
+            return LINK_CONFIG_TEMPLATE.format(port_num, port_ip, prefix_len)
 
-        link_configs = []
-        for port_pair in self.port_pair_list:
-            for port in port_pair:
-                port = port[-1]
-                virtual_interface = self.interfaces[int(port)]["virtual-interface"]
-                local_ip = virtual_interface["local_ip"]
-                netmask = virtual_interface["netmask"]
-                port_ip, prefix_len = self.validate_ip_and_prefixlen(local_ip, netmask)
-                link_configs.append(LINK_CONFIG_TEMPLATE.format(port, port_ip, prefix_len))
-
-        return ''.join(link_configs)
+        return ''.join(build_args(port) for port in self.all_ports)
 
     def get_route_data(self, src_key, data_key, port):
         route_list = self.vnfd['vdu'][0].get(src_key, [])
@@ -548,37 +610,38 @@ class MultiPortConfig(object):
 
     def generate_arp_config(self):
         arp_config = []
-        for port_pair in self.port_pair_list:
-            for port in port_pair:
-                # ignore gateway, always use TG IP
-                # gateway = self.get_ports_gateway(port)
-                dst_mac = self.interfaces[int(port[-1])]["virtual-interface"]["dst_mac"]
-                dst_ip = self.interfaces[int(port[-1])]["virtual-interface"]["dst_ip"]
-                # arp_config.append((port[-1], gateway, dst_mac, self.txrx_pipeline))
-                # so dst_mac is the TG dest mac, so we need TG dest IP.
-                arp_config.append((port[-1], dst_ip, dst_mac, self.txrx_pipeline))
+        for port in self.all_ports:
+            # ignore gateway, always use TG IP
+            # gateway = self.get_ports_gateway(port)
+            vintf = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
+            dst_mac = vintf["dst_mac"]
+            dst_ip = vintf["dst_ip"]
+            # arp_config.append(
+            #     (self.vnfd_helper.port_num(port), gateway, dst_mac, self.txrx_pipeline))
+            # so dst_mac is the TG dest mac, so we need TG dest IP.
+            # should be dpdk_port_num
+            arp_config.append(
+                (self.vnfd_helper.port_num(port), dst_ip, dst_mac, self.txrx_pipeline))
 
         return '\n'.join(('p {3} arpadd {0} {1} {2}'.format(*values) for values in arp_config))
 
     def generate_arp_config6(self):
         arp_config6 = []
-        for port_pair in self.port_pair_list:
-            for port in port_pair:
-                # ignore gateway, always use TG IP
-                # gateway6 = self.get_ports_gateway6(port)
-                dst_mac6 = self.interfaces[int(port[-1])]["virtual-interface"]["dst_mac"]
-                dst_ip6 = self.interfaces[int(port[-1])]["virtual-interface"]["dst_ip"]
-                # arp_config6.append((port[-1], gateway6, dst_mac6, self.txrx_pipeline))
-                arp_config6.append((port[-1], dst_ip6, dst_mac6, self.txrx_pipeline))
+        for port in self.all_ports:
+            # ignore gateway, always use TG IP
+            # gateway6 = self.get_ports_gateway6(port)
+            vintf = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
+            dst_mac6 = vintf["dst_mac"]
+            dst_ip6 = vintf["dst_ip"]
+            # arp_config6.append(
+            #     (self.vnfd_helper.port_num(port), gateway6, dst_mac6, self.txrx_pipeline))
+            arp_config6.append(
+                (self.vnfd_helper.port_num(port), dst_ip6, dst_mac6, self.txrx_pipeline))
 
         return '\n'.join(('p {3} arpadd {0} {1} {2}'.format(*values) for values in arp_config6))
 
     def generate_action_config(self):
-        port_list = []
-        for port_pair in self.port_pair_list:
-            for port in port_pair:
-                port_list.append(port[-1])
-
+        port_list = (self.vnfd_helper.port_num(p) for p in self.all_ports)
         if self.vnf_type == "VFW":
             template = FW_ACTION_TEMPLATE
         else:
@@ -589,8 +652,9 @@ class MultiPortConfig(object):
     def get_ip_from_port(self, port):
         # we can't use gateway because in OpenStack gateways interfer with floating ip routing
         # return self.make_ip_addr(self.get_ports_gateway(port), self.get_netmask_gateway(port))
-        ip = self.interfaces[port]["virtual-interface"]["local_ip"]
-        netmask = self.interfaces[port]["virtual-interface"]["netmask"]
+        vintf = self.vnfd_helper.find_interface(name=port)["virtual-interface"]
+        ip = vintf["local_ip"]
+        netmask = vintf["netmask"]
         return self.make_ip_addr(ip, netmask)
 
     def get_network_and_prefixlen_from_ip_of_port(self, port):
@@ -607,12 +671,12 @@ class MultiPortConfig(object):
         new_rules = []
         new_ipv6_rules = []
         pattern = 'p {0} add {1} {2} {3} {4} {5} 0 65535 0 65535 0 0 {6}'
-        for port_pair in self.port_pair_list:
-            src_port = int(port_pair[0][-1])
-            dst_port = int(port_pair[1][-1])
+        for src_intf, dst_intf in self.port_pair_list:
+            src_port = self.vnfd_helper.port_num(src_intf)
+            dst_port = self.vnfd_helper.port_num(dst_intf)
 
-            src_net, src_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(src_port)
-            dst_net, dst_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(dst_port)
+            src_net, src_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(src_intf)
+            dst_net, dst_prefix_len = self.get_network_and_prefixlen_from_ip_of_port(dst_intf)
             # ignore entires with empty values
             if all((src_net, src_prefix_len, dst_net, dst_prefix_len)):
                 new_rules.append((cmd, self.txrx_pipeline, src_net, src_prefix_len,
@@ -637,7 +701,8 @@ class MultiPortConfig(object):
         return ''.join([rules_config, new_rules_config, acl_apply])
 
     def generate_script_data(self):
-        self.port_pair_list, self.networks = self.get_port_pairs(self.interfaces)
+        self._port_pairs = PortPairs(self.vnfd_helper.interfaces)
+        self.port_pair_list = self._port_pairs.port_pair_list
         self.get_lb_count()
         script_data = {
             'link_config': self.generate_link_config(),
@@ -675,5 +740,5 @@ set_hash_input_set {0} ipv6-udp src-ipv6 udp-src-port add
 set_hash_input_set {1} ipv6-udp dst-ipv6 udp-dst-port add
 """
             for port_pair in self.port_pair_list:
-                script += hwlb_tpl.format(port_pair[0][-1], port_pair[1][-1])
+                script += hwlb_tpl.format(*(self.vnfd_helper.port_nums(port_pair)))
         return script
index 38831ee..1ec00e5 100644 (file)
@@ -113,10 +113,10 @@ class IxNextgen(object):
     }
 
     MODE_SEEDS_MAP = {
-        0: ('private_1', ['256', '2048']),
+        0: ('private_0', ['256', '2048']),
     }
 
-    MODE_SEEDS_DEFAULT = 'public_1', ['2048', '256']
+    MODE_SEEDS_DEFAULT = 'public_0', ['2048', '256']
 
     @staticmethod
     def find_view_obj(view_name, views):
index 055fdba..fa32a4d 100644 (file)
@@ -21,11 +21,11 @@ import os
 import os.path
 import re
 import multiprocessing
-from collections import Sequence
 
 from oslo_config import cfg
 
 from yardstick import ssh
+from yardstick.common.utils import validate_non_string_sequence
 from yardstick.network_services.nfvi.collectd import AmqpConsumer
 from yardstick.network_services.utils import get_nsb_option
 
@@ -45,16 +45,14 @@ class ResourceProfile(object):
 
     def __init__(self, mgmt, interfaces=None, cores=None):
         self.enable = True
-        self.connection = None
-        self.cores = cores if isinstance(cores, Sequence) else []
+        self.cores = validate_non_string_sequence(cores, default=[])
         self._queue = multiprocessing.Queue()
         self.amqp_client = None
-        self.interfaces = interfaces if isinstance(interfaces, Sequence) else []
+        self.interfaces = validate_non_string_sequence(interfaces, default=[])
 
         # why the host or ip?
         self.vnfip = mgmt.get("host", mgmt["ip"])
         self.connection = ssh.SSH.from_node(mgmt, overrides={"ip": self.vnfip})
-
         self.connection.wait()
 
     def check_if_sa_running(self, process):
@@ -111,7 +109,7 @@ class ResourceProfile(object):
 
     @classmethod
     def parse_intel_pmu_stats(cls, key, value):
-        return {''.join(key): value.split(":")[1]}
+        return {''.join(str(v) for v in key): value.split(":")[1]}
 
     def parse_collectd_result(self, metrics, core_list):
         """ convert collectd data into json"""
@@ -234,7 +232,7 @@ class ResourceProfile(object):
         connection.execute("sudo rabbitmqctl delete_user guest")
         connection.execute("sudo rabbitmqctl add_user admin admin")
         connection.execute("sudo rabbitmqctl authenticate_user admin admin")
-        connection.execute("sudo rabbitmqctl set_permissions -p / admin \".*\" \".*\" \".*\"")
+        connection.execute("sudo rabbitmqctl set_permissions -p / admin '.*' '.*' '.*'")
 
         LOG.debug("Start collectd service.....")
         connection.execute("sudo %s" % collectd_path)
index 9064985..611792b 100644 (file)
@@ -44,7 +44,7 @@ class TrafficProfile(object):
         # IMIX = {"10K": 0.1, "100M": 0.5}
         self.params = tp_config
 
-    def execute(self, traffic_generator):
+    def execute_traffic(self, traffic_generator):
         """ This methods defines the behavior of the traffic generator.
         It will be called in a loop until the traffic generator exits.
 
index ddb41f3..049a81a 100644 (file)
@@ -23,11 +23,17 @@ LOG = logging.getLogger(__name__)
 
 
 class IXIARFC2544Profile(TrexProfile):
-    def _get_ixia_traffic_profile(self, profile_data, mac={},
-                                  xfile=None, static_traffic={}):
+
+    def _get_ixia_traffic_profile(self, profile_data, mac=None, xfile=None, static_traffic=None):
+        if mac is None:
+            mac = {}
+
+        if static_traffic is None:
+            static_traffic = {}
+
         result = {}
         if xfile:
-            with open(xfile, 'r') as stream:
+            with open(xfile) as stream:
                 try:
                     static_traffic = json.load(stream)
                 except Exception as exc:
@@ -73,7 +79,7 @@ class IXIARFC2544Profile(TrexProfile):
     def _ixia_traffic_generate(self, traffic_generator, traffic, ixia_obj):
         for key, value in traffic.items():
             if "public" in key or "private" in key:
-                traffic[key]["iload"] = str(self.rate)
+                value["iload"] = str(self.rate)
         ixia_obj.ix_update_frame(traffic)
         ixia_obj.ix_update_ether(traffic)
         ixia_obj.add_ip_header(traffic, 4)
@@ -81,19 +87,27 @@ class IXIARFC2544Profile(TrexProfile):
         self.tmp_drop = 0
         self.tmp_throughput = 0
 
-    def update_traffic_profile(self):
-        self.profile = 'private_1'
-        for key, value in self.params.items():
-            if "private" in key or "public" in key:
-                self.profile_data = self.params[key]
+    def update_traffic_profile(self, traffic_generator):
+        def port_generator():
+            for vld_id, intfs in sorted(traffic_generator.networks.items()):
+                if not vld_id.startswith(("private", "public")):
+                    continue
+                profile_data = self.params.get(vld_id)
+                if not profile_data:
+                    continue
+                self.profile_data = profile_data
                 self.get_streams(self.profile_data)
-                self.full_profile.update({key: self.profile_data})
+                self.full_profile.update({vld_id: self.profile_data})
+                for intf in intfs:
+                    yield traffic_generator.vnfd_helper.port_num(intf)
+
+        self.ports = [port for port in port_generator()]
 
-    def execute(self, traffic_generator, ixia_obj, mac={}, xfile=None):
+    def execute_traffic(self, traffic_generator, ixia_obj, mac={}, xfile=None):
         if self.first_run:
             self.full_profile = {}
             self.pg_id = 0
-            self.update_traffic_profile()
+            self.update_traffic_profile(traffic_generator)
             traffic = \
                 self._get_ixia_traffic_profile(self.full_profile, mac, xfile)
             self.max_rate = self.rate
@@ -108,7 +122,7 @@ class IXIARFC2544Profile(TrexProfile):
 
     def start_ixia_latency(self, traffic_generator, ixia_obj,
                            mac={}, xfile=None):
-        self.update_traffic_profile()
+        self.update_traffic_profile(traffic_generator)
         traffic = \
             self._get_ixia_traffic_profile(self.full_profile, mac, xfile)
         self._ixia_traffic_generate(traffic_generator, traffic,
index a3b8036..6a0ecaf 100644 (file)
@@ -43,7 +43,7 @@ class RFC2544Profile(TrexProfile):
     def register_generator(self, generator):
         self.generator = generator
 
-    def execute(self, traffic_generator=None):
+    def execute_traffic(self, traffic_generator=None):
         """ Generate the stream and run traffic on the given ports """
         if traffic_generator is not None and self.generator is None:
             self.generator = traffic_generator
@@ -52,21 +52,18 @@ class RFC2544Profile(TrexProfile):
             return
 
         self.ports = []
-        priv_ports = self.generator.priv_ports
-        pub_ports = self.generator.pub_ports
-        # start from 1 for private_1, public_1, etc.
-        for index, (priv_port, pub_port) in enumerate(zip(priv_ports, pub_ports), 1):
-            profile_data = self.params.get('private_{}'.format(index), '')
-            self.ports.append(priv_port)
-            # pass profile_data directly, don't use self.profile_data
-            self.generator.client.add_streams(self.get_streams(profile_data), ports=priv_port)
-            profile_data = self.params.get('public_{}'.format(index), '')
+        for vld_id, intfs in sorted(self.generator.networks.items()):
+            profile_data = self.params.get(vld_id)
+            # no profile for this port
+            if not profile_data:
+                continue
             # correlated traffic doesn't use public traffic?
-            if not profile_data or self.generator.rfc2544_helper.correlated_traffic:
+            if vld_id.startswith("public") and self.generator.rfc2544_helper.correlated_traffic:
                 continue
-            # just get the pub_port
-            self.ports.append(pub_port)
-            self.generator.client.add_streams(self.get_streams(profile_data), ports=pub_port)
+            for intf in intfs:
+                port = self.generator.vnfd_helper.port_num(intf)
+                self.ports.append(port)
+                self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
 
         self.max_rate = self.rate
         self.min_rate = 0
@@ -86,7 +83,7 @@ class RFC2544Profile(TrexProfile):
         if generator is None:
             generator = self.generator
         run_duration = self.generator.RUN_DURATION
-        samples = self.generator.generate_samples()
+        samples = self.generator.generate_samples(self.ports)
 
         in_packets = sum([value['in_packets'] for value in samples.values()])
         out_packets = sum([value['out_packets'] for value in samples.values()])
@@ -135,8 +132,8 @@ class RFC2544Profile(TrexProfile):
             # TODO(esm): why don't we discard results that are out of tolerance?
             self.min_rate = self.rate
 
-        generator.clear_client_stats()
-        generator.start_client(mult=self.get_multiplier(),
+        generator.clear_client_stats(self.ports)
+        generator.start_client(self.ports, mult=self.get_multiplier(),
                                duration=run_duration, force=True)
 
         # if correlated traffic update the Throughput
index 4c6595d..894126c 100644 (file)
@@ -188,9 +188,9 @@ class TrexProfile(TrafficProfile):
                   ),
         }
 
-    def execute(self, traffic_generator):
+    def execute_traffic(self, traffic_generator):
         """ Generate the stream and run traffic on the given ports """
-        pass
+        raise NotImplementedError()
 
     def _call_on_range(self, range, single_action, range_action, count=1, to_int=False):
         def convert_to_int(val):
index 5f3c8a0..3ba38de 100644 (file)
@@ -24,7 +24,7 @@ LOG = logging.getLogger(__name__)
 
 # ACL should work the same on all systems, we can provide the binary
 ACL_PIPELINE_COMMAND = \
-    'sudo {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}'
+    'sudo {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}'
 
 ACL_COLLECT_KPI = r"""\
 ACL TOTAL:[^p]+pkts_processed"?:\s(\d+),[^p]+pkts_drop"?:\s(\d+),[^p]+pkts_received"?:\s(\d+),"""
index 955f9f0..e32e5fb 100644 (file)
@@ -16,6 +16,8 @@
 from __future__ import absolute_import
 import logging
 
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
+
 LOG = logging.getLogger(__name__)
 
 
@@ -59,6 +61,10 @@ class QueueFileWrapper(object):
 
 class VnfdHelper(dict):
 
+    def __init__(self, *args, **kwargs):
+        super(VnfdHelper, self).__init__(*args, **kwargs)
+        self.port_pairs = PortPairs(self['vdu'][0]['external-interface'])
+
     @property
     def mgmt_interface(self):
         return self["mgmt-interface"]
@@ -92,6 +98,28 @@ class VnfdHelper(dict):
             if interface[key] == value:
                 return interface
 
+    # hide dpdk_port_num key so we can abstract
+    def find_interface_by_port(self, port):
+        for interface in self.interfaces:
+            virtual_intf = interface["virtual-interface"]
+            # we have to convert to int to compare
+            if int(virtual_intf['dpdk_port_num']) == port:
+                return interface
+
+    def port_num(self, name):
+        # we need interface name -> DPDK port num (PMD ID) -> LINK ID
+        # LINK ID -> PMD ID is governed by the port mask
+        """
+
+        :rtype: int
+        :type name: str
+        """
+        intf = self.find_interface(name=name)
+        return int(intf["virtual-interface"]["dpdk_port_num"])
+
+    def port_nums(self, intfs):
+        return [self.port_num(i) for i in intfs]
+
 
 class VNFObject(object):
 
index f9980b1..45ef757 100644 (file)
 # limitations under the License.
 
 from __future__ import absolute_import
-import time
 import logging
 
-from six.moves import zip
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
 
 LOG = logging.getLogger(__name__)
 
 # CGNAPT should work the same on all systems, we can provide the binary
-CGNAPT_PIPELINE_COMMAND = 'sudo {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}'
+CGNAPT_PIPELINE_COMMAND = 'sudo {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}'
 WAIT_FOR_STATIC_NAPT = 4
 
 CGNAPT_COLLECT_KPI = """\
@@ -55,7 +53,7 @@ class CgnaptApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
             yield '.'.join(ip_parts)
 
     @staticmethod
-    def _update_cgnat_script_file(ip_pipeline_cfg, mcpi, vnf_str):
+    def _update_cgnat_script_file(ip_pipeline_cfg, mcpi):
         pipeline_config_str = str(ip_pipeline_cfg)
         input_cmds = '\n'.join(mcpi)
         icmp_flag = 'link 0 down' in input_cmds
@@ -67,16 +65,13 @@ class CgnaptApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
         raise NotImplementedError
 
     def _get_cgnapt_config(self, interfaces=None):
+        # TODO: static CGNAPT is broken, don't use it
         if interfaces is None:
             interfaces = self.vnfd_helper.interfaces
 
-        gateway_ips = []
-
         # fixme: Get private port and gateway from port list
-        priv_ports = interfaces[::2]
-        for interface in priv_ports:
-            gateway_ips.append(self._get_ports_gateway(interface["name"]))
-        return gateway_ips
+        priv_ports = self.vnfd_helper.port_pairs.priv_ports
+        return [self._get_ports_gateway(intf["name"]) for intf in priv_ports]
 
 
 class CgnaptApproxVnf(SampleVNF):
@@ -103,21 +98,23 @@ class CgnaptApproxVnf(SampleVNF):
         if self.scenario_helper.options.get('napt', 'static') != 'static':
             return
 
-        ip_iter = self.setup_helper._generate_ip_from_pool("152.16.40.10")
-        gw_ips = self.setup_helper._get_cgnapt_config()
-        if self.scenario_helper.vnf_cfg.get("lb_config", "SW") == 'HW':
-            pipeline = self.setup_helper.HW_DEFAULT_CORE
-            offset = 3
-        else:
-            pipeline = self.setup_helper.SW_DEFAULT_CORE - 1
-            offset = 0
-
-        worker_threads = int(self.scenario_helper.vnf_cfg["worker_threads"])
-        cmd_template = "p {0} entry addm {1} 1 {2} 1 0 32 65535 65535 65535"
-        for gw, ip in zip(gw_ips, ip_iter):
-            cmd = cmd_template.format(pipeline, gw, ip)
-            pipeline += worker_threads
-            pipeline += offset
-            self.vnf_execute(cmd)
-
-        time.sleep(WAIT_FOR_STATIC_NAPT)
+        # ip_iter = self.setup_helper._generate_ip_from_pool("152.16.40.10")
+        # gw_ips = self.setup_helper._get_cgnapt_config()
+        # if self.scenario_helper.vnf_cfg.get("lb_config", "SW") == 'HW':
+        #     pipeline = self.setup_helper.HW_DEFAULT_CORE
+        #     offset = 3
+        # else:
+        #     pipeline = self.setup_helper.SW_DEFAULT_CORE - 1
+        #     offset = 0
+        #
+        # worker_threads = int(self.scenario_helper.vnf_cfg["worker_threads"])
+        # # p <pipeline id> entry addm <prv_ipv4/6> prvport> <pub_ip> <pub_port> <phy_port> <ttl>
+        # # <no_of_entries> <end_prv_port> <end_pub_port>
+        # cmd_template = "p {0} entry addm {1} 1 {2} 1 0 32 65535 65535 65535"
+        # for gw, ip in zip(gw_ips, ip_iter):
+        #     cmd = cmd_template.format(pipeline, gw, ip)
+        #     pipeline += worker_threads
+        #     pipeline += offset
+        #     self.vnf_execute(cmd)
+        #
+        # time.sleep(WAIT_FOR_STATIC_NAPT)
index d6ec271..00ab6c2 100644 (file)
@@ -639,9 +639,10 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
         prox_config.parse()
 
         # Ensure MAC is set "hardware"
-        ext_intf = self.vnfd_helper.interfaces
-        # we are using enumeration to map logical port numbers to interfaces
-        for port_num, intf in enumerate(ext_intf):
+        all_ports = self.vnfd_helper.port_pairs.all_ports
+        # use dpdk port number
+        for port_name in all_ports:
+            port_num = self.vnfd_helper.port_num(port_name)
             port_section_name = "port {}".format(port_num)
             for section_name, section in sections:
                 if port_section_name != section_name:
@@ -659,13 +660,15 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
                 if item_val.startswith("@@dst_mac"):
                     tx_port_iter = re.finditer(r'\d+', item_val)
                     tx_port_no = int(next(tx_port_iter).group(0))
-                    mac = ext_intf[tx_port_no]["virtual-interface"]["dst_mac"]
+                    intf = self.vnfd_helper.find_interface_by_port(tx_port_no)
+                    mac = intf["virtual-interface"]["dst_mac"]
                     section_data[1] = mac.replace(":", " ", 6)
 
                 if item_key == "dst mac" and item_val.startswith("@@"):
                     tx_port_iter = re.finditer(r'\d+', item_val)
                     tx_port_no = int(next(tx_port_iter).group(0))
-                    mac = ext_intf[tx_port_no]["virtual-interface"]["dst_mac"]
+                    intf = self.vnfd_helper.find_interface_by_port(tx_port_no)
+                    mac = intf["virtual-interface"]["dst_mac"]
                     section_data[1] = mac
 
         # if addition file specified in prox config
@@ -714,13 +717,15 @@ class ProxDpdkVnfSetupEnvHelper(DpdkVnfSetupEnvHelper):
 
     def generate_prox_lua_file(self):
         p = OrderedDict()
-        ext_intf = self.vnfd_helper.interfaces
+        all_ports = self.vnfd_helper.port_pairs.all_ports
         lua_param = self.LUA_PARAMETER_NAME
-        for intf in ext_intf:
+        for port_name in all_ports:
             peer = self.LUA_PARAMETER_PEER[lua_param]
-            port_num = intf["virtual-interface"]["dpdk_port_num"]
-            local_ip = intf["local_ip"]
-            dst_ip = intf["dst_ip"]
+            port_num = self.vnfd_helper.port_num(port_name)
+            intf = self.vnfd_helper.find_interface(name=port_name)
+            vintf = intf['virtual-interface']
+            local_ip = vintf["local_ip"]
+            dst_ip = vintf["dst_ip"]
             local_ip_hex = ip_to_hex(local_ip, separator=' ')
             dst_ip_hex = ip_to_hex(dst_ip, separator=' ')
             p.update([
@@ -880,7 +885,7 @@ class ProxResourceHelper(ClientResourceHelper):
             self._run_traffic_once(traffic_profile)
 
     def _run_traffic_once(self, traffic_profile):
-        traffic_profile.execute(self)
+        traffic_profile.execute_traffic(self)
         if traffic_profile.done:
             self._queue.put({'done': True})
             LOG.debug("tg_prox done")
@@ -922,12 +927,11 @@ class ProxResourceHelper(ClientResourceHelper):
             self.sut.stop_all()
 
     def run_test(self, pkt_size, duration, value, tolerated_loss=0.0):
-        # type: (object, object, object, object) -> object
         # do this assert in init?  unless we expect interface count to
         # change from one run to another run...
-        interfaces = self.vnfd_helper.interfaces
-        interface_count = len(interfaces)
-        assert interface_count in {1, 2, 4}, \
+        ports = self.vnfd_helper.port_pairs.all_ports
+        port_count = len(ports)
+        assert port_count in {1, 2, 4}, \
             "Invalid number of ports: 1, 2 or 4 ports only supported at this time"
 
         with self.traffic_context(pkt_size, value):
@@ -942,15 +946,18 @@ class ProxResourceHelper(ClientResourceHelper):
             latency = self.get_latency()
 
         deltas = data['delta']
-        rx_total, tx_total = self.sut.port_stats(range(interface_count))[6:8]
-        pps = value / 100.0 * self.line_rate_to_pps(pkt_size, interface_count)
+        rx_total, tx_total = self.sut.port_stats(range(port_count))[6:8]
+        pps = value / 100.0 * self.line_rate_to_pps(pkt_size, port_count)
 
         samples = {}
         # we are currently using enumeration to map logical port num to interface
-        for index, iface in enumerate(interfaces):
-            port_rx_total, port_tx_total = self.sut.port_stats([index])[6:8]
-            samples[iface["name"]] = {"in_packets": port_rx_total,
-                                      "out_packets": port_tx_total}
+        for port_name in ports:
+            port = self.vnfd_helper.port_num(port_name)
+            port_rx_total, port_tx_total = self.sut.port_stats([port])[6:8]
+            samples[port_name] = {
+                "in_packets": port_rx_total,
+                "out_packets": port_tx_total,
+            }
 
         result = ProxTestDataTuple(tolerated_loss, tsc_hz, deltas.rx, deltas.tx,
                                    deltas.tsc, latency, rx_total, tx_total, pps)
index cb09b43..bef7c5a 100644 (file)
@@ -51,9 +51,7 @@ class ProxApproxVnf(SampleVNF):
         try:
             return self.resource_helper.execute(cmd, *args, **kwargs)
         except OSError as e:
-            if ignore_errors and e.errno in {errno.EPIPE, errno.ESHUTDOWN}:
-                pass
-            else:
+            if not ignore_errors or e.errno not in {errno.EPIPE, errno.ESHUTDOWN}:
                 raise
 
     def collect_kpi(self):
@@ -66,11 +64,12 @@ class ProxApproxVnf(SampleVNF):
             }
             return result
 
-        if len(self.vnfd_helper.interfaces) not in {1, 2, 4}:
+        intf_count = len(self.vnfd_helper.interfaces)
+        if intf_count not in {1, 2, 4}:
             raise RuntimeError("Failed ..Invalid no of ports .. "
                                "1, 2 or 4 ports only supported at this time")
 
-        port_stats = self.vnf_execute('port_stats', range(len(self.vnfd_helper.interfaces)))
+        port_stats = self.vnf_execute('port_stats', range(intf_count))
         try:
             rx_total = port_stats[6]
             tx_total = port_stats[7]
@@ -90,7 +89,7 @@ class ProxApproxVnf(SampleVNF):
 
     def _tear_down(self):
         # this should be standardized for all VNFs or removed
-        self.setup_helper.rebind_drivers()
+        self.setup_helper.tear_down()
 
     def terminate(self):
         # try to quit with socket commands
index 1b2533a..96e7030 100644 (file)
@@ -30,7 +30,9 @@ from six.moves import cStringIO
 from yardstick.benchmark.contexts.base import Context
 from yardstick.benchmark.scenarios.networking.vnf_generic import find_relative_file
 from yardstick.network_services.helpers.cpu import CpuSysCores
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
 from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
+from yardstick.network_services.helpers.dpdknicbind_helper import DpdkBindHelper
 from yardstick.network_services.nfvi.resource import ResourceProfile
 from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
 from yardstick.network_services.vnf_generic.vnf.base import QueueFileWrapper
@@ -126,15 +128,11 @@ class SetupEnvHelper(object):
 class DpdkVnfSetupEnvHelper(SetupEnvHelper):
 
     APP_NAME = 'DpdkVnf'
-    DPDK_BIND_CMD = "sudo {dpdk_nic_bind} {force} -b {driver} {vpci}"
-    DPDK_UNBIND_CMD = "sudo {dpdk_nic_bind} --force -b {driver} {vpci}"
     FIND_NET_CMD = "find /sys/class/net -lname '*{}*' -printf '%f'"
 
     HW_DEFAULT_CORE = 3
     SW_DEFAULT_CORE = 2
 
-    DPDK_STATUS_DRIVER_RE = re.compile(r"(\d{2}:\d{2}\.\d).*drv=([-\w]+)")
-
     @staticmethod
     def _update_packet_type(ip_pipeline_cfg, traffic_options):
         match_str = 'pkt_type = ipv4'
@@ -165,15 +163,9 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
         super(DpdkVnfSetupEnvHelper, self).__init__(vnfd_helper, ssh_helper, scenario_helper)
         self.all_ports = None
         self.bound_pci = None
-        self._dpdk_nic_bind = None
         self.socket = None
         self.used_drivers = None
-
-    @property
-    def dpdk_nic_bind(self):
-        if self._dpdk_nic_bind is None:
-            self._dpdk_nic_bind = self.ssh_helper.provision_tool(tool_file="dpdk-devbind.py")
-        return self._dpdk_nic_bind
+        self.dpdk_bind_helper = DpdkBindHelper(ssh_helper)
 
     def _setup_hugepages(self):
         cmd = "awk '/Hugepagesize/ { print $2$3 }' < /proc/meminfo"
@@ -190,10 +182,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
 
         self.ssh_helper.execute("echo %s | sudo tee %s" % (pages, memory_path))
 
-    def _get_dpdk_port_num(self, name):
-        interface = self.vnfd_helper.find_interface(name=name)
-        return interface['virtual-interface']['dpdk_port_num']
-
     def build_config(self):
         vnf_cfg = self.scenario_helper.vnf_cfg
         task_path = self.scenario_helper.task_path
@@ -216,7 +204,7 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
         multiport = MultiPortConfig(self.scenario_helper.topology,
                                     config_tpl_cfg,
                                     config_basename,
-                                    self.vnfd_helper.interfaces,
+                                    self.vnfd_helper,
                                     self.VNF_TYPE,
                                     lb_count,
                                     worker_threads,
@@ -234,7 +222,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
         self.ssh_helper.upload_config_file(config_basename, new_config)
         self.ssh_helper.upload_config_file(script_basename,
                                            multiport.generate_script(self.vnfd_helper))
-        self.all_ports = multiport.port_pair_list
 
         LOG.info("Provision and start the %s", self.APP_NAME)
         self._build_pipeline_kwargs()
@@ -242,11 +229,19 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
 
     def _build_pipeline_kwargs(self):
         tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME)
-        ports_len_hex = hex(2 ** (len(self.all_ports) + 1) - 1)
+        # count the number of actual ports in the list of pairs
+        # remove duplicate ports
+        # this is really a mapping from LINK ID to DPDK PMD ID
+        # e.g. 0x110 maps LINK0 -> PMD_ID_1, LINK1 -> PMD_ID_2
+        #      0x1010 maps LINK0 -> PMD_ID_1, LINK1 -> PMD_ID_3
+        ports = self.vnfd_helper.port_pairs.all_ports
+        port_nums = self.vnfd_helper.port_nums(ports)
+        # create mask from all the dpdk port numbers
+        ports_mask_hex = hex(sum(2 ** num for num in port_nums))
         self.pipeline_kwargs = {
             'cfg_file': self.CFG_CONFIG,
             'script': self.CFG_SCRIPT,
-            'ports_len_hex': ports_len_hex,
+            'port_mask_hex': ports_mask_hex,
             'tool_path': tool_path,
         }
 
@@ -285,17 +280,6 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
     def _validate_cpu_cfg(self):
         return self._get_cpu_sibling_list()
 
-    def _find_used_drivers(self):
-        cmd = "{0} -s".format(self.dpdk_nic_bind)
-        rc, dpdk_status, _ = self.ssh_helper.execute(cmd)
-
-        self.used_drivers = {
-            vpci: (index, driver)
-            for index, (vpci, driver)
-            in enumerate(self.DPDK_STATUS_DRIVER_RE.findall(dpdk_status))
-            if any(b.endswith(vpci) for b in self.bound_pci)
-        }
-
     def setup_vnf_environment(self):
         self._setup_dpdk()
         resource = self._setup_resources()
@@ -341,65 +325,31 @@ class DpdkVnfSetupEnvHelper(SetupEnvHelper):
     def _detect_and_bind_drivers(self):
         interfaces = self.vnfd_helper.interfaces
 
-        self._find_used_drivers()
-        for vpci, (index, _) in self.used_drivers.items():
-            try:
-                intf1 = next(v for v in interfaces if vpci == v['virtual-interface']['vpci'])
-            except StopIteration:
-                pass
-            else:
-                intf1['dpdk_port_num'] = index
-
-        for vpci in self.bound_pci:
-            self._bind_dpdk('igb_uio', vpci)
-            time.sleep(2)
-
-        # debug dump after binding
-        self.ssh_helper.execute("sudo {} -s".format(self.dpdk_nic_bind))
+        self.dpdk_bind_helper.read_status()
+        self.dpdk_bind_helper.save_used_drivers()
 
-    def rebind_drivers(self, force=True):
-        if not self.used_drivers:
-            self._find_used_drivers()
-        for vpci, (_, driver) in self.used_drivers.items():
-            self._bind_dpdk(driver, vpci, force)
+        self.dpdk_bind_helper.bind(self.bound_pci, 'igb_uio')
 
-    def _bind_dpdk(self, driver, vpci, force=True):
-        if force:
-            force = '--force '
-        else:
-            force = ''
-        cmd = self.DPDK_BIND_CMD.format(force=force,
-                                        dpdk_nic_bind=self.dpdk_nic_bind,
-                                        driver=driver,
-                                        vpci=vpci)
-        self.ssh_helper.execute(cmd)
+        sorted_dpdk_pci_addresses = sorted(self.dpdk_bind_helper.dpdk_bound_pci_addresses)
+        for dpdk_port_num, vpci in enumerate(sorted_dpdk_pci_addresses):
+            try:
+                intf = next(v for v in interfaces
+                            if vpci == v['virtual-interface']['vpci'])
+                # force to int
+                intf['virtual-interface']['dpdk_port_num'] = int(dpdk_port_num)
+            except:
+                pass
+        time.sleep(2)
 
-    def _detect_and_bind_dpdk(self, vpci, driver):
+    def get_local_iface_name_by_vpci(self, vpci):
         find_net_cmd = self.FIND_NET_CMD.format(vpci)
-        exit_status, _, _ = self.ssh_helper.execute(find_net_cmd)
-        if exit_status == 0:
-            # already bound
-            return None
-        self._bind_dpdk(driver, vpci)
         exit_status, stdout, _ = self.ssh_helper.execute(find_net_cmd)
-        if exit_status != 0:
-            # failed to bind
-            return None
-        return stdout
-
-    def _bind_kernel_devices(self):
-        # only used by PingSetupEnvHelper?
-        for intf in self.vnfd_helper.interfaces:
-            vi = intf["virtual-interface"]
-            stdout = self._detect_and_bind_dpdk(vi["vpci"], vi["driver"])
-            if stdout is not None:
-                vi["local_iface_name"] = posixpath.basename(stdout)
+        if exit_status == 0:
+            return stdout
+        return None
 
     def tear_down(self):
-        for vpci, (_, driver) in self.used_drivers.items():
-            self.ssh_helper.execute(self.DPDK_UNBIND_CMD.format(dpdk_nic_bind=self.dpdk_nic_bind,
-                                                                driver=driver,
-                                                                vpci=vpci))
+        self.dpdk_bind_helper.rebind_drivers()
 
 
 class ResourceHelper(object):
@@ -458,14 +408,17 @@ class ClientResourceHelper(ResourceHelper):
 
         self.client = None
         self.client_started = Value('i', 0)
-        self.my_ports = None
+        self.all_ports = None
         self._queue = Queue()
         self._result = {}
         self._terminated = Value('i', 0)
         self._vpci_ascending = None
 
     def _build_ports(self):
-        self.my_ports = [0, 1]
+        self.networks = self.vnfd_helper.port_pairs.networks
+        self.priv_ports = self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.priv_ports)
+        self.pub_ports = self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.pub_ports)
+        self.all_ports = self.vnfd_helper.port_nums(self.vnfd_helper.port_pairs.all_ports)
 
     def get_stats(self, *args, **kwargs):
         try:
@@ -474,8 +427,9 @@ class ClientResourceHelper(ResourceHelper):
             LOG.exception("TRex client not connected")
             return {}
 
-    def generate_samples(self, key=None, default=None):
-        last_result = self.get_stats(self.my_ports)
+    def generate_samples(self, ports, key=None, default=None):
+        # needs to be used ports
+        last_result = self.get_stats(ports)
         key_value = last_result.get(key, default)
 
         if not isinstance(last_result, Mapping):  # added for mock unit test
@@ -483,27 +437,29 @@ class ClientResourceHelper(ResourceHelper):
             return {}
 
         samples = {}
-        for vpci_idx, vpci in enumerate(self._vpci_ascending):
-            name = self.vnfd_helper.find_virtual_interface(vpci=vpci)["name"]
-            # fixme: VNFDs KPIs values needs to be mapped to TRex structure
-            xe_value = last_result.get(vpci_idx, {})
-            samples[name] = {
-                "rx_throughput_fps": float(xe_value.get("rx_pps", 0.0)),
-                "tx_throughput_fps": float(xe_value.get("tx_pps", 0.0)),
-                "rx_throughput_mbps": float(xe_value.get("rx_bps", 0.0)),
-                "tx_throughput_mbps": float(xe_value.get("tx_bps", 0.0)),
-                "in_packets": int(xe_value.get("ipackets", 0)),
-                "out_packets": int(xe_value.get("opackets", 0)),
-            }
-            if key:
-                samples[name][key] = key_value
+        # recalculate port for interface and see if it matches ports provided
+        for intf in self.vnfd_helper.interfaces:
+            name = intf["name"]
+            port = self.vnfd_helper.port_num(name)
+            if port in ports:
+                xe_value = last_result.get(port, {})
+                samples[name] = {
+                    "rx_throughput_fps": float(xe_value.get("rx_pps", 0.0)),
+                    "tx_throughput_fps": float(xe_value.get("tx_pps", 0.0)),
+                    "rx_throughput_mbps": float(xe_value.get("rx_bps", 0.0)),
+                    "tx_throughput_mbps": float(xe_value.get("tx_bps", 0.0)),
+                    "in_packets": int(xe_value.get("ipackets", 0)),
+                    "out_packets": int(xe_value.get("opackets", 0)),
+                }
+                if key:
+                    samples[name][key] = key_value
         return samples
 
     def _run_traffic_once(self, traffic_profile):
-        traffic_profile.execute(self)
+        traffic_profile.execute_traffic(self)
         self.client_started.value = 1
         time.sleep(self.RUN_DURATION)
-        samples = self.generate_samples()
+        samples = self.generate_samples(traffic_profile.ports)
         time.sleep(self.QUEUE_WAIT_TIME)
         self._queue.put(samples)
 
@@ -513,14 +469,14 @@ class ClientResourceHelper(ResourceHelper):
         try:
             self._build_ports()
             self.client = self._connect()
-            self.client.reset(ports=self.my_ports)
-            self.client.remove_all_streams(self.my_ports)  # remove all streams
+            self.client.reset(ports=self.all_ports)
+            self.client.remove_all_streams(self.all_ports)  # remove all streams
             traffic_profile.register_generator(self)
 
             while self._terminated.value == 0:
                 self._run_traffic_once(traffic_profile)
 
-            self.client.stop(self.my_ports)
+            self.client.stop(self.all_ports)
             self.client.disconnect()
             self._terminated.value = 0
         except STLError:
@@ -534,12 +490,12 @@ class ClientResourceHelper(ResourceHelper):
 
     def clear_stats(self, ports=None):
         if ports is None:
-            ports = self.my_ports
+            ports = self.all_ports
         self.client.clear_stats(ports=ports)
 
     def start(self, ports=None, *args, **kwargs):
         if ports is None:
-            ports = self.my_ports
+            ports = self.all_ports
         self.client.start(ports=ports, *args, **kwargs)
 
     def collect_kpi(self):
@@ -730,7 +686,6 @@ class SampleVNF(GenericVNF):
 
         self.resource_helper = resource_helper_type(self.setup_helper)
 
-        self.all_ports = None
         self.context_cfg = None
         self.nfvi_context = None
         self.pipeline_kwargs = {}
@@ -742,11 +697,17 @@ class SampleVNF(GenericVNF):
         self.q_out = Queue()
         self.queue_wrapper = None
         self.run_kwargs = {}
-        self.tg_port_pairs = None
         self.used_drivers = {}
         self.vnf_port_pairs = None
         self._vnf_process = None
 
+    def _build_ports(self):
+        self._port_pairs = PortPairs(self.vnfd_helper.interfaces)
+        self.networks = self._port_pairs.networks
+        self.priv_ports = self.vnfd_helper.port_nums(self._port_pairs.priv_ports)
+        self.pub_ports = self.vnfd_helper.port_nums(self._port_pairs.pub_ports)
+        self.my_ports = self.vnfd_helper.port_nums(self._port_pairs.all_ports)
+
     def _get_route_data(self, route_index, route_type):
         route_iter = iter(self.vnfd_helper.vdu0.get('nd_route_tbl', []))
         for _ in range(route_index):
@@ -825,6 +786,8 @@ class SampleVNF(GenericVNF):
 
             LOG.info("Waiting for %s VNF to start.. ", self.APP_NAME)
             time.sleep(1)
+            # put newline to force new prompt?
+            self.q_in.put("\r\n")
 
     def _build_run_kwargs(self):
         self.run_kwargs = {
@@ -925,7 +888,6 @@ class SampleVNFTrafficGen(GenericTrafficGen):
 
         self.runs_traffic = True
         self.traffic_finished = False
-        self.tg_port_pairs = None
         self._tg_process = None
         self._traffic_process = None
 
index e652962..9cd9f25 100644 (file)
@@ -23,6 +23,7 @@ from ipaddress import IPv4Interface
 
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
 
 LOG = logging.getLogger(__name__)
 
@@ -59,7 +60,38 @@ class PingParser(object):
 class PingSetupEnvHelper(DpdkVnfSetupEnvHelper):
 
     def setup_vnf_environment(self):
-        self._bind_kernel_devices()
+        for intf in self.vnfd_helper.interfaces:
+            vi = intf['virtual-interface']
+            vi['local_iface_name'] = self.get_local_iface_name_by_vpci(vi['vpci'])
+
+
+class PingResourceHelper(ClientResourceHelper):
+
+    def __init__(self, setup_helper):
+        super(PingResourceHelper, self).__init__(setup_helper)
+        self._queue = Queue()
+        self._parser = PingParser(self._queue)
+
+    def run_traffic(self, traffic_profile):
+        # drop the connection in order to force a new one
+        self.ssh_helper.drop_connection()
+
+        self.client_started.value = 1
+        cmd_list = [
+            "sudo ip addr flush {local_if_name}",
+            "sudo ip addr add {local_ip}/24 dev {local_if_name}",
+            "sudo ip link set {local_if_name} up",
+        ]
+
+        self.cmd_kwargs['packet_size'] = traffic_profile.params['traffic_profile']['frame_size']
+
+        for cmd in cmd_list:
+            self.ssh_helper.execute(cmd.format(**self.cmd_kwargs))
+
+        ping_cmd = "nohup ping -s {packet_size} {target_ip}&"
+        self.ssh_helper.run(ping_cmd.format(**self.cmd_kwargs),
+                            stdout=self._parser,
+                            keep_stdin_open=True, pty=True)
 
 
 class PingTrafficGen(SampleVNFTrafficGen):
@@ -69,16 +101,17 @@ class PingTrafficGen(SampleVNFTrafficGen):
     """
 
     TG_NAME = 'Ping'
+    APP_NAME = 'Ping'
     RUN_WAIT = 4
 
     def __init__(self, name, vnfd, setup_env_helper_type=None, resource_helper_type=None):
         if setup_env_helper_type is None:
             setup_env_helper_type = PingSetupEnvHelper
+        if resource_helper_type is None:
+            resource_helper_type = PingResourceHelper
 
         super(PingTrafficGen, self).__init__(name, vnfd, setup_env_helper_type,
                                              resource_helper_type)
-        self._queue = Queue()
-        self._parser = PingParser(self._queue)
         self._result = {}
 
     def scale(self, flavor=""):
@@ -89,12 +122,23 @@ class PingTrafficGen(SampleVNFTrafficGen):
         return self._tg_process.is_alive()
 
     def instantiate(self, scenario_cfg, context_cfg):
+        self._start_server()
         self._result = {
             "packets_received": 0,
             "rtt": 0,
         }
+        intf = self.vnfd_helper.interfaces[0]["virtual-interface"]
+        self.resource_helper.cmd_kwargs = {
+            'target_ip': IPv4Interface(intf["dst_ip"]).ip.exploded,
+            'local_ip': IPv4Interface(intf["local_ip"]).ip.exploded,
+            'local_if_name': intf["local_iface_name"].split('/')[0],
+        }
+
         self.setup_helper.setup_vnf_environment()
 
+    def wait_for_instantiate(self):
+        pass
+
     def listen_traffic(self, traffic_profile):
         """ Not needed for ping
 
@@ -102,27 +146,3 @@ class PingTrafficGen(SampleVNFTrafficGen):
         :return:
         """
         pass
-
-    def _traffic_runner(self, traffic_profile):
-        intf = self.vnfd_helper.interfaces[0]["virtual-interface"]
-        profile = traffic_profile.params["traffic_profile"]
-        cmd_kwargs = {
-            'target_ip': IPv4Interface(intf["dst_ip"]).ip.exploded,
-            'local_ip': IPv4Interface(intf["local_ip"]).ip.exploded,
-            'local_if_name': intf["local_iface_name"].split('/')[0],
-            'packet_size': profile["frame_size"],
-        }
-
-        cmd_list = [
-            "sudo ip addr flush {local_if_name}",
-            "sudo ip addr add {local_ip}/24 dev {local_if_name}",
-            "sudo ip link set {local_if_name} up",
-        ]
-
-        for cmd in cmd_list:
-            self.ssh_helper.execute(cmd.format(**cmd_kwargs))
-
-        ping_cmd = "ping -s {packet_size} {target_ip}"
-        self.ssh_helper.run(ping_cmd.format(**cmd_kwargs),
-                            stdout=self._parser,
-                            keep_stdin_open=True, pty=True)
index c266f2c..40eda75 100644 (file)
@@ -56,7 +56,6 @@ class ProxTrafficGen(SampleVNFTrafficGen):
 
         self.runs_traffic = True
         self.traffic_finished = False
-        self.tg_port_pairs = None
         self._tg_process = None
         self._traffic_process = None
 
index a52416d..93e4969 100644 (file)
@@ -58,19 +58,12 @@ class IxiaResourceHelper(ClientResourceHelper):
             rfc_helper_type = IxiaRfc2544Helper
 
         self.rfc_helper = rfc_helper_type(self.scenario_helper)
-        self.tg_port_pairs = []
         self.priv_ports = None
         self.pub_ports = None
 
     def _connect(self, client=None):
         self.client._connect(self.vnfd_helper)
 
-    def _build_ports(self):
-        # self.generate_port_pairs(self.topology)
-        self.priv_ports = [int(x[0][2:]) for x in self.tg_port_pairs]
-        self.pub_ports = [int(x[1][2:]) for x in self.tg_port_pairs]
-        self.my_ports = list(set(self.priv_ports).union(set(self.pub_ports)))
-
     def get_stats(self, *args, **kwargs):
         return self.client.ix_get_statistics()
 
@@ -79,33 +72,37 @@ class IxiaResourceHelper(ClientResourceHelper):
         if self.client and self.client.ixnet:
             self.client.ix_stop_traffic()
 
-    def generate_samples(self, key=None, default=None):
+    def generate_samples(self, ports, key=None, default=None):
         stats = self.get_stats()
         last_result = stats[1]
         latency = stats[0]
 
         samples = {}
-        for vpci_idx, interface in enumerate(self.vnfd_helper.interfaces):
+        for interface in self.vnfd_helper.interfaces:
             try:
-                name = "xe{0}".format(vpci_idx)
-                samples[name] = {
-                    "rx_throughput_kps": float(last_result["Rx_Rate_Kbps"][vpci_idx]),
-                    "tx_throughput_kps": float(last_result["Tx_Rate_Kbps"][vpci_idx]),
-                    "rx_throughput_mbps": float(last_result["Rx_Rate_Mbps"][vpci_idx]),
-                    "tx_throughput_mbps": float(last_result["Tx_Rate_Mbps"][vpci_idx]),
-                    "in_packets": int(last_result["Valid_Frames_Rx"][vpci_idx]),
-                    "out_packets": int(last_result["Frames_Tx"][vpci_idx]),
-                    "RxThroughput": int(last_result["Valid_Frames_Rx"][vpci_idx]) / 30,
-                    "TxThroughput": int(last_result["Frames_Tx"][vpci_idx]) / 30,
-                }
-                if key:
-                    avg_latency = latency["Store-Forward_Avg_latency_ns"][vpci_idx]
-                    min_latency = latency["Store-Forward_Min_latency_ns"][vpci_idx]
-                    max_latency = latency["Store-Forward_Max_latency_ns"][vpci_idx]
-                    samples[name][key] = \
-                        {"Store-Forward_Avg_latency_ns": avg_latency,
-                         "Store-Forward_Min_latency_ns": min_latency,
-                         "Store-Forward_Max_latency_ns": max_latency}
+                name = interface["name"]
+                # this is not DPDK port num, but this is whatever number we gave
+                # when we selected ports and programmed the profile
+                port = self.vnfd_helper.port_num(name)
+                if port in ports:
+                    samples[name] = {
+                        "rx_throughput_kps": float(last_result["Rx_Rate_Kbps"][port]),
+                        "tx_throughput_kps": float(last_result["Tx_Rate_Kbps"][port]),
+                        "rx_throughput_mbps": float(last_result["Rx_Rate_Mbps"][port]),
+                        "tx_throughput_mbps": float(last_result["Tx_Rate_Mbps"][port]),
+                        "in_packets": int(last_result["Valid_Frames_Rx"][port]),
+                        "out_packets": int(last_result["Frames_Tx"][port]),
+                        "RxThroughput": int(last_result["Valid_Frames_Rx"][port]) / 30,
+                        "TxThroughput": int(last_result["Frames_Tx"][port]) / 30,
+                    }
+                    if key:
+                        avg_latency = latency["Store-Forward_Avg_latency_ns"][port]
+                        min_latency = latency["Store-Forward_Min_latency_ns"][port]
+                        max_latency = latency["Store-Forward_Max_latency_ns"][port]
+                        samples[name][key] = \
+                            {"Store-Forward_Avg_latency_ns": avg_latency,
+                             "Store-Forward_Min_latency_ns": min_latency,
+                             "Store-Forward_Max_latency_ns": max_latency}
             except IndexError:
                 pass
 
@@ -132,6 +129,7 @@ class IxiaResourceHelper(ClientResourceHelper):
         self.client.ix_assign_ports()
 
         mac = {}
+        # TODO: shouldn't this index map to port number we used to generate the profile
         for index, interface in enumerate(self.vnfd_helper.interfaces, 1):
             virt_intf = interface["virtual-interface"]
             mac.update({
@@ -145,11 +143,11 @@ class IxiaResourceHelper(ClientResourceHelper):
                                        self.scenario_helper.scenario_cfg["task_path"])
         # Generate ixia traffic config...
         while not self._terminated.value:
-            traffic_profile.execute(self, self.client, mac, ixia_file)
+            traffic_profile.execute_traffic(self, self.client, mac, ixia_file)
             self.client_started.value = 1
             time.sleep(WAIT_FOR_TRAFFIC)
             self.client.ix_stop_traffic()
-            samples = self.generate_samples()
+            samples = self.generate_samples(traffic_profile.ports)
             self._queue.put(samples)
             status, samples = traffic_profile.get_drop_percentage(self, samples, min_tol,
                                                                   max_tol, self.client, mac,
@@ -167,11 +165,11 @@ class IxiaResourceHelper(ClientResourceHelper):
             self._terminated.value = 1
             return
 
-        traffic_profile.execute(self, self.client, mac, ixia_file)
+        traffic_profile.execute_traffic(self, self.client, mac, ixia_file)
         for _ in range(5):
             time.sleep(self.LATENCY_TIME_SLEEP)
             self.client.ix_stop_traffic()
-            samples = self.generate_samples('latency', {})
+            samples = self.generate_samples(traffic_profile.ports, 'latency', {})
             self._queue.put(samples)
             traffic_profile.start_ixia_latency(self, self.client, mac, ixia_file)
             if self._terminated.value:
@@ -197,7 +195,6 @@ class IxiaTrafficGen(SampleVNFTrafficGen):
                                              resource_helper_type)
         self._ixia_traffic_gen = None
         self.ixia_file_name = ''
-        self.tg_port_pairs = []
         self.vnf_port_pairs = []
 
     def _check_status(self):
index 15c9c0e..4e9f4bd 100644 (file)
@@ -18,9 +18,7 @@ from __future__ import print_function
 import time
 import logging
 from collections import Mapping
-from itertools import chain
 
-from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
 from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexTrafficGen
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
 from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexResourceHelper
@@ -47,23 +45,15 @@ class TrexRfcResourceHelper(TrexResourceHelper):
             rfc_helper_type = TrexRfc2544ResourceHelper
 
         self.rfc2544_helper = rfc_helper_type(self.scenario_helper)
-        # self.tg_port_pairs = []
-
-    def _build_ports(self):
-        self.tg_port_pairs, self.networks = MultiPortConfig.get_port_pairs(
-            self.vnfd_helper.interfaces)
-        self.priv_ports = [int(x[0][2:]) for x in self.tg_port_pairs]
-        self.pub_ports = [int(x[1][2:]) for x in self.tg_port_pairs]
-        self.my_ports = list(set(chain(self.priv_ports, self.pub_ports)))
 
     def _run_traffic_once(self, traffic_profile):
         if self._terminated.value:
             return
 
-        traffic_profile.execute(self)
+        traffic_profile.execute_traffic(self)
         self.client_started.value = 1
         time.sleep(self.RUN_DURATION)
-        self.client.stop(self.my_ports)
+        self.client.stop(traffic_profile.ports)
         time.sleep(self.WAIT_TIME)
         samples = traffic_profile.get_drop_percentage(self)
         self._queue.put(samples)
@@ -71,30 +61,30 @@ class TrexRfcResourceHelper(TrexResourceHelper):
         if not self.rfc2544_helper.is_done():
             return
 
-        self.client.stop(self.my_ports)
-        self.client.reset(ports=self.my_ports)
-        self.client.remove_all_streams(self.my_ports)
-        traffic_profile.execute_latency(samples=samples)
+        self.client.stop(traffic_profile.ports)
+        self.client.reset(ports=traffic_profile.ports)
+        self.client.remove_all_streams(traffic_profile.ports)
+        traffic_profile.execute_traffic_latency(samples=samples)
         multiplier = traffic_profile.calculate_pps(samples)[1]
         for _ in range(5):
             time.sleep(self.LATENCY_TIME_SLEEP)
-            self.client.stop(self.my_ports)
+            self.client.stop(traffic_profile.ports)
             time.sleep(self.WAIT_TIME)
-            last_res = self.client.get_stats(self.my_ports)
+            last_res = self.client.get_stats(traffic_profile.ports)
             if not isinstance(last_res, Mapping):
                 self._terminated.value = 1
                 continue
-            self.generate_samples('latency', {})
+            self.generate_samples(traffic_profile.ports, 'latency', {})
             self._queue.put(samples)
             self.client.start(mult=str(multiplier),
-                              ports=self.my_ports,
+                              ports=traffic_profile.ports,
                               duration=120, force=True)
 
-    def start_client(self, mult, duration, force=True):
-        self.client.start(ports=self.my_ports, mult=mult, duration=duration, force=force)
+    def start_client(self, ports, mult=None, duration=None, force=True):
+        self.client.start(ports=ports, mult=mult, duration=duration, force=force)
 
-    def clear_client_stats(self):
-        self.client.clear_stats(ports=self.my_ports)
+    def clear_client_stats(self, ports):
+        self.client.clear_stats(ports=ports)
 
     def collect_kpi(self):
         self.rfc2544_helper.iteration.value += 1
index a9bc204..8877338 100644 (file)
@@ -19,14 +19,22 @@ from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
 
+
 LOG = logging.getLogger(__name__)
 
 # UDP_Replay should work the same on all systems, we can provide the binary
+
+# we can't match the prompt regexp due to extra noise
+# yardstick.ssh ssh.py:302 DEBUG stdout: UDP_Replay: lcore 0 has nothing to do
+# eplUDP_Replay:  -- lcoreid=1 portid=0 rxqueueid=0
+# ay>
+#
+# try decreasing log level to RTE_LOG_NOTICE (5)
 REPLAY_PIPELINE_COMMAND = (
-    """sudo {tool_path} -c {cpu_mask_hex} -n 4 -w {whitelist} -- """
-    """{hw_csum} -p {ports_len_hex} --config='{config}'"""
+    """sudo {tool_path} --log-level=5 -c {cpu_mask_hex} -n 4 -w {whitelist} -- """
+    """{hw_csum} -p {port_mask_hex} --config='{config}'"""
 )
-# {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}'
+# {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}'
 
 
 class UdpReplaySetupEnvHelper(DpdkVnfSetupEnvHelper):
@@ -42,7 +50,8 @@ class UdpReplayApproxVnf(SampleVNF):
 
     APP_NAME = "UDP_Replay"
     APP_WORD = "UDP_Replay"
-    VNF_PROMPT = 'Replay>'
+    # buffering issue?
+    VNF_PROMPT = 'eplay>'
 
     VNF_TYPE = 'UdpReplay'
 
@@ -60,36 +69,30 @@ class UdpReplayApproxVnf(SampleVNF):
         super(UdpReplayApproxVnf, self).__init__(name, vnfd, setup_env_helper_type,
                                                  resource_helper_type)
 
-    def _start_server(self):
-        super(UdpReplayApproxVnf, self)._start_server()
-        self.resource_helper.start()
-
-    def scale(self, flavor=""):
-        """ scale vnfbased on flavor input """
-        raise NotImplementedError
-
-    def _deploy(self):
-        self.generate_port_pairs()
-        super(UdpReplayApproxVnf, self)._deploy()
-
     def _build_pipeline_kwargs(self):
-        all_ports = [i for i, _ in enumerate(self.vnfd_helper.interfaces)]
-        number_of_ports = len(all_ports)
+        ports = self.vnfd_helper.port_pairs.all_ports
+        number_of_ports = len(ports)
 
         tool_path = self.ssh_helper.provision_tool(tool_file=self.APP_NAME)
-        ports_mask = 2 ** number_of_ports - 1
-        ports_mask_hex = hex(ports_mask)
+        port_nums = self.vnfd_helper.port_nums(ports)
+        ports_mask_hex = hex(sum(2 ** num for num in port_nums))
+        # one core extra for master
         cpu_mask_hex = hex(2 ** (number_of_ports + 1) - 1)
         hw_csum = ""
         if (not self.scenario_helper.options.get('hw_csum', False) or
                 self.nfvi_context.attrs.get('nfvi_type') not in self.HW_OFFLOADING_NFVI_TYPES):
             hw_csum = '--no-hw-csum'
 
-        config_value = "".join(str((port, 0, port + 1)) for port in all_ports)
+        # tuples of (FLD_PORT, FLD_QUEUE, FLD_LCORE)
+        #  [--config (port,queue,lcore)[,(port,queue,lcore]]"
+        # start with lcore = 1 since we use lcore=0 for master
+        config_value = ",".join(
+            str((self.vnfd_helper.port_num(port), 0, core)).replace(" ", "") for core, port in
+            enumerate(self.vnfd_helper.port_pairs.all_ports, 1))
 
         whitelist = " -w ".join(self.setup_helper.bound_pci)
         self.pipeline_kwargs = {
-            'ports_len_hex': ports_mask_hex,
+            'port_mask_hex': ports_mask_hex,
             'tool_path': tool_path,
             'hw_csum': hw_csum,
             'whitelist': whitelist,
@@ -105,7 +108,7 @@ class UdpReplayApproxVnf(SampleVNF):
         def get_sum(offset):
             return sum(int(i) for i in split_stats[offset::5])
 
-        number_of_ports = len(self.vnfd_helper.interfaces)
+        number_of_ports = len(self.vnfd_helper.port_pairs.all_ports)
 
         stats = self.get_stats()
         stats_words = stats.split()
index 32a08c7..6c95648 100644 (file)
@@ -22,7 +22,7 @@ from yardstick.network_services.yang_model import YangModel
 LOG = logging.getLogger(__name__)
 
 # vFW should work the same on all systems, we can provide the binary
-FW_PIPELINE_COMMAND = """sudo {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}"""
+FW_PIPELINE_COMMAND = """sudo {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}"""
 
 FW_COLLECT_KPI = (r"""VFW TOTAL:[^p]+pkts_received"?:\s(\d+),[^p]+pkts_fw_forwarded"?:\s(\d+),"""
                   r"""[^p]+pkts_drop_fw"?:\s(\d+),\s""")
index 310ab67..72c1514 100644 (file)
@@ -15,6 +15,8 @@
 
 from __future__ import absolute_import
 from __future__ import print_function
+
+
 import os
 import logging
 import re
@@ -22,17 +24,17 @@ import posixpath
 
 from six.moves import configparser, zip
 
+from yardstick.network_services.helpers.samplevnf_helper import PortPairs
 from yardstick.network_services.pipeline import PipelineRules
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF, DpdkVnfSetupEnvHelper
 
 LOG = logging.getLogger(__name__)
 
-VPE_PIPELINE_COMMAND = """sudo {tool_path} -p {ports_len_hex} -f {cfg_file} -s {script}"""
+VPE_PIPELINE_COMMAND = """sudo {tool_path} -p {port_mask_hex} -f {cfg_file} -s {script}"""
 
 VPE_COLLECT_KPI = """\
 Pkts in:\s(\d+)\r\n\
-\tPkts dropped by Pkts in:\s(\d+)\r\n\
-\tPkts dropped by AH:\s(\d+)\r\n\\
+\tPkts dropped by AH:\s(\d+)\r\n\
 \tPkts dropped by other:\s(\d+)\
 """
 
@@ -92,24 +94,23 @@ class ConfigCreate(object):
         pktq = "SWQ{0}{1}".format(self.sw_q, sink)
         return pktq
 
-    def vpe_upstream(self, vnf_cfg, intf):
+    def vpe_upstream(self, vnf_cfg, index=0):
         parser = configparser.ConfigParser()
         parser.read(os.path.join(vnf_cfg, 'vpe_upstream'))
+
         for pipeline in parser.sections():
             for k, v in parser.items(pipeline):
                 if k == "pktq_in":
-                    index = intf['index']
                     if "RXQ" in v:
-                        value = "RXQ{0}.0".format(index)
+                        value = "RXQ{0}.0".format(self.priv_ports[index])
                     else:
                         value = self.get_sink_swq(parser, pipeline, k, index)
 
                     parser.set(pipeline, k, value)
 
                 elif k == "pktq_out":
-                    index = intf['peer_intf']['index']
                     if "TXQ" in v:
-                        value = "TXQ{0}.0".format(index)
+                        value = "TXQ{0}.0".format(self.pub_ports[index])
                     else:
                         self.sw_q += 1
                         value = self.get_sink_swq(parser, pipeline, k, index)
@@ -123,21 +124,19 @@ class ConfigCreate(object):
             self.n_pipeline += 1
         return parser
 
-    def vpe_downstream(self, vnf_cfg, intf):
+    def vpe_downstream(self, vnf_cfg, index):
         parser = configparser.ConfigParser()
         parser.read(os.path.join(vnf_cfg, 'vpe_downstream'))
         for pipeline in parser.sections():
             for k, v in parser.items(pipeline):
-                index = intf['dpdk_port_num']
-                peer_index = intf['peer_intf']['dpdk_port_num']
 
                 if k == "pktq_in":
                     if "RXQ" not in v:
                         value = self.get_sink_swq(parser, pipeline, k, index)
                     elif "TM" in v:
-                        value = "RXQ{0}.0 TM{1}".format(peer_index, index)
+                        value = "RXQ{0}.0 TM{1}".format(self.pub_ports[index], index)
                     else:
-                        value = "RXQ{0}.0".format(peer_index)
+                        value = "RXQ{0}.0".format(self.pub_ports[index])
 
                     parser.set(pipeline, k, value)
 
@@ -146,9 +145,9 @@ class ConfigCreate(object):
                         self.sw_q += 1
                         value = self.get_sink_swq(parser, pipeline, k, index)
                     elif "TM" in v:
-                        value = "TXQ{0}.0 TM{1}".format(peer_index, index)
+                        value = "TXQ{0}.0 TM{1}".format(self.priv_ports[index], index)
                     else:
-                        value = "TXQ{0}.0".format(peer_index)
+                        value = "TXQ{0}.0".format(self.priv_ports[index])
 
                     parser.set(pipeline, k, value)
 
@@ -166,10 +165,10 @@ class ConfigCreate(object):
             config = self.vpe_initialize(config)
             config = self.vpe_rxq(config)
             config.write(cfg_file)
-            for index, priv_port in enumerate(self.priv_ports):
-                config = self.vpe_upstream(vnf_cfg, priv_port)
+            for index in range(0, len(self.priv_ports)):
+                config = self.vpe_upstream(vnf_cfg, index)
                 config.write(cfg_file)
-                config = self.vpe_downstream(vnf_cfg, priv_port)
+                config = self.vpe_downstream(vnf_cfg, index)
                 config = self.vpe_tmq(config, index)
                 config.write(cfg_file)
 
@@ -199,36 +198,41 @@ class ConfigCreate(object):
 
         return rules.get_string()
 
+    def generate_tm_cfg(self, vnf_cfg, index=0):
+        vnf_cfg = os.path.join(vnf_cfg, "full_tm_profile_10G.cfg")
+        if os.path.exists(vnf_cfg):
+            return open(vnf_cfg).read()
+
 
 class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
 
+    APP_NAME = 'vPE_vnf'
     CFG_CONFIG = "/tmp/vpe_config"
     CFG_SCRIPT = "/tmp/vpe_script"
+    TM_CONFIG = "/tmp/full_tm_profile_10G.cfg"
     CORES = ['0', '1', '2', '3', '4', '5']
     PIPELINE_COMMAND = VPE_PIPELINE_COMMAND
 
+    def _build_vnf_ports(self):
+        self._port_pairs = PortPairs(self.vnfd_helper.interfaces)
+        self.priv_ports = self._port_pairs.priv_ports
+        self.pub_ports = self._port_pairs.pub_ports
+        self.all_ports = self._port_pairs.all_ports
+
     def build_config(self):
         vpe_vars = {
             "bin_path": self.ssh_helper.bin_path,
             "socket": self.socket,
         }
 
-        all_ports = []
-        priv_ports = []
-        pub_ports = []
-        for interface in self.vnfd_helper.interfaces:
-            all_ports.append(interface['name'])
-            vld_id = interface['virtual-interface']['vld_id']
-            if vld_id.startswith('private'):
-                priv_ports.append(interface)
-            elif vld_id.startswith('public'):
-                pub_ports.append(interface)
-
-        vpe_conf = ConfigCreate(priv_ports, pub_ports, self.socket)
+        self._build_vnf_ports()
+        vpe_conf = ConfigCreate(self.vnfd_helper.port_pairs.priv_ports,
+                                self.vnfd_helper.port_pairs.pub_ports, self.socket)
         vpe_conf.create_vpe_config(self.scenario_helper.vnf_cfg)
 
         config_basename = posixpath.basename(self.CFG_CONFIG)
         script_basename = posixpath.basename(self.CFG_SCRIPT)
+        tm_basename = posixpath.basename(self.TM_CONFIG)
         with open(self.CFG_CONFIG) as handle:
             vpe_config = handle.read()
 
@@ -237,6 +241,15 @@ class VpeApproxSetupEnvHelper(DpdkVnfSetupEnvHelper):
         vpe_script = vpe_conf.generate_vpe_script(self.vnfd_helper.interfaces)
         self.ssh_helper.upload_config_file(script_basename, vpe_script.format(**vpe_vars))
 
+        tm_config = vpe_conf.generate_tm_cfg(self.scenario_helper.vnf_cfg)
+        self.ssh_helper.upload_config_file(tm_basename, tm_config)
+
+        LOG.info("Provision and start the %s", self.APP_NAME)
+        LOG.info(self.CFG_CONFIG)
+        LOG.info(self.CFG_SCRIPT)
+        self._build_pipeline_kwargs()
+        return self.PIPELINE_COMMAND.format(**self.pipeline_kwargs)
+
 
 class VpeApproxVnf(SampleVNF):
     """ This class handles vPE VNF model-driver definitions """