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
-
-from yardstick.common.utils import ip_to_hex
+from yardstick.common import utils
LOG = logging.getLogger(__name__)
link {0} up
"""
-ACTION_TEMPLATE = """\
-p action add {0} accept
-p action add {0} fwd
-p action add {0} count
-"""
-
-FW_ACTION_TEMPLATE = """\
-p action add {0} accept
-p action add {0} fwd
-p action add {0} count
-p action add {0} conntrack
-"""
-
# This sets up a basic passthrough with no rules
SCRIPT_TPL = """
{link_config}
{arp_config6}
-{actions}
+{arp_route_tbl}
+
+{arp_route_tbl6}
-{rules}
+{flows}
"""
+class PortPairs(object):
+
+ DOWNLINK = "downlink"
+ UPLINK = "uplink"
+
+ def __init__(self, interfaces):
+ super(PortPairs, self).__init__()
+ self.interfaces = interfaces
+ self._all_ports = None
+ self._uplink_ports = None
+ self._downlink_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_downlink_id(cls, vld_id):
+ # partition returns a tuple
+ parts = list(vld_id.partition(cls.UPLINK))
+ if parts[0]:
+ # 'uplink' was not in or not leftmost in the string
+ return
+ parts[1] = cls.DOWNLINK
+ public_id = ''.join(parts)
+ return public_id
+
+ @property
+ # this only works for vnfs that have both uplink and public visible
+ def valid_networks(self):
+ if self._valid_networks is None:
+ self._valid_networks = []
+ for vld_id in self.networks:
+ downlink_id = self.get_downlink_id(vld_id)
+ if downlink_id in self.networks:
+ self._valid_networks.append((vld_id, downlink_id))
+ return self._valid_networks
+
+ @property
+ def all_ports(self):
+ if self._all_ports is None:
+ self._all_ports = sorted(set(self.uplink_ports + self.downlink_ports))
+ return self._all_ports
+
+ @property
+ def uplink_ports(self):
+ if self._uplink_ports is None:
+ intfs = chain.from_iterable(
+ intfs for vld_id, intfs in self.networks.items() if
+ vld_id.startswith(self.UPLINK))
+ self._uplink_ports = sorted(set(intfs))
+ return self._uplink_ports
+
+ @property
+ def downlink_ports(self):
+ if self._downlink_ports is None:
+ intfs = chain.from_iterable(
+ intfs for vld_id, intfs in self.networks.items() if
+ vld_id.startswith(self.DOWNLINK))
+ self._downlink_ports = sorted(set(intfs))
+ return self._downlink_ports
+
+ @property
+ def port_pair_list(self):
+ if self._port_pair_list is None:
+ self._port_pair_list = []
+
+ for uplink, downlink in self.valid_networks:
+ for uplink_intf in self.networks[uplink]:
+ # only VNFs have uplink, public peers
+ peer_intfs = self.networks.get(downlink, [])
+ if peer_intfs:
+ for downlink_intf in peer_intfs:
+ port_pair = uplink_intf, downlink_intf
+ self._port_pair_list.append(port_pair)
+ return self._port_pair_list
+
+
class MultiPortConfig(object):
HW_LB = "HW"
return parser.get(section, key)
return default
- @staticmethod
- def make_ip_addr(ip, mask_len):
- try:
- return ipaddress.ip_interface(six.text_type('/'.join([ip, mask_len])))
- except ValueError:
- # None so we can skip later
- return None
-
@classmethod
def validate_ip_and_prefixlen(cls, ip_addr, prefixlen):
- ip_addr = cls.make_ip_addr(ip_addr, prefixlen)
+ ip_addr = utils.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):
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)
self.tmp_file = os.path.join("/tmp", tmp_file)
self.pktq_out_os = []
self.socket = socket
- self.start_core = ""
+ self.start_core = 1
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()
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.flows = None
+ self.pktq_out = []
@staticmethod
def gen_core(core):
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')
- timer_tpl['core'] = self.gen_core(self.start_core)
+ timer_tpl['core'] = self.gen_core(0)
self.update_write_parser(timer_tpl)
- self.start_core += 1
def get_config_tpl_data(self, type_value):
for section in self.read_parser.sections():
def init_write_parser_template(self, type_value='ARPICMP'):
for section in self.read_parser.sections():
if type_value == self.parser_get(self.read_parser, section, 'type', object()):
- self.start_core = self.read_parser.getint(section, 'core')
self.pipeline_counter = self.read_parser.getint(section, 'core')
self.txrx_pipeline = self.read_parser.getint(section, 'core')
return
return
try:
- self.start_core = 'h{}'.format(int(self.start_core))
+ self.start_core = '{}h'.format(int(self.start_core))
except ValueError:
self.start_core = int(self.start_core[:-1]) + 1
- @staticmethod
- def get_port_pairs(interfaces):
- port_pair_list = []
- networks = defaultdict(list)
- for private_intf in interfaces:
- vintf = private_intf['virtual-interface']
- networks[vintf['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))
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)
+ uplink_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 uplink_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]
- # port0_ip = ipaddress.ip_interface(six.text_type(
- # "%s/%s" % (interface["virtual-interface"]["local_ip"],
- # interface["virtual-interface"]["netmask"])))
- 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.ip.exploded),
- "port0_netmask_hex": ip_to_hex(dst_port0_ip.network.netmask.exploded),
- "port_num": port_num,
- # next hop is dst in this case
- "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)
+ arp_route_tbl_tmpl = "routeadd net {port_num} {port_dst_ip} 0x{port_netmask_hex}"
+
+ 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_port_ip = ipaddress.ip_interface(six.text_type(
+ "%s/%s" % (interface["dst_ip"], interface["netmask"])))
+
+ arp_vars = {
+ "port_netmask_hex": utils.ip_to_hex(dst_port_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
+ "port_dst_ip": str(dst_port_ip.ip),
+ }
+ return arp_route_tbl_tmpl.format(**arp_vars)
+
+ return '\n'.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)
self.swq += self.lb_count
swq_out_str = self.make_range_str('SWQ{}', self.swq, offset=self.lb_count)
self.swq += self.lb_count
- 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)
+ # ports_mac_list is disabled for some reason
+
+ # 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),
+ 'core': self.gen_core(0),
'pktq_in': swq_in_str,
'pktq_out': swq_out_str,
- 'ports_mac_list': ' '.join(mac_iter),
+ # we need to disable ports_mac_list?
+ # it looks like ports_mac_list is no longer required
+ # 'ports_mac_list': ' '.join(mac_iter),
'pktq_in_prv': ' '.join(pktq_in_iter),
'prv_to_pub_map': self.set_priv_to_pub_mapping(),
- 'arp_route_tbl': self.generate_arp_route_tbl(),
- # can't use empty string, defaul to ()
- 'nd_route_tbl': "()",
}
self.pktq_out_os = swq_out_str.split(' ')
- # why?
+ # HWLB is a run to complition. So override the pktq_in/pktq_out
if self.lb_config == self.HW_LB:
- arpicmp_data['pktq_in'] = swq_in_str
self.swq = 0
+ swq_in_str = \
+ self.make_range_str('SWQ{}', self.swq,
+ offset=(self.lb_count * self.worker_threads))
+ arpicmp_data['pktq_in'] = swq_in_str
+ # WA: Since port_pairs will not be populated during arp pipeline
+ self.port_pairs = self.port_pair_list
+ port_iter = \
+ self.make_port_pairs_iter(self.float_x_plus_one_tenth_of_y, [self.mul])
+ pktq_out = self.make_str('TXQ{}', port_iter)
+ arpicmp_data['pktq_out'] = pktq_out
+
return arpicmp_data
- def generate_final_txrx_data(self):
+ def generate_final_txrx_data(self, core=0):
swq_start = self.swq - self.ports_len * self.worker_threads
txq_start = 0
'pktq_in': swq_str,
'pktq_out': txq_str,
'pipeline_txrx_type': 'TXTX',
- 'core': self.gen_core(self.start_core),
+ 'core': self.gen_core(core),
}
pktq_in = rxtx_data['pktq_in']
pktq_in = '{0} {1}'.format(pktq_in, self.pktq_out_os[self.lb_index - 1])
'core': self.gen_core(self.start_core),
}
self.pipeline_counter += 1
- return txrx_data
+ return self.start_core, txrx_data
def generate_lb_data(self):
pktq_in = self.make_range_str('SWQ{}', self.swq, offset=self.ports_len)
self.arpicmp_tpl.update(arpicmp_data)
self.update_write_parser(self.arpicmp_tpl)
- self.start_core += 1
if self.vnf_type == 'CGNAPT':
self.pipeline_counter += 1
self.update_timer()
+ if self.lb_config == 'HW':
+ self.start_core = 1
+
for lb in self.lb_to_port_pair_mapping:
self.lb_index = lb
self.mul = 0
self.ports_len = port_pair_count * 2
self.set_priv_que_handler()
if self.lb_config == 'SW':
- txrx_data = self.generate_initial_txrx_data()
+ core, txrx_data = self.generate_initial_txrx_data()
self.txrx_tpl.update(txrx_data)
self.update_write_parser(self.txrx_tpl)
self.start_core += 1
self.update_write_parser(self.loadb_tpl)
self.start_core += 1
- for i in range(self.worker_threads):
+ for _ in range(self.worker_threads):
vnf_data = self.generate_vnf_data()
if not self.vnf_tpl:
self.vnf_tpl = {}
self.generate_next_core_id()
if self.lb_config == 'SW':
- txrx_data = self.generate_final_txrx_data()
+ txrx_data = self.generate_final_txrx_data(core)
self.txrx_tpl.update(txrx_data)
self.update_write_parser(self.txrx_tpl)
- self.start_core += 1
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()
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, [])
def generate_arp_config(self):
arp_config = []
- for port_pair in self.port_pair_list:
- for port in port_pair:
- gateway = self.get_ports_gateway(port)
- # omit entries with no gateway
- if not gateway:
- continue
- dst_mac = self.interfaces[int(port[-1])]["virtual-interface"]["dst_mac"]
- arp_config.append((port[-1], gateway, 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:
- gateway6 = self.get_ports_gateway6(port)
- # omit entries with no gateway
- if not gateway6:
- continue
- dst_mac6 = self.interfaces[int(port[-1])]["virtual-interface"]["dst_mac"]
- arp_config6.append((port[-1], gateway6, 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])
-
- if self.vnf_type == "VFW":
- template = FW_ACTION_TEMPLATE
- else:
- template = ACTION_TEMPLATE
-
- return ''.join((template.format(port) for port in port_list))
-
- def get_ip_from_port(self, port):
- return self.make_ip_addr(self.get_ports_gateway(port), self.get_netmask_gateway(port))
-
- def get_ip_and_prefixlen_from_ip_of_port(self, port):
- ip_addr = self.get_ip_from_port(port)
- # handle cases with no gateway
- if ip_addr:
- return ip_addr.ip.exploded, ip_addr.network.prefixlen
- else:
- return None, None
-
- def generate_rule_config(self):
- cmd = 'acl' if self.vnf_type == "ACL" else "vfw"
- rules_config = self.rules if self.rules else ''
- 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])
-
- src_ip, src_prefix_len = self.get_ip_and_prefixlen_from_ip_of_port(port_pair[0])
- dst_ip, dst_prefix_len = self.get_ip_and_prefixlen_from_ip_of_port(port_pair[1])
- # ignore entires with empty values
- if all((src_ip, src_prefix_len, dst_ip, dst_prefix_len)):
- new_rules.append((cmd, self.txrx_pipeline, src_ip, src_prefix_len,
- dst_ip, dst_prefix_len, dst_port))
- new_rules.append((cmd, self.txrx_pipeline, dst_ip, dst_prefix_len,
- src_ip, src_prefix_len, src_port))
-
- src_ip = self.get_ports_gateway6(port_pair[0])
- src_prefix_len = self.get_netmask_gateway6(port_pair[0])
- dst_ip = self.get_ports_gateway6(port_pair[1])
- dst_prefix_len = self.get_netmask_gateway6(port_pair[0])
- # ignore entires with empty values
- if all((src_ip, src_prefix_len, dst_ip, dst_prefix_len)):
- new_ipv6_rules.append((cmd, self.txrx_pipeline, src_ip, src_prefix_len,
- dst_ip, dst_prefix_len, dst_port))
- new_ipv6_rules.append((cmd, self.txrx_pipeline, dst_ip, dst_prefix_len,
- src_ip, src_prefix_len, src_port))
-
- acl_apply = "\np %s applyruleset" % cmd
- new_rules_config = '\n'.join(pattern.format(*values) for values
- in chain(new_rules, new_ipv6_rules))
- return ''.join([rules_config, new_rules_config, acl_apply])
+ def get_flows_config(self):
+ return self.flows if self.flows else ''
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(),
'arp_config': self.generate_arp_config(),
- 'arp_config6': self.generate_arp_config6(),
- 'actions': '',
- 'rules': '',
+ # disable IPv6 for now
+ # 'arp_config6': self.generate_arp_config6(),
+ 'arp_config6': "",
+ 'arp_route_tbl': self.generate_arp_route_tbl(),
+ 'arp_route_tbl6': "",
+ 'flows': self.get_flows_config()
}
-
- if self.vnf_type in ('ACL', 'VFW'):
- script_data.update({
- 'actions': self.generate_action_config(),
- 'rules': self.generate_rule_config(),
- })
-
return script_data
- def generate_script(self, vnfd, rules=None):
+ def generate_script(self, vnfd, flows=None):
self.vnfd = vnfd
- self.rules = rules
+ self.flows = flows
script_data = self.generate_script_data()
script = SCRIPT_TPL.format(**script_data)
if self.lb_config == self.HW_LB:
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