Adding script to auto build VNFs 93/33493/5
authorDeepak S <deepak.s@linux.intel.com>
Tue, 18 Apr 2017 06:02:53 +0000 (23:02 -0700)
committerDeepak S <deepak.s@linux.intel.com>
Wed, 19 Apr 2017 07:22:30 +0000 (00:22 -0700)
Change-Id: I5af3301dceacb57499b92c543b912ed21f8b253d
Signed-off-by: Deepak S <deepak.s@linux.intel.com>
INSTALL.rst [new file with mode: 0644]
RELEASE_NOTES.rst [new file with mode: 0644]
patches/dpdk_custom_patch/i40e-fix-Rx-hang-when-disable-LLDP.patch [new file with mode: 0644]
patches/dpdk_custom_patch/i40e-fix-VF-bonded-device-link-down.patch [new file with mode: 0755]
patches/dpdk_custom_patch/i40e-fix-link-management.patch [new file with mode: 0644]
patches/dpdk_custom_patch/i40e-fix-link-status-change-interrupt.patch [new file with mode: 0755]
patches/dpdk_custom_patch/rte_pipeline.patch [new file with mode: 0644]
tools/setenv.sh [new file with mode: 0755]
tools/vnf_build.sh [new file with mode: 0755]

diff --git a/INSTALL.rst b/INSTALL.rst
new file mode 100644 (file)
index 0000000..310bffe
--- /dev/null
@@ -0,0 +1,30 @@
+.. this work is licensed under a creative commons attribution 4.0 international
+.. license.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) opnfv, national center of scientific research "demokritos" and others.
+
+============================
+SAMPLEVNF Installation Guide
+============================
+
+Introduction
+============
+This project provides a placeholder for various sample VNF (Virtual Network Function)
+development which includes example reference architecture and optimization methods
+related to VNF/Network service for high performance VNFs. 
+
+The sample VNFs are Open Source approximations* of Telco grade VNF’s using
+optimized VNF + NFVi Infrastructure libraries, with Performance Characterization
+of Sample† Traffic Flows.
+• * Not a commercial product. Encourage the community to contribute and close the feature gaps.
+• † No Vendor/Proprietary Workloads 
+
+VNF supported
+=============
+ 1. CG-NAT (Carrier Grade Network Address Translation) VNF
+ 2. Firewall (vFW) VNF
+ 4. Access Control List (vACL) VNF
+
+Please refer docs folder for individual VNF Installation guide.
+
+Note:- Each VNF should include a installation document explain the process to install and run VNF.
diff --git a/RELEASE_NOTES.rst b/RELEASE_NOTES.rst
new file mode 100644 (file)
index 0000000..9dd4fef
--- /dev/null
@@ -0,0 +1,28 @@
+.. this work is licensed under a creative commons attribution 4.0 international
+.. license.
+.. http://creativecommons.org/licenses/by/4.0
+.. (c) opnfv, national center of scientific research "demokritos" and others.
+
+==========================
+Sample VNF Release Notes
+==========================
+
+Introduction
+============
+This project provides a placeholder for various sample VNF (Virtual Network Function)
+development which includes example reference architecture and optimization methods
+related to VNF/Network service for high performance VNFs. 
+
+The sample VNFs are Open Source approximations* of Telco grade VNF’s using
+optimized VNF + NFVi Infrastructure libraries, with Performance Characterization
+of Sample† Traffic Flows.
+• * Not a commercial product. Encourage the community to contribute and close the feature gaps.
+• † No Vendor/Proprietary Workloads 
+
+VNF supported
+=============
+ 1. CG-NAT (Carrier Grade Network Address Translation) VNF
+ 2. Firewall (vFW) VNF
+ 4. Access Control List (vACL) VNF
+
+Please refer docs folder for individual VNF release notes.
diff --git a/patches/dpdk_custom_patch/i40e-fix-Rx-hang-when-disable-LLDP.patch b/patches/dpdk_custom_patch/i40e-fix-Rx-hang-when-disable-LLDP.patch
new file mode 100644 (file)
index 0000000..7b0e536
--- /dev/null
@@ -0,0 +1,49 @@
+From fcbd40d4327b36725c4de9f33f57809edc359f4a Mon Sep 17 00:00:00 2001
+From: Qi Zhang <qi.z.zhang@intel.com>
+Date: Thu, 20 Oct 2016 04:40:13 +0800
+Subject: [PATCH] net/i40e: fix Rx hang when disable LLDP
+
+Remove stopping LLDP as a workaround for a known
+errata which can cause Rx hang.
+
+Ref: Item #70 from
+http://www.intel.com/content/www/us/en/embedded/products/networking/xl710-10-40-controller-spec-update.html
+
+Fixes: 4861cde46116 ("i40e: new poll mode driver")
+
+Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
+Acked-by: Jingjing Wu <jingjing.wu@intel.com>
+---
+ drivers/net/i40e/i40e_ethdev.c | 9 ---------
+ 1 file changed, 9 deletions(-)
+
+diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
+index ca515dd..bb81b15 100644
+--- a/drivers/net/i40e/i40e_ethdev.c
++++ b/drivers/net/i40e/i40e_ethdev.c
+@@ -1223,11 +1223,6 @@ eth_i40e_dev_uninit(struct rte_eth_dev *dev)
+       dev->rx_pkt_burst = NULL;
+       dev->tx_pkt_burst = NULL;
+-      /* Disable LLDP */
+-      ret = i40e_aq_stop_lldp(hw, true, NULL);
+-      if (ret != I40E_SUCCESS) /* Its failure can be ignored */
+-              PMD_INIT_LOG(INFO, "Failed to stop lldp");
+-
+       /* Clear PXE mode */
+       i40e_clear_pxe_mode(hw);
+@@ -9432,10 +9427,6 @@ i40e_dcb_init_configure(struct rte_eth_dev *dev, bool sw_dcb)
+        * LLDP MIB change event.
+        */
+       if (sw_dcb == TRUE) {
+-              ret = i40e_aq_stop_lldp(hw, TRUE, NULL);
+-              if (ret != I40E_SUCCESS)
+-                      PMD_INIT_LOG(DEBUG, "Failed to stop lldp");
+-
+               ret = i40e_init_dcb(hw);
+               /* if sw_dcb, lldp agent is stopped, the return from
+                * i40e_init_dcb we expect is failure with I40E_AQ_RC_EPERM
+-- 
+2.7.4
+
diff --git a/patches/dpdk_custom_patch/i40e-fix-VF-bonded-device-link-down.patch b/patches/dpdk_custom_patch/i40e-fix-VF-bonded-device-link-down.patch
new file mode 100755 (executable)
index 0000000..ef6fd58
--- /dev/null
@@ -0,0 +1,251 @@
+diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
+index 9c1f542..13060db 100644
+--- a/drivers/net/i40e/i40e_ethdev.c
++++ b/drivers/net/i40e/i40e_ethdev.c
+@@ -5418,6 +5418,24 @@ i40e_dev_handle_vfr_event(struct rte_eth_dev *dev)
+ }
+ static void
++i40e_notify_all_vfs_link_status(struct rte_eth_dev *dev)
++{
++      struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
++      struct i40e_virtchnl_pf_event event;
++      int i;
++
++      event.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
++      event.event_data.link_event.link_status =
++              dev->data->dev_link.link_status;
++      event.event_data.link_event.link_speed =
++              dev->data->dev_link.link_speed;
++
++      for (i = 0; i < pf->vf_num; i++)
++              i40e_pf_host_send_msg_to_vf(&pf->vfs[i], I40E_VIRTCHNL_OP_EVENT,
++                              I40E_SUCCESS, (uint8_t *)&event, sizeof(event));
++}
++
++static void
+ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
+ {
+       struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+@@ -5455,9 +5473,11 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
+                       break;
+               case i40e_aqc_opc_get_link_status:
+                       ret = i40e_dev_link_update(dev, 0);
+-                      if (!ret)
++                      if (!ret) {
++                              i40e_notify_all_vfs_link_status(dev);
+                               _rte_eth_dev_callback_process(dev,
+                                       RTE_ETH_EVENT_INTR_LSC);
++                      }
+                       break;
+               default:
+                       PMD_DRV_LOG(ERR, "Request %u is not supported yet",
+diff --git a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
+index 92c8fad..61dfa93 100644
+--- a/drivers/net/i40e/i40e_ethdev.h
++++ b/drivers/net/i40e/i40e_ethdev.h
+@@ -599,7 +599,9 @@ int i40e_hash_filter_inset_select(struct i40e_hw *hw,
+                            struct rte_eth_input_set_conf *conf);
+ int i40e_fdir_filter_inset_select(struct i40e_pf *pf,
+                            struct rte_eth_input_set_conf *conf);
+-
++int i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf, uint32_t opcode,
++                              uint32_t retval, uint8_t *msg,
++                              uint16_t msglen);
+ void i40e_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
+       struct rte_eth_rxq_info *qinfo);
+ void i40e_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
+diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
+index a616ae0..ba63a7f 100644
+--- a/drivers/net/i40e/i40e_ethdev_vf.c
++++ b/drivers/net/i40e/i40e_ethdev_vf.c
+@@ -126,8 +126,6 @@ static void i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev);
+ static void i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev);
+ static void i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev);
+ static void i40evf_dev_allmulticast_disable(struct rte_eth_dev *dev);
+-static int i40evf_get_link_status(struct rte_eth_dev *dev,
+-                                struct rte_eth_link *link);
+ static int i40evf_init_vlan(struct rte_eth_dev *dev);
+ static int i40evf_dev_rx_queue_start(struct rte_eth_dev *dev,
+                                    uint16_t rx_queue_id);
+@@ -1084,31 +1082,6 @@ i40evf_del_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
+       return err;
+ }
+-static int
+-i40evf_get_link_status(struct rte_eth_dev *dev, struct rte_eth_link *link)
+-{
+-      struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+-      int err;
+-      struct vf_cmd_info args;
+-      struct rte_eth_link *new_link;
+-
+-      args.ops = (enum i40e_virtchnl_ops)I40E_VIRTCHNL_OP_GET_LINK_STAT;
+-      args.in_args = NULL;
+-      args.in_args_size = 0;
+-      args.out_buffer = vf->aq_resp;
+-      args.out_size = I40E_AQ_BUF_SZ;
+-      err = i40evf_execute_vf_cmd(dev, &args);
+-      if (err) {
+-              PMD_DRV_LOG(ERR, "fail to execute command OP_GET_LINK_STAT");
+-              return err;
+-      }
+-
+-      new_link = (struct rte_eth_link *)args.out_buffer;
+-      (void)rte_memcpy(link, new_link, sizeof(*link));
+-
+-      return 0;
+-}
+-
+ static const struct rte_pci_id pci_id_i40evf_map[] = {
+       { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF) },
+       { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_VF_HV) },
+@@ -2166,35 +2139,33 @@ i40evf_dev_link_update(struct rte_eth_dev *dev,
+        * DPDK pf host provide interfacet to acquire link status
+        * while Linux driver does not
+        */
+-      if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
+-              i40evf_get_link_status(dev, &new_link);
+-      else {
+-              /* Linux driver PF host */
+-              switch (vf->link_speed) {
+-              case I40E_LINK_SPEED_100MB:
+-                      new_link.link_speed = ETH_SPEED_NUM_100M;
+-                      break;
+-              case I40E_LINK_SPEED_1GB:
+-                      new_link.link_speed = ETH_SPEED_NUM_1G;
+-                      break;
+-              case I40E_LINK_SPEED_10GB:
+-                      new_link.link_speed = ETH_SPEED_NUM_10G;
+-                      break;
+-              case I40E_LINK_SPEED_20GB:
+-                      new_link.link_speed = ETH_SPEED_NUM_20G;
+-                      break;
+-              case I40E_LINK_SPEED_40GB:
+-                      new_link.link_speed = ETH_SPEED_NUM_40G;
+-                      break;
+-              default:
+-                      new_link.link_speed = ETH_SPEED_NUM_100M;
+-                      break;
+-              }
+-              /* full duplex only */
+-              new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
+-              new_link.link_status = vf->link_up ? ETH_LINK_UP :
+-                                                   ETH_LINK_DOWN;
++
++      /* Linux driver PF host */
++      switch (vf->link_speed) {
++      case I40E_LINK_SPEED_100MB:
++              new_link.link_speed = ETH_SPEED_NUM_100M;
++              break;
++      case I40E_LINK_SPEED_1GB:
++              new_link.link_speed = ETH_SPEED_NUM_1G;
++              break;
++      case I40E_LINK_SPEED_10GB:
++              new_link.link_speed = ETH_SPEED_NUM_10G;
++              break;
++      case I40E_LINK_SPEED_20GB:
++              new_link.link_speed = ETH_SPEED_NUM_20G;
++              break;
++      case I40E_LINK_SPEED_40GB:
++              new_link.link_speed = ETH_SPEED_NUM_40G;
++              break;
++      default:
++              new_link.link_speed = ETH_SPEED_NUM_100M;
++              break;
+       }
++      /* full duplex only */
++      new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
++      new_link.link_status = vf->link_up ? ETH_LINK_UP :
++                                           ETH_LINK_DOWN;
++
+       i40evf_dev_atomic_write_link_status(dev, &new_link);
+       return 0;
+diff --git a/drivers/net/i40e/i40e_pf.c b/drivers/net/i40e/i40e_pf.c
+index d5b2d45..350f6a0 100644
+--- a/drivers/net/i40e/i40e_pf.c
++++ b/drivers/net/i40e/i40e_pf.c
+@@ -250,7 +250,7 @@ i40e_pf_host_vf_reset(struct i40e_pf_vf *vf, bool do_hw_reset)
+       return ret;
+ }
+-static int
++int
+ i40e_pf_host_send_msg_to_vf(struct i40e_pf_vf *vf,
+                           uint32_t opcode,
+                           uint32_t retval,
+@@ -847,18 +847,6 @@ i40e_pf_host_process_cmd_get_stats(struct i40e_pf_vf *vf)
+       return I40E_SUCCESS;
+ }
+-static void
+-i40e_pf_host_process_cmd_get_link_status(struct i40e_pf_vf *vf)
+-{
+-      struct rte_eth_dev *dev = I40E_VSI_TO_ETH_DEV(vf->pf->main_vsi);
+-
+-      /* Update link status first to acquire latest link change */
+-      i40e_dev_link_update(dev, 1);
+-      i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_GET_LINK_STAT,
+-              I40E_SUCCESS, (uint8_t *)&dev->data->dev_link,
+-                              sizeof(struct rte_eth_link));
+-}
+-
+ static int
+ i40e_pf_host_process_cmd_cfg_vlan_offload(
+                                       struct i40e_pf_vf *vf,
+@@ -909,6 +897,20 @@ send_msg:
+       return ret;
+ }
++static void
++i40e_notify_vf_link_status(struct rte_eth_dev *dev, struct i40e_pf_vf *vf)
++{
++      struct i40e_virtchnl_pf_event event;
++
++      event.event = I40E_VIRTCHNL_EVENT_LINK_CHANGE;
++      event.event_data.link_event.link_status =
++                      dev->data->dev_link.link_status;
++      event.event_data.link_event.link_speed =
++                      dev->data->dev_link.link_speed;
++      i40e_pf_host_send_msg_to_vf(vf, I40E_VIRTCHNL_OP_EVENT,
++                      I40E_SUCCESS, (uint8_t *)&event, sizeof(event));
++}
++
+ void
+ i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
+                          uint16_t abs_vf_id, uint32_t opcode,
+@@ -964,6 +966,7 @@ i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
+       case I40E_VIRTCHNL_OP_ENABLE_QUEUES:
+               PMD_DRV_LOG(INFO, "OP_ENABLE_QUEUES received");
+               i40e_pf_host_process_cmd_enable_queues(vf, msg, msglen);
++              i40e_notify_vf_link_status(dev, vf);
+               break;
+       case I40E_VIRTCHNL_OP_DISABLE_QUEUES:
+               PMD_DRV_LOG(INFO, "OP_DISABLE_QUEUE received");
+@@ -993,10 +996,6 @@ i40e_pf_host_handle_vf_msg(struct rte_eth_dev *dev,
+               PMD_DRV_LOG(INFO, "OP_GET_STATS received");
+               i40e_pf_host_process_cmd_get_stats(vf);
+               break;
+-      case I40E_VIRTCHNL_OP_GET_LINK_STAT:
+-              PMD_DRV_LOG(INFO, "OP_GET_LINK_STAT received");
+-              i40e_pf_host_process_cmd_get_link_status(vf);
+-              break;
+       case I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD:
+               PMD_DRV_LOG(INFO, "OP_CFG_VLAN_OFFLOAD received");
+               i40e_pf_host_process_cmd_cfg_vlan_offload(vf, msg, msglen);
+diff --git a/drivers/net/i40e/i40e_pf.h b/drivers/net/i40e/i40e_pf.h
+index 9c01829..cddc45c 100644
+--- a/drivers/net/i40e/i40e_pf.h
++++ b/drivers/net/i40e/i40e_pf.h
+@@ -59,9 +59,8 @@ enum i40e_virtchnl_ops_dpdk {
+        * Keep some gap between Linux PF commands and
+        * DPDK PF extended commands.
+        */
+-      I40E_VIRTCHNL_OP_GET_LINK_STAT = I40E_VIRTCHNL_OP_VERSION +
++      I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD = I40E_VIRTCHNL_OP_VERSION +
+                                               I40E_DPDK_OFFSET,
+-      I40E_VIRTCHNL_OP_CFG_VLAN_OFFLOAD,
+       I40E_VIRTCHNL_OP_CFG_VLAN_PVID,
+       I40E_VIRTCHNL_OP_CONFIG_VSI_QUEUES_EXT,
+ };
diff --git a/patches/dpdk_custom_patch/i40e-fix-link-management.patch b/patches/dpdk_custom_patch/i40e-fix-link-management.patch
new file mode 100644 (file)
index 0000000..af2c9a4
--- /dev/null
@@ -0,0 +1,169 @@
+From ca7e599d4506f3d6b89dd846c901d09d46ea593c Mon Sep 17 00:00:00 2001
+From: Jingjing Wu <jingjing.wu@intel.com>
+Date: Thu, 12 May 2016 15:21:04 +0800
+Subject: [PATCH] net/i40e: fix link management
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Previously, there was a known issue "On Intel® 40G Ethernet
+Controller stopping the port does not really down the port link."
+
+There were two reasons why the port was always kept up.
+1. Old firmware versions had issues when "Set PHY config command"
+   was used on 40G NICs.
+2. The kernel i40e driver didn't call "Set PHY config command" when
+   ifconfig up/down was used, it assumes the link is always up. But
+   in DPDK, ports are forced down when an applications quits. So if
+   the port is then switched to being controlled by kernel the driver,
+   the port can not be brought up through "ifconfig <ethx> up".
+
+This patch fixes this issue by adding in "Set PHY config command"
+into our driver. This is now possible because with newer firmware
+there is no longer a problem using this command.
+
+With this fix, after DPDK quit, if the port is switched to being used
+by the kernel driver, "ethtool -s <ethx> autoneg on" can be used to
+turn on the auto negotiation, and then port can be brought up through
+"ifconfig <ethx> up".
+NOTE: requires kernel i40e driver version >= 1.4.X
+
+Fixes: 2f1e22817420 ("i40e: skip link control as firmware workaround")
+Fixes: 16c979f9adf2 ("i40e: disable setting of PHY configuration")
+
+Signed-off-by: Jingjing Wu <jingjing.wu@intel.com>
+---
+ doc/guides/rel_notes/known_issues.rst | 19 ---------
+ drivers/net/i40e/i40e_ethdev.c        | 72 +++++++++++++++++++++++++++++------
+ 2 files changed, 60 insertions(+), 31 deletions(-)
+
+diff --git a/doc/guides/rel_notes/known_issues.rst b/doc/guides/rel_notes/known_issues.rst
+index e464eca..5ec1987 100644
+--- a/doc/guides/rel_notes/known_issues.rst
++++ b/doc/guides/rel_notes/known_issues.rst
+@@ -532,25 +532,6 @@ Cannot set link speed on Intel® 40G Ethernet controller
+    Poll Mode Driver (PMD).
+-Stopping the port does not down the link on Intel® 40G Ethernet controller
+---------------------------------------------------------------------------
+-
+-**Description**:
+-   On Intel® 40G Ethernet Controller stopping the port does not really down the port link.
+-
+-**Implication**:
+-   The port link will be still up after stopping the port.
+-
+-**Resolution/Workaround**:
+-   None
+-
+-**Affected Environment/Platform**:
+-   All.
+-
+-**Driver/Module**:
+-   Poll Mode Driver (PMD).
+-
+-
+ Devices bound to igb_uio with VT-d enabled do not work on Linux kernel 3.15-3.17
+ --------------------------------------------------------------------------------
+diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
+index f94ad87..7a94663 100644
+--- a/drivers/net/i40e/i40e_ethdev.c
++++ b/drivers/net/i40e/i40e_ethdev.c
+@@ -1407,15 +1407,58 @@ i40e_parse_link_speeds(uint16_t link_speeds)
+ }
+ static int
+-i40e_phy_conf_link(__rte_unused struct i40e_hw *hw,
+-                 __rte_unused uint8_t abilities,
+-                 __rte_unused uint8_t force_speed)
+-{
+-      /* Skip any phy config on both 10G and 40G interfaces, as a workaround
+-       * for the link control limitation of that all link control should be
+-       * handled by firmware. It should follow up if link control will be
+-       * opened to software driver in future firmware versions.
+-       */
++i40e_phy_conf_link(struct i40e_hw *hw,
++                 uint8_t abilities,
++                 uint8_t force_speed)
++{
++      enum i40e_status_code status;
++      struct i40e_aq_get_phy_abilities_resp phy_ab;
++      struct i40e_aq_set_phy_config phy_conf;
++      const uint8_t mask = I40E_AQ_PHY_FLAG_PAUSE_TX |
++                      I40E_AQ_PHY_FLAG_PAUSE_RX |
++                      I40E_AQ_PHY_FLAG_PAUSE_RX |
++                      I40E_AQ_PHY_FLAG_LOW_POWER;
++      const uint8_t advt = I40E_LINK_SPEED_40GB |
++                      I40E_LINK_SPEED_10GB |
++                      I40E_LINK_SPEED_1GB |
++                      I40E_LINK_SPEED_100MB;
++      int ret = -ENOTSUP;
++
++
++      status = i40e_aq_get_phy_capabilities(hw, false, false, &phy_ab,
++                                            NULL);
++      if (status)
++              return ret;
++
++      memset(&phy_conf, 0, sizeof(phy_conf));
++
++      /* bits 0-2 use the values from get_phy_abilities_resp */
++      abilities &= ~mask;
++      abilities |= phy_ab.abilities & mask;
++
++      /* update ablities and speed */
++      if (abilities & I40E_AQ_PHY_AN_ENABLED)
++              phy_conf.link_speed = advt;
++      else
++              phy_conf.link_speed = force_speed;
++
++      phy_conf.abilities = abilities;
++
++      /* use get_phy_abilities_resp value for the rest */
++      phy_conf.phy_type = phy_ab.phy_type;
++      phy_conf.eee_capability = phy_ab.eee_capability;
++      phy_conf.eeer = phy_ab.eeer_val;
++      phy_conf.low_power_ctrl = phy_ab.d3_lpan;
++
++      PMD_DRV_LOG(DEBUG, "\tCurrent: abilities %x, link_speed %x",
++                  phy_ab.abilities, phy_ab.link_speed);
++      PMD_DRV_LOG(DEBUG, "\tConfig:  abilities %x, link_speed %x",
++                  phy_conf.abilities, phy_conf.link_speed);
++
++      status = i40e_aq_set_phy_config(hw, &phy_conf, NULL);
++      if (status)
++              return ret;
++
+       return I40E_SUCCESS;
+ }
+@@ -1431,8 +1474,13 @@ i40e_apply_link_speed(struct rte_eth_dev *dev)
+       abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+       if (!(conf->link_speeds & ETH_LINK_SPEED_FIXED))
+               abilities |= I40E_AQ_PHY_AN_ENABLED;
+-      else
+-              abilities |= I40E_AQ_PHY_LINK_ENABLED;
++      abilities |= I40E_AQ_PHY_LINK_ENABLED;
++
++      /* Skip changing speed on 40G interfaces, FW does not support */
++      if (i40e_is_40G_device(hw->device_id)) {
++              speed =  I40E_LINK_SPEED_UNKNOWN;
++              abilities |= I40E_AQ_PHY_AN_ENABLED;
++      }
+       return i40e_phy_conf_link(hw, abilities, speed);
+ }
+@@ -1742,7 +1790,7 @@ i40e_dev_set_link_up(struct rte_eth_dev *dev)
+  * Set device link down.
+  */
+ static int
+-i40e_dev_set_link_down(__rte_unused struct rte_eth_dev *dev)
++i40e_dev_set_link_down(struct rte_eth_dev *dev)
+ {
+       uint8_t speed = I40E_LINK_SPEED_UNKNOWN;
+       uint8_t abilities = I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+-- 
+2.7.4
+
diff --git a/patches/dpdk_custom_patch/i40e-fix-link-status-change-interrupt.patch b/patches/dpdk_custom_patch/i40e-fix-link-status-change-interrupt.patch
new file mode 100755 (executable)
index 0000000..1510b36
--- /dev/null
@@ -0,0 +1,150 @@
+diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
+index d0aeb70..9c1f542 100644
+--- a/drivers/net/i40e/i40e_ethdev.c
++++ b/drivers/net/i40e/i40e_ethdev.c
+@@ -108,7 +108,6 @@
+               I40E_PFINT_ICR0_ENA_GRST_MASK | \
+               I40E_PFINT_ICR0_ENA_PCI_EXCEPTION_MASK | \
+               I40E_PFINT_ICR0_ENA_STORM_DETECT_MASK | \
+-              I40E_PFINT_ICR0_ENA_LINK_STAT_CHANGE_MASK | \
+               I40E_PFINT_ICR0_ENA_HMC_ERR_MASK | \
+               I40E_PFINT_ICR0_ENA_PE_CRITERR_MASK | \
+               I40E_PFINT_ICR0_ENA_VFLR_MASK | \
+@@ -1768,6 +1767,16 @@ i40e_dev_start(struct rte_eth_dev *dev)
+               if (dev->data->dev_conf.intr_conf.lsc != 0)
+                       PMD_INIT_LOG(INFO, "lsc won't enable because of"
+                                    " no intr multiplex\n");
++      } else if (dev->data->dev_conf.intr_conf.lsc != 0) {
++              ret = i40e_aq_set_phy_int_mask(hw,
++                                             ~(I40E_AQ_EVENT_LINK_UPDOWN |
++                                             I40E_AQ_EVENT_MODULE_QUAL_FAIL |
++                                             I40E_AQ_EVENT_MEDIA_NA), NULL);
++              if (ret != I40E_SUCCESS)
++                      PMD_DRV_LOG(WARNING, "Fail to set phy mask");
++
++              /* Call get_link_info aq commond to enable LSE */
++              i40e_dev_link_update(dev, 0);
+       }
+       /* enable uio intr after callback register */
+@@ -1984,6 +1993,7 @@ i40e_dev_link_update(struct rte_eth_dev *dev,
+       struct rte_eth_link link, old;
+       int status;
+       unsigned rep_cnt = MAX_REPEAT_TIME;
++      bool enable_lse = dev->data->dev_conf.intr_conf.lsc ? true : false;
+       memset(&link, 0, sizeof(link));
+       memset(&old, 0, sizeof(old));
+@@ -1992,7 +2002,8 @@ i40e_dev_link_update(struct rte_eth_dev *dev,
+       do {
+               /* Get link status information from hardware */
+-              status = i40e_aq_get_link_info(hw, false, &link_status, NULL);
++              status = i40e_aq_get_link_info(hw, enable_lse,
++                                              &link_status, NULL);
+               if (status != I40E_SUCCESS) {
+                       link.link_speed = ETH_SPEED_NUM_100M;
+                       link.link_duplex = ETH_LINK_FULL_DUPLEX;
+@@ -5442,6 +5453,12 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
+                                       info.msg_buf,
+                                       info.msg_len);
+                       break;
++              case i40e_aqc_opc_get_link_status:
++                      ret = i40e_dev_link_update(dev, 0);
++                      if (!ret)
++                              _rte_eth_dev_callback_process(dev,
++                                      RTE_ETH_EVENT_INTR_LSC);
++                      break;
+               default:
+                       PMD_DRV_LOG(ERR, "Request %u is not supported yet",
+                                   opcode);
+@@ -5451,57 +5468,6 @@ i40e_dev_handle_aq_msg(struct rte_eth_dev *dev)
+       rte_free(info.msg_buf);
+ }
+-/*
+- * Interrupt handler is registered as the alarm callback for handling LSC
+- * interrupt in a definite of time, in order to wait the NIC into a stable
+- * state. Currently it waits 1 sec in i40e for the link up interrupt, and
+- * no need for link down interrupt.
+- */
+-static void
+-i40e_dev_interrupt_delayed_handler(void *param)
+-{
+-      struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+-      struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+-      uint32_t icr0;
+-
+-      /* read interrupt causes again */
+-      icr0 = I40E_READ_REG(hw, I40E_PFINT_ICR0);
+-
+-#ifdef RTE_LIBRTE_I40E_DEBUG_DRIVER
+-      if (icr0 & I40E_PFINT_ICR0_ECC_ERR_MASK)
+-              PMD_DRV_LOG(ERR, "ICR0: unrecoverable ECC error\n");
+-      if (icr0 & I40E_PFINT_ICR0_MAL_DETECT_MASK)
+-              PMD_DRV_LOG(ERR, "ICR0: malicious programming detected\n");
+-      if (icr0 & I40E_PFINT_ICR0_GRST_MASK)
+-              PMD_DRV_LOG(INFO, "ICR0: global reset requested\n");
+-      if (icr0 & I40E_PFINT_ICR0_PCI_EXCEPTION_MASK)
+-              PMD_DRV_LOG(INFO, "ICR0: PCI exception\n activated\n");
+-      if (icr0 & I40E_PFINT_ICR0_STORM_DETECT_MASK)
+-              PMD_DRV_LOG(INFO, "ICR0: a change in the storm control "
+-                                                              "state\n");
+-      if (icr0 & I40E_PFINT_ICR0_HMC_ERR_MASK)
+-              PMD_DRV_LOG(ERR, "ICR0: HMC error\n");
+-      if (icr0 & I40E_PFINT_ICR0_PE_CRITERR_MASK)
+-              PMD_DRV_LOG(ERR, "ICR0: protocol engine critical error\n");
+-#endif /* RTE_LIBRTE_I40E_DEBUG_DRIVER */
+-
+-      if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) {
+-              PMD_DRV_LOG(INFO, "INT:VF reset detected\n");
+-              i40e_dev_handle_vfr_event(dev);
+-      }
+-      if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {
+-              PMD_DRV_LOG(INFO, "INT:ADMINQ event\n");
+-              i40e_dev_handle_aq_msg(dev);
+-      }
+-
+-      /* handle the link up interrupt in an alarm callback */
+-      i40e_dev_link_update(dev, 0);
+-      _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC);
+-
+-      i40e_pf_enable_irq0(hw);
+-      rte_intr_enable(&(dev->pci_dev->intr_handle));
+-}
+-
+ /**
+  * Interrupt handler triggered by NIC  for handling
+  * specific interrupt.
+@@ -5558,31 +5524,6 @@ i40e_dev_interrupt_handler(__rte_unused struct rte_intr_handle *handle,
+               PMD_DRV_LOG(INFO, "ICR0: adminq event");
+               i40e_dev_handle_aq_msg(dev);
+       }
+-
+-      /* Link Status Change interrupt */
+-      if (icr0 & I40E_PFINT_ICR0_LINK_STAT_CHANGE_MASK) {
+-#define I40E_US_PER_SECOND 1000000
+-              struct rte_eth_link link;
+-
+-              PMD_DRV_LOG(INFO, "ICR0: link status changed\n");
+-              memset(&link, 0, sizeof(link));
+-              rte_i40e_dev_atomic_read_link_status(dev, &link);
+-              i40e_dev_link_update(dev, 0);
+-
+-              /*
+-               * For link up interrupt, it needs to wait 1 second to let the
+-               * hardware be a stable state. Otherwise several consecutive
+-               * interrupts can be observed.
+-               * For link down interrupt, no need to wait.
+-               */
+-              if (!link.link_status && rte_eal_alarm_set(I40E_US_PER_SECOND,
+-                      i40e_dev_interrupt_delayed_handler, (void *)dev) >= 0)
+-                      return;
+-              else
+-                      _rte_eth_dev_callback_process(dev,
+-                              RTE_ETH_EVENT_INTR_LSC);
+-      }
+-
+ done:
+       /* Enable interrupt */
+       i40e_pf_enable_irq0(hw);
diff --git a/patches/dpdk_custom_patch/rte_pipeline.patch b/patches/dpdk_custom_patch/rte_pipeline.patch
new file mode 100644 (file)
index 0000000..3f52d32
--- /dev/null
@@ -0,0 +1,88 @@
+--- lib/librte_pipeline/rte_pipeline.c 2016-08-10 21:50:46.625571187 +0530
++++ lib/librte_pipeline/rte_pipeline.c 2016-08-10 21:51:02.333571628 +0530
+@@ -1241,6 +1241,85 @@
+               }
+ }
+
++void
++rte_pipeline_action_handler_port_ext(struct rte_pipeline *p,
++                                        uint64_t pkts_mask,
++                                        struct rte_pipeline_table_entry **entries);
++
++void
++rte_pipeline_action_handler_port_ext(struct rte_pipeline *p,
++                                        uint64_t pkts_mask,
++                                        struct rte_pipeline_table_entry **entries)
++{
++        p->pkts_mask = pkts_mask;
++
++        if ((pkts_mask & (pkts_mask + 1)) == 0) {
++                uint64_t n_pkts = __builtin_popcountll(pkts_mask);
++                uint32_t i;
++
++                for (i = 0; i < n_pkts; i++) {
++                        struct rte_mbuf *pkt = p->pkts[i];
++                        uint32_t port_out_id = entries[i]->port_id;
++                        struct rte_port_out *port_out =
++                                &p->ports_out[port_out_id];
++
++                        /* Output port user actions */
++                        if (port_out->f_action == NULL) /* Output port TX */
++                                port_out->ops.f_tx(port_out->h_port, pkt);
++                        else {
++                                uint64_t pkt_mask = 1LLU << i;
++
++                                port_out->f_action(p,
++                                        p->pkts,
++                                        pkt_mask,
++                                        port_out->arg_ah);
++
++                                RTE_PIPELINE_STATS_AH_DROP_READ(p,
++                                        port_out->n_pkts_dropped_by_ah);
++
++                                /* Output port TX */
++                                if (pkt_mask & p->pkts_mask)
++                                        port_out->ops.f_tx(port_out->h_port,
++                                                pkt);
++                        }
++                }
++        } else {
++                uint32_t i;
++
++                for (i = 0;  i < RTE_PORT_IN_BURST_SIZE_MAX; i++) {
++                        uint64_t pkt_mask = 1LLU << i;
++                        struct rte_mbuf *pkt;
++                        struct rte_port_out *port_out;
++                        uint32_t port_out_id;
++
++                        if ((pkt_mask & pkts_mask) == 0)
++                                continue;
++
++                        pkt = p->pkts[i];
++                        port_out_id = entries[i]->port_id;
++                        port_out = &p->ports_out[port_out_id];
++
++                        /* Output port user actions */
++                        if (port_out->f_action == NULL) /* Output port TX */
++                                port_out->ops.f_tx(port_out->h_port, pkt);
++                        else {
++                                port_out->f_action(p,
++                                        p->pkts,
++                                        pkt_mask,
++                                        port_out->arg_ah);
++
++                                RTE_PIPELINE_STATS_AH_DROP_READ(p,
++                                        port_out->n_pkts_dropped_by_ah);
++
++                                /* Output port TX */
++                                if (pkt_mask & p->pkts_mask)
++                                        port_out->ops.f_tx(port_out->h_port,
++                                                pkt);
++                        }
++                }
++        }
++}
++
+ static inline void
+ rte_pipeline_action_handler_port_meta(struct rte_pipeline *p,
+               uint64_t pkts_mask)
diff --git a/tools/setenv.sh b/tools/setenv.sh
new file mode 100755 (executable)
index 0000000..800168b
--- /dev/null
@@ -0,0 +1,19 @@
+#! /bin/bash
+#
+# Copyright (c) 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.
+#
+export VNF_CORE=$( cd "$( dirname "${BASH_SOURCE[0]}")/.." && pwd )
+export RTE_SDK=$( cd "$( dirname "${BASH_SOURCE[0]}")/.." && pwd )/dpdk
+export RTE_TARGET=x86_64-native-linuxapp-gcc
diff --git a/tools/vnf_build.sh b/tools/vnf_build.sh
new file mode 100755 (executable)
index 0000000..7c9265d
--- /dev/null
@@ -0,0 +1,317 @@
+#! /bin/bash
+#
+# Copyright (c) 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.
+#
+
+cd $(dirname ${BASH_SOURCE[0]})/..
+export VNF_CORE=$PWD
+echo "------------------------------------------------------------------------------"
+echo " VNF_CORE exported as $VNF_CORE"
+echo "------------------------------------------------------------------------------"
+
+HUGEPGSZ=`cat /proc/meminfo  | grep Hugepagesize | cut -d : -f 2 | tr -d ' '`
+MODPROBE="/sbin/modprobe"
+INSMOD="/sbin/insmod"
+DPDK_DOWNLOAD="http://dpdk.org/browse/dpdk/snapshot/dpdk-16.04.zip"
+DPDK_DIR=$VNF_CORE/dpdk
+
+#
+# Sets QUIT variable so script will finish.
+#
+quit()
+{
+       QUIT=$1
+}
+
+# Shortcut for quit.
+q()
+{
+       quit
+}
+
+setup_http_proxy()
+{
+       while true; do
+               echo
+               read -p "Enter Proxy : " proxy
+               export http_proxy=$proxy
+               export https_proxy=$proxy
+               echo "Acquire::http::proxy \"$http_proxy\";" | sudo tee -a /etc/apt/apt.conf > /dev/null
+               echo "Acquire::https::proxy \"$http_proxy\";" | sudo tee -a /etc/apt/apt.conf > /dev/null
+
+               wget -T 20 -t 3 --spider http://www.google.com > /dev/null 2>&1
+               if [ "$?" != 0 ]; then
+                       echo -e "No Internet connection. Proxy incorrect? Try again"
+                       echo -e "eg: http://<proxy>:<port>"
+                       exit 1
+               fi
+       return
+       done
+       echo "Network connectivity successful."
+}
+
+step_1()
+{
+        TITLE="Environment setup."
+        CONFIG_NUM=1
+        TEXT[1]="Check OS and network connection"
+        FUNC[1]="setup_env"
+}
+setup_env()
+{
+       # a. Check for OS dependencies
+       source /etc/os-release
+       if [[ $VERSION_ID != "16.04" ]] ; then
+               echo "WARNING: It is recommended to use Ubuntu 16.04..Your version is "$VERSION_ID
+       else
+               echo "Ubuntu 16.04 OS requirement met..."
+       fi
+       echo
+       echo "Checking network connectivity..."
+       # b. Check for internet connections
+       wget -T 20 -t 3 --spider http://www.google.com > /dev/null 2>&1
+       if [ "$?" != 0 ]; then
+               while true; do
+                       read -p "No Internet connection. Are you behind a proxy (y/n)? " yn
+                       case $yn in
+                               [Yy]* ) $SETUP_PROXY ; return;;
+                               [Nn]* ) echo "Please check your internet connection..." ; exit;;
+                               * ) "Please answer yes or no.";;
+                       esac
+               done
+       fi
+       echo "Network connectivity successful."
+}
+
+step_2()
+{
+        TITLE="Download and Install"
+        CONFIG_NUM=1
+        TEXT[1]="Agree to download"
+        FUNC[1]="get_agreement_download"
+       TEXT[2]="Download packages"
+       FUNC[2]="install_libs"
+       TEXT[3]="Download DPDK zip"
+       FUNC[3]="download_dpdk_zip"
+       TEXT[4]="Build and Install DPDK"
+       FUNC[4]="install_dpdk"
+       TEXT[5]="Setup hugepages"
+       FUNC[5]="setup_hugepages"
+}
+get_agreement_download()
+{
+       echo
+       echo "List of packages needed for VNFs build and installation:"
+       echo "-------------------------------------------------------"
+       echo "1. DPDK version 16.04"
+       echo "2. build-essential"
+       echo "3. linux-headers-generic"
+       echo "4. git"
+       echo "5. unzip"
+       echo "6. libpcap-dev"
+       echo "7. make"
+       echo "8. and other library dependencies"
+       while true; do
+               read -p "We need download above mentioned package. Press (y/n) to continue? " yn
+               case $yn in
+                       [Yy]* )
+                               touch .agree
+                               return;;
+                       [Nn]* ) exit;;
+                       * ) "Please answer yes or no.";;
+               esac
+       done
+}
+
+install_libs()
+{
+       echo "Install libs needed to build and run VNFs..."
+       file_name=".agree"
+       if [ ! -e "$file_name" ]; then
+               echo "Please choose option '2.Agree to download' first"
+               return
+       fi
+       file_name=".download"
+       if [ -e "$file_name" ]; then
+               clear
+               return
+       fi
+       sudo apt-get update
+       sudo apt-get -y install build-essential linux-headers-$(uname -r) git unzip libpcap0.8-dev gcc \
+               make libc6 libc6-dev g++-multilib libzmq3-dev libcurl4-openssl-dev
+       touch .download
+}
+
+download_dpdk_zip()
+{
+       echo "Download DPDK zip"
+       file_name=".agree"
+       if [ ! -e "$file_name" ]; then
+               echo "Please choose option '2.Agree to download' first"
+               return
+       fi
+       rm -rf $DPDK_DIR
+       if [ ! -e ${DPDK_DOWNLOAD##*/} ] ; then
+               wget ${DPDK_DOWNLOAD}
+       fi
+       unzip -o ${DPDK_DOWNLOAD##*/}
+       mv $VNF_CORE/dpdk-16.04 $VNF_CORE/dpdk
+}
+
+install_dpdk()
+{
+       echo "Build DPDK"
+
+       if [ ! -d "$DPDK_DIR" ]; then
+     echo "Please choose option '4 Download DPDK zip'"
+     return
+       fi
+
+       export RTE_TARGET=x86_64-native-linuxapp-gcc
+
+       pushd $DPDK_DIR
+       echo "Apply dpdk custom patches..."
+       patch -p0 < $VNF_CORE/patches/dpdk_custom_patch/rte_pipeline.patch
+       patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-link-management.patch
+       patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-Rx-hang-when-disable-LLDP.patch
+       patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-link-status-change-interrupt.patch
+       patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/i40e-fix-VF-bonded-device-link-down.patch
+
+       make -j install T=$RTE_TARGET
+       if [ $? -ne 0 ] ; then
+               echo "Failed to build dpdk, please check the errors."
+               return
+       fi
+       sudo modinfo igb_uio
+       if [ $? -ne 0 ] ; then
+               sudo $MODPROBE -v uio
+               sudo $INSMOD $RTE_TARGET/kmod/igb_uio.ko
+               sudo cp -f $RTE_TARGET/kmod/igb_uio.ko /lib/modules/$(uname -r)
+               echo "uio" | sudo tee -a /etc/modules
+               echo "igb_uio" | sudo tee -a /etc/modules
+               sudo depmod
+       fi
+       popd
+}
+
+setup_hugepages()
+{
+       #----
+       Pages=16
+       if [[ "$HUGEPGSZ" = "2048kB" ]] ; then
+               Pages=8192
+       fi
+       if [ ! "`grep nr_hugepages /etc/sysctl.conf`" ] ; then
+               echo "vm.nr_hugepages=$Pages" | sudo tee /etc/sysctl.conf
+       fi
+       sudo sysctl -p
+
+       sudo service procps start
+
+       grep -s '/dev/hugepages' /proc/mounts
+       if [ $? -ne 0 ] ; then
+               echo "Creating /mnt/huge and mounting as hugetlbfs"
+               sudo mkdir -p /mnt/huge
+               sudo mount -t hugetlbfs nodev /mnt/huge
+               echo "nodev /mnt/huge hugetlbfs defaults 0 0" | sudo tee -a /etc/fstab > /dev/null
+        fi
+}
+
+step_3()
+{
+        TITLE="Build VNFs"
+        CONFIG_NUM=1
+                               TEXT[1]="Build all VNFs (vACL, vCGNAPT, vFW)"
+        FUNC[1]="build_vnfs"
+}
+
+build_vnfs()
+{
+
+       if [ ! -d "$DPDK_DIR" ]; then
+     echo "Please choose option '4 Download DPDK zip'"
+     return
+       fi
+
+       if [ ! -d "$DPDK_DIR/x86_64-native-linux-gcc" ]; then
+     echo "Please choose option '5 Build and Install DPDK'"
+     return
+       fi
+
+       export RTE_SDK=$DPDK_DIR
+       export RTE_TARGET=x86_64-native-linuxapp-gcc
+       pushd $VNF_CORE
+       make clean
+       make || { echo -e "\nVNF: Make failed\n"; }
+       popd
+}
+
+SETUP_PROXY="setup_http_proxy"
+STEPS[1]="step_1"
+STEPS[2]="step_2"
+STEPS[3]="step_3"
+
+QUIT=0
+
+clear
+
+echo -n "Checking for user permission.. "
+sudo -n true
+if [ $? -ne 0 ]; then
+   echo "Password-less sudo user must run this script" 1>&2
+   exit 1
+fi
+echo "Done"
+clear
+
+while [ "$QUIT" == "0" ]; do
+        OPTION_NUM=1
+        for s in $(seq ${#STEPS[@]}) ; do
+                ${STEPS[s]}
+
+                echo "----------------------------------------------------------"
+                echo " Step $s: ${TITLE}"
+                echo "----------------------------------------------------------"
+
+                for i in $(seq ${#TEXT[@]}) ; do
+                        echo "[$OPTION_NUM] ${TEXT[i]}"
+                        OPTIONS[$OPTION_NUM]=${FUNC[i]}
+                        let "OPTION_NUM+=1"
+                done
+
+                # Clear TEXT and FUNC arrays before next step
+                unset TEXT
+                unset FUNC
+
+                echo ""
+        done
+
+        echo "[$OPTION_NUM] Exit Script"
+        OPTIONS[$OPTION_NUM]="quit"
+        echo ""
+        echo -n "Option: "
+        read our_entry
+        echo ""
+        ${OPTIONS[our_entry]} ${our_entry}
+
+        if [ "$QUIT" == "0" ] ; then
+                echo
+                echo -n "Press enter to continue ..."; read
+                clear
+                continue
+                exit
+        fi
+        echo "Installation successfully complete."
+done