dpdk_setup_ports.py revision 129a116b
1#! /usr/bin/python
2# hhaim
3import sys
4import os
5python_ver = 'python%s' % sys.version_info[0]
6yaml_path = os.path.join('external_libs', 'pyyaml-3.11', python_ver)
7if yaml_path not in sys.path:
8    sys.path.append(yaml_path)
9import yaml
10import dpdk_nic_bind
11import re
12import argparse
13import copy
14import shlex
15import traceback
16from collections import defaultdict, OrderedDict
17from distutils.util import strtobool
18import subprocess
19import platform
20
21# exit code is Important should be
22# -1 : don't continue
23# 0  : no errors - no need to load mlx share object
24# 32  : no errors - mlx share object should be loaded
25MLX_EXIT_CODE = 32
26
27class VFIOBindErr(Exception): pass
28
29PATH_ARR = os.getenv('PATH', '').split(':')
30for path in ['/usr/local/sbin', '/usr/sbin', '/sbin']:
31    if path not in PATH_ARR:
32        PATH_ARR.append(path)
33os.environ['PATH'] = ':'.join(PATH_ARR)
34
35class ConfigCreator(object):
36    mandatory_interface_fields = ['Slot_str', 'Device_str', 'NUMA']
37    _2hex_re = '[\da-fA-F]{2}'
38    mac_re = re.compile('^({0}:){{5}}{0}$'.format(_2hex_re))
39
40    # cpu_topology - dict: physical processor -> physical core -> logical processing unit (thread)
41    # interfaces - array of dicts per interface, should include "mandatory_interface_fields" values
42    def __init__(self, cpu_topology, interfaces, include_lcores = [], exclude_lcores = [], only_first_thread = False, zmq_rpc_port = None, zmq_pub_port = None, prefix = None, ignore_numa = False):
43        self.cpu_topology = copy.deepcopy(cpu_topology)
44        self.interfaces   = copy.deepcopy(interfaces)
45        del cpu_topology
46        del interfaces
47        assert isinstance(self.cpu_topology, dict), 'Type of cpu_topology should be dict, got: %s' % type(self.cpu_topology)
48        assert len(self.cpu_topology.keys()) > 0, 'cpu_topology should contain at least one processor'
49        assert isinstance(self.interfaces, list), 'Type of interfaces should be list, got: %s' % type(list)
50        assert len(self.interfaces) % 2 == 0, 'Should be even number of interfaces, got: %s' % len(self.interfaces)
51        assert len(self.interfaces) >= 2, 'Should be at least two interfaces, got: %s' % len(self.interfaces)
52        assert isinstance(include_lcores, list), 'include_lcores should be list, got: %s' % type(include_lcores)
53        assert isinstance(exclude_lcores, list), 'exclude_lcores should be list, got: %s' % type(exclude_lcores)
54        assert len(self.interfaces) >= 2, 'Should be at least two interfaces, got: %s' % len(self.interfaces)
55        if only_first_thread:
56            for cores in self.cpu_topology.values():
57                for core in cores.keys():
58                    cores[core] = cores[core][:1]
59        include_lcores = [int(x) for x in include_lcores]
60        exclude_lcores = [int(x) for x in exclude_lcores]
61
62        self.has_zero_lcore = False
63        self.lcores_per_numa = {}
64        total_lcores = 0
65        for numa, cores in self.cpu_topology.items():
66            self.lcores_per_numa[numa] = {'main': [], 'siblings': [], 'all': []}
67            for core, lcores in cores.items():
68                total_lcores += len(lcores)
69                for lcore in list(lcores):
70                    if include_lcores and lcore not in include_lcores:
71                        cores[core].remove(lcore)
72                    if exclude_lcores and lcore in exclude_lcores:
73                        cores[core].remove(lcore)
74                if 0 in lcores:
75                    self.has_zero_lcore = True
76                    lcores.remove(0)
77                    self.lcores_per_numa[numa]['siblings'].extend(lcores)
78                else:
79                    self.lcores_per_numa[numa]['main'].extend(lcores[:1])
80                    self.lcores_per_numa[numa]['siblings'].extend(lcores[1:])
81                self.lcores_per_numa[numa]['all'].extend(lcores)
82
83        for interface in self.interfaces:
84            for mandatory_interface_field in ConfigCreator.mandatory_interface_fields:
85                if mandatory_interface_field not in interface:
86                    raise DpdkSetup("Expected '%s' field in interface dictionary, got: %s" % (mandatory_interface_field, interface))
87
88        Device_str = self._verify_devices_same_type(self.interfaces)
89        if '40Gb' in Device_str:
90            self.speed = 40
91        else:
92            self.speed = 10
93
94        minimum_required_lcores = len(self.interfaces) // 2 + 2
95        if total_lcores < minimum_required_lcores:
96            raise DpdkSetup('Your system should have at least %s cores for %s interfaces, and it has: %s.' %
97                    (minimum_required_lcores, len(self.interfaces), total_lcores))
98        interfaces_per_numa = defaultdict(int)
99
100        for i in range(0, len(self.interfaces), 2):
101            numa = self.interfaces[i]['NUMA']
102            if numa != self.interfaces[i+1]['NUMA'] and not ignore_numa:
103                raise DpdkSetup('NUMA of each pair of interfaces should be the same. Got NUMA %s for client interface %s, NUMA %s for server interface %s' %
104                        (numa, self.interfaces[i]['Slot_str'], self.interfaces[i+1]['NUMA'], self.interfaces[i+1]['Slot_str']))
105            interfaces_per_numa[numa] += 2
106
107        self.interfaces_per_numa = interfaces_per_numa
108        self.prefix              = prefix
109        self.zmq_pub_port        = zmq_pub_port
110        self.zmq_rpc_port        = zmq_rpc_port
111        self.ignore_numa         = ignore_numa
112
113    @staticmethod
114    def verify_mac(mac_string):
115        if not ConfigCreator.mac_re.match(mac_string):
116            raise DpdkSetup('MAC address should be in format of 12:34:56:78:9a:bc, got: %s' % mac_string)
117        return mac_string.lower()
118
119    @staticmethod
120    def _exit_if_bad_ip(ip):
121        if not ConfigCreator._verify_ip(ip):
122            raise DpdkSetup("Got bad IP %s" % ip)
123
124    @staticmethod
125    def _verify_ip(ip):
126        a = ip.split('.')
127        if len(a) != 4:
128            return False
129        for x in a:
130            if not x.isdigit():
131                return False
132            i = int(x)
133            if i < 0 or i > 255:
134                return False
135        return True
136
137    @staticmethod
138    def _verify_devices_same_type(interfaces_list):
139        Device_str = interfaces_list[0]['Device_str']
140        for interface in interfaces_list:
141            if Device_str != interface['Device_str']:
142                raise DpdkSetup('Interfaces should be of same type, got:\n\t* %s\n\t* %s' % (Device_str, interface['Device_str']))
143        return Device_str
144
145    def create_config(self, filename = None, print_config = False):
146        config_str = '### Config file generated by dpdk_setup_ports.py ###\n\n'
147        config_str += '- port_limit: %s\n' % len(self.interfaces)
148        config_str += '  version: 2\n'
149        config_str += "  interfaces: ['%s']\n" % "', '".join([interface['Slot_str'] for interface in self.interfaces])
150        if self.speed > 10:
151            config_str += '  port_bandwidth_gb: %s\n' % self.speed
152        if self.prefix:
153            config_str += '  prefix: %s\n' % self.prefix
154        if self.zmq_pub_port:
155            config_str += '  zmq_pub_port: %s\n' % self.zmq_pub_port
156        if self.zmq_rpc_port:
157            config_str += '  zmq_rpc_port: %s\n' % self.zmq_rpc_port
158        config_str += '  port_info:\n'
159        for index, interface in enumerate(self.interfaces):
160            if 'ip' in interface:
161                self._exit_if_bad_ip(interface['ip'])
162                self._exit_if_bad_ip(interface['def_gw'])
163                config_str += ' '*6 + '- ip: %s\n' % interface['ip']
164                config_str += ' '*8 + 'default_gw: %s\n' % interface['def_gw']
165            else:
166                config_str += ' '*6 + '- dest_mac: %s' % self.verify_mac(interface['dest_mac'])
167                if interface.get('loopback_dest'):
168                    config_str += " # MAC OF LOOPBACK TO IT'S DUAL INTERFACE\n"
169                else:
170                    config_str += '\n'
171                config_str += ' '*8 + 'src_mac:  %s\n' % self.verify_mac(interface['src_mac'])
172            if index % 2:
173                config_str += '\n' # dual if barrier
174
175        if not self.ignore_numa:
176            config_str += '  platform:\n'
177            if len(self.interfaces_per_numa.keys()) == 1 and -1 in self.interfaces_per_numa: # VM, use any cores
178                lcores_pool = sorted([lcore for lcores in self.lcores_per_numa.values() for lcore in lcores['all']])
179                config_str += ' '*6 + 'master_thread_id: %s\n' % (0 if self.has_zero_lcore else lcores_pool.pop(0))
180                config_str += ' '*6 + 'latency_thread_id: %s\n' % lcores_pool.pop(0)
181                lcores_per_dual_if = int(len(lcores_pool) * 2 / len(self.interfaces))
182                config_str += ' '*6 + 'dual_if:\n'
183                for i in range(0, len(self.interfaces), 2):
184                    lcores_for_this_dual_if = list(map(str, sorted(lcores_pool[:lcores_per_dual_if])))
185                    lcores_pool = lcores_pool[lcores_per_dual_if:]
186                    if not lcores_for_this_dual_if:
187                        raise DpdkSetup('lcores_for_this_dual_if is empty (internal bug, please report with details of setup)')
188                    config_str += ' '*8 + '- socket: 0\n'
189                    config_str += ' '*10 + 'threads: [%s]\n\n' % ','.join(lcores_for_this_dual_if)
190            else:
191                # we will take common minimum among all NUMAs, to satisfy all
192                lcores_per_dual_if = 99
193                extra_lcores = 1 if self.has_zero_lcore else 2
194                # worst case 3 iterations, to ensure master and "rx" have cores left
195                while (lcores_per_dual_if * sum(self.interfaces_per_numa.values()) / 2) + extra_lcores > sum([len(lcores['all']) for lcores in self.lcores_per_numa.values()]):
196                    lcores_per_dual_if -= 1
197                    for numa, lcores_dict in self.lcores_per_numa.items():
198                        if not self.interfaces_per_numa[numa]:
199                            continue
200                        lcores_per_dual_if = min(lcores_per_dual_if, int(2 * len(lcores_dict['all']) / self.interfaces_per_numa[numa]))
201                lcores_pool = copy.deepcopy(self.lcores_per_numa)
202                # first, allocate lcores for dual_if section
203                dual_if_section = ' '*6 + 'dual_if:\n'
204                for i in range(0, len(self.interfaces), 2):
205                    numa = self.interfaces[i]['NUMA']
206                    dual_if_section += ' '*8 + '- socket: %s\n' % numa
207                    lcores_for_this_dual_if  = lcores_pool[numa]['all'][:lcores_per_dual_if]
208                    lcores_pool[numa]['all'] = lcores_pool[numa]['all'][lcores_per_dual_if:]
209                    for lcore in lcores_for_this_dual_if:
210                        if lcore in lcores_pool[numa]['main']:
211                            lcores_pool[numa]['main'].remove(lcore)
212                        elif lcore in lcores_pool[numa]['siblings']:
213                            lcores_pool[numa]['siblings'].remove(lcore)
214                        else:
215                            raise DpdkSetup('lcore not in main nor in siblings list (internal bug, please report with details of setup)')
216                    if not lcores_for_this_dual_if:
217                        raise DpdkSetup('Not enough cores at NUMA %s. This NUMA has %s processing units and %s interfaces.' % (numa, len(self.lcores_per_numa[numa]), self.interfaces_per_numa[numa]))
218                    dual_if_section += ' '*10 + 'threads: [%s]\n\n' % ','.join(list(map(str, sorted(lcores_for_this_dual_if))))
219
220                # take the cores left to master and rx
221                mains_left = [lcore for lcores in lcores_pool.values() for lcore in lcores['main']]
222                siblings_left = [lcore for lcores in lcores_pool.values() for lcore in lcores['siblings']]
223                if mains_left:
224                    rx_core = mains_left.pop(0)
225                else:
226                    rx_core = siblings_left.pop(0)
227                if self.has_zero_lcore:
228                    master_core = 0
229                elif mains_left:
230                    master_core = mains_left.pop(0)
231                else:
232                    master_core = siblings_left.pop(0)
233                config_str += ' '*6 + 'master_thread_id: %s\n' % master_core
234                config_str += ' '*6 + 'latency_thread_id: %s\n' % rx_core
235                # add the dual_if section
236                config_str += dual_if_section
237
238        # verify config is correct YAML format
239        try:
240            yaml.safe_load(config_str)
241        except Exception as e:
242            raise DpdkSetup('Could not create correct yaml config.\nGenerated YAML:\n%s\nEncountered error:\n%s' % (config_str, e))
243
244        if print_config:
245            print(config_str)
246        if filename:
247            if os.path.exists(filename):
248                if not dpdk_nic_bind.confirm('File %s already exist, overwrite? (y/N)' % filename):
249                    print('Skipping.')
250                    return config_str
251            with open(filename, 'w') as f:
252                f.write(config_str)
253            print('Saved to %s.' % filename)
254        return config_str
255
256# only load igb_uio if it's available
257def load_igb_uio():
258    loaded_mods = dpdk_nic_bind.get_loaded_modules()
259    if 'igb_uio' in loaded_mods:
260        return True
261    if 'uio' not in loaded_mods:
262        ret = os.system('modprobe uio')
263        if ret:
264            return False
265    km = './ko/%s/igb_uio.ko' % dpdk_nic_bind.kernel_ver
266    if os.path.exists(km):
267        return os.system('insmod %s' % km) == 0
268
269# try to compile igb_uio if it's missing
270def compile_and_load_igb_uio():
271    loaded_mods = dpdk_nic_bind.get_loaded_modules()
272    if 'igb_uio' in loaded_mods:
273        return
274    if 'uio' not in loaded_mods:
275        ret = os.system('modprobe uio')
276        if ret:
277            print('Failed inserting uio module, please check if it is installed')
278            sys.exit(-1)
279    km = './ko/%s/igb_uio.ko' % dpdk_nic_bind.kernel_ver
280    if not os.path.exists(km):
281        print("ERROR: We don't have precompiled igb_uio.ko module for your kernel version")
282        print('Will try compiling automatically.')
283        try:
284            subprocess.check_output('make', cwd = './ko/src', stderr = subprocess.STDOUT)
285            subprocess.check_output(['make', 'install'], cwd = './ko/src', stderr = subprocess.STDOUT)
286            print('\nSuccess.')
287        except Exception as e:
288            print('\nAutomatic compilation failed: (%s)' % e)
289            print('You can try compiling yourself, using the following commands:')
290            print('  $cd ko/src')
291            print('  $make')
292            print('  $make install')
293            print('  $cd -')
294            print('Then, try to run TRex again.')
295            print('Note: you might need additional Linux packages for that:')
296            print('  * yum based (Fedora, CentOS, RedHat):')
297            print('        sudo yum install kernel-devel-`uname -r`')
298            print('        sudo yum group install "Development tools"')
299            print('  * apt based (Ubuntu):')
300            print('        sudo apt install linux-headers-`uname -r`')
301            print('        sudo apt install build-essential')
302            sys.exit(-1)
303    ret = os.system('insmod %s' % km)
304    if ret:
305        print('Failed inserting igb_uio module')
306        sys.exit(-1)
307
308class map_driver(object):
309    args=None;
310    cfg_file='/etc/trex_cfg.yaml'
311    parent_args = None
312
313class DpdkSetup(Exception):
314    pass
315
316class CIfMap:
317
318    def __init__(self, cfg_file):
319        self.m_cfg_file =cfg_file;
320        self.m_cfg_dict={};
321        self.m_devices={};
322        self.m_is_mellanox_mode=False;
323
324    def dump_error (self,err):
325        s="""%s
326From this TRex version a configuration file must exist in /etc/ folder "
327The name of the configuration file should be /etc/trex_cfg.yaml "
328The minimum configuration file should include something like this
329- version       : 2 # version 2 of the configuration file
330  interfaces    : ["03:00.0","03:00.1","13:00.1","13:00.0"]  # list of the interfaces to bind run ./dpdk_nic_bind.py --status to see the list
331  port_limit      : 2 # number of ports to use valid is 2,4,6,8,10,12
332
333example of already bind devices
334
335$ ./dpdk_nic_bind.py --status
336
337Network devices using DPDK-compatible driver
338============================================
3390000:03:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused=
3400000:03:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused=
3410000:13:00.0 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused=
3420000:13:00.1 '82599ES 10-Gigabit SFI/SFP+ Network Connection' drv=igb_uio unused=
343
344Network devices using kernel driver
345===================================
3460000:02:00.0 '82545EM Gigabit Ethernet Controller (Copper)' if=eth2 drv=e1000 unused=igb_uio *Active*
347
348Other network devices
349=====================
350
351
352          """ % (err);
353        return s;
354
355
356    def raise_error  (self,err):
357        s= self.dump_error (err)
358        raise DpdkSetup(s)
359
360    def set_only_mellanox_nics(self):
361        self.m_is_mellanox_mode=True;
362
363    def get_only_mellanox_nics(self):
364        return self.m_is_mellanox_mode
365
366
367    def read_pci (self,pci_id,reg_id):
368        out=subprocess.check_output(['setpci', '-s',pci_id, '%s.w' %(reg_id)])
369        out=out.decode(errors='replace');
370        return (out.strip());
371
372    def write_pci (self,pci_id,reg_id,val):
373        out=subprocess.check_output(['setpci','-s',pci_id, '%s.w=%s' %(reg_id,val)])
374        out=out.decode(errors='replace');
375        return (out.strip());
376
377    def tune_mlx5_device (self,pci_id):
378        # set PCIe Read to 1024 and not 512 ... need to add it to startup s
379        val=self.read_pci (pci_id,68)
380        if val[0]!='3':
381            val='3'+val[1:]
382            self.write_pci (pci_id,68,val)
383            assert(self.read_pci (pci_id,68)==val);
384
385    def get_mtu_mlx5 (self,dev_id):
386        if len(dev_id)>0:
387            out=subprocess.check_output(['ifconfig', dev_id])
388            out=out.decode(errors='replace');
389            obj=re.search(r'MTU:(\d+)',out,flags=re.MULTILINE|re.DOTALL);
390            if obj:
391                return int(obj.group(1));
392            else:
393                obj=re.search(r'mtu (\d+)',out,flags=re.MULTILINE|re.DOTALL);
394                if obj:
395                    return int(obj.group(1));
396                else:
397                    return -1
398
399    def set_mtu_mlx5 (self,dev_id,new_mtu):
400        if len(dev_id)>0:
401            out=subprocess.check_output(['ifconfig', dev_id,'mtu',str(new_mtu)])
402            out=out.decode(errors='replace');
403
404
405    def set_max_mtu_mlx5_device(self,dev_id):
406        mtu=9*1024+22
407        dev_mtu=self.get_mtu_mlx5 (dev_id);
408        if (dev_mtu>0) and (dev_mtu!=mtu):
409            self.set_mtu_mlx5(dev_id,mtu);
410            if self.get_mtu_mlx5(dev_id) != mtu:
411                print("Could not set MTU to %d" % mtu)
412                exit(-1);
413
414
415    def disable_flow_control_mlx5_device (self,dev_id):
416
417           if len(dev_id)>0:
418               my_stderr = open("/dev/null","wb")
419               cmd ='ethtool -A '+dev_id + ' rx off tx off '
420               subprocess.call(cmd, stdout=my_stderr,stderr=my_stderr, shell=True)
421               my_stderr.close();
422
423    def check_ofed_version (self):
424        ofed_info='/usr/bin/ofed_info'
425
426        ofed_ver_re = re.compile('.*[-](\d)[.](\d)[-].*')
427
428        ofed_ver= 40
429        ofed_ver_show= '4.0'
430
431
432        if not os.path.isfile(ofed_info):
433            print("OFED %s is not installed on this setup" % ofed_info)
434            exit(-1);
435
436        try:
437          out = subprocess.check_output([ofed_info])
438        except Exception as e:
439            print("OFED %s can't run " % (ofed_info))
440            exit(-1);
441
442        lines=out.splitlines();
443
444        if len(lines)>1:
445            m= ofed_ver_re.match(str(lines[0]))
446            if m:
447                ver=int(m.group(1))*10+int(m.group(2))
448                if ver < ofed_ver:
449                  print("installed OFED version is '%s' should be at least '%s' and up" % (lines[0],ofed_ver_show))
450                  exit(-1);
451            else:
452                print("not found valid  OFED version '%s' " % (lines[0]))
453                exit(-1);
454
455
456    def verify_ofed_os(self):
457        err_msg = 'Warning: Mellanox NICs where tested only with RedHat/CentOS 7.2\n'
458        err_msg += 'Correct usage with other Linux distributions is not guaranteed.'
459        try:
460            dist = platform.dist()
461            if dist[0] not in ('redhat', 'centos') or not dist[1].startswith('7.2'):
462                print(err_msg)
463        except Exception as e:
464            print('Error while determining OS type: %s' % e)
465
466    def load_config_file (self):
467
468        fcfg=self.m_cfg_file
469
470        if not os.path.isfile(fcfg) :
471            self.raise_error ("There is no valid configuration file %s\n" % fcfg)
472
473        try:
474          stream = open(fcfg, 'r')
475          self.m_cfg_dict= yaml.safe_load(stream)
476        except Exception as e:
477          print(e);
478          raise e
479
480        stream.close();
481        cfg_dict = self.m_cfg_dict[0]
482        if 'version' not in cfg_dict:
483            raise DpdkSetup("Configuration file %s is old, it should include version field\n" % fcfg )
484
485        if int(cfg_dict['version'])<2 :
486            raise DpdkSetup("Configuration file %s is old, expected version 2, got: %s\n" % (fcfg, cfg_dict['version']))
487
488        if 'interfaces' not in self.m_cfg_dict[0]:
489            raise DpdkSetup("Configuration file %s is old, it should include interfaces field with even number of elements" % fcfg)
490
491        if_list=self.m_cfg_dict[0]['interfaces']
492        l=len(if_list);
493        if l > 16:
494            raise DpdkSetup("Configuration file %s should include interfaces field with maximum 16 elements, got: %s." % (fcfg,l))
495        if l % 2:
496            raise DpdkSetup("Configuration file %s should include even number of interfaces " % (fcfg,l))
497        if 'port_limit' in cfg_dict and cfg_dict['port_limit'] > len(if_list):
498            raise DpdkSetup('Error: port_limit should not be higher than number of interfaces in config file: %s\n' % fcfg)
499
500
501    def do_bind_all(self, drv, pci, force = False):
502        assert type(pci) is list
503        cmd = '{ptn} dpdk_nic_bind.py --bind={drv} {pci} {frc}'.format(
504            ptn = sys.executable,
505            drv = drv,
506            pci = ' '.join(pci),
507            frc = '--force' if force else '')
508        print(cmd)
509        return os.system(cmd)
510
511    # pros: no need to compile .ko per Kernel version
512    # cons: need special config/hw (not always works)
513    def try_bind_to_vfio_pci(self, to_bind_list):
514        krnl_params_file = '/proc/cmdline'
515        if not os.path.exists(krnl_params_file):
516            raise VFIOBindErr('Could not find file with Kernel boot parameters: %s' % krnl_params_file)
517        with open(krnl_params_file) as f:
518            krnl_params = f.read()
519        if 'iommu=' not in krnl_params:
520            raise VFIOBindErr('vfio-pci is not an option here')
521        if 'vfio_pci' not in dpdk_nic_bind.get_loaded_modules():
522            ret = os.system('modprobe vfio_pci')
523            if ret:
524                raise VFIOBindErr('Could not load vfio_pci')
525        ret = self.do_bind_all('vfio-pci', to_bind_list)
526        if ret:
527            raise VFIOBindErr('Binding to vfio_pci failed')
528
529
530    def pci_name_to_full_name (self,pci_name):
531          c='[0-9A-Fa-f]';
532          sp='[:]'
533          s_short=c+c+sp+c+c+'[.]'+c;
534          s_full=c+c+c+c+sp+s_short
535          re_full = re.compile(s_full)
536          re_short = re.compile(s_short)
537
538          if re_short.match(pci_name):
539              return '0000:'+pci_name
540
541          if re_full.match(pci_name):
542              return pci_name
543
544          err=" %s is not a valid pci address \n" %pci_name;
545          raise DpdkSetup(err)
546
547
548    def run_dpdk_lspci (self):
549        dpdk_nic_bind.get_nic_details()
550        self.m_devices= dpdk_nic_bind.devices
551
552    def do_run (self,only_check_all_mlx=False):
553        """ return the number of mellanox drivers"""
554
555        self.run_dpdk_lspci ()
556        self.load_config_file()
557        if (map_driver.parent_args.dump_interfaces is None or
558                    (map_driver.parent_args.dump_interfaces == [] and
559                            map_driver.parent_args.cfg)):
560            if_list=self.m_cfg_dict[0]['interfaces']
561        else:
562            if_list = map_driver.parent_args.dump_interfaces
563            if not if_list:
564                for dev in self.m_devices.values():
565                    if dev.get('Driver_str') in dpdk_nic_bind.dpdk_drivers + dpdk_nic_bind.dpdk_and_kernel:
566                        if_list.append(dev['Slot'])
567
568        if_list = list(map(self.pci_name_to_full_name, if_list))
569
570
571        # check how many mellanox cards we have
572        Mellanox_cnt=0;
573        for key in if_list:
574            if key not in self.m_devices:
575                err=" %s does not exist " %key;
576                raise DpdkSetup(err)
577
578            if 'Vendor_str' not in self.m_devices[key]:
579                err=" %s does not have Vendor_str " %key;
580                raise DpdkSetup(err)
581
582            if 'Mellanox' in self.m_devices[key]['Vendor_str']:
583                Mellanox_cnt += 1
584
585
586        if not map_driver.parent_args.dump_interfaces:
587            if (Mellanox_cnt > 0) and (Mellanox_cnt != len(if_list)):
588               err=" All driver should be from one vendor. you have at least one driver from Mellanox but not all ";
589               raise DpdkSetup(err)
590            if Mellanox_cnt > 0:
591                self.set_only_mellanox_nics()
592
593        if self.get_only_mellanox_nics():
594            if not map_driver.parent_args.no_ofed_check:
595                self.verify_ofed_os()
596                self.check_ofed_version()
597
598            for key in if_list:
599                if 'Virtual' not in self.m_devices[key]['Device_str']:
600                    pci_id = self.m_devices[key]['Slot_str']
601                    self.tune_mlx5_device(pci_id)
602                if 'Interface' in self.m_devices[key]:
603                    dev_id=self.m_devices[key]['Interface']
604                    self.disable_flow_control_mlx5_device (dev_id)
605                    self.set_max_mtu_mlx5_device(dev_id)
606
607
608        if only_check_all_mlx:
609            if Mellanox_cnt > 0:
610                exit(MLX_EXIT_CODE);
611            else:
612                exit(0);
613
614        if if_list and map_driver.args.parent and self.m_cfg_dict[0].get('enable_zmq_pub', True):
615            publisher_port = self.m_cfg_dict[0].get('zmq_pub_port', 4500)
616            pid = dpdk_nic_bind.get_tcp_port_usage(publisher_port)
617            if pid:
618                cmdline = dpdk_nic_bind.read_pid_cmdline(pid)
619                print('ZMQ port is used by following process:\npid: %s, cmd: %s' % (pid, cmdline))
620                if not dpdk_nic_bind.confirm('Ignore and proceed (y/N):'):
621                    sys.exit(-1)
622
623        if map_driver.parent_args.stl and not map_driver.parent_args.no_scapy_server:
624            try:
625                master_core = self.m_cfg_dict[0]['platform']['master_thread_id']
626            except:
627                master_core = 0
628            ret = os.system('%s scapy_daemon_server restart -c %s' % (sys.executable, master_core))
629            if ret:
630                print("Could not start scapy_daemon_server, which is needed by GUI to create packets.\nIf you don't need it, use --no-scapy-server flag.")
631                sys.exit(-1)
632
633
634        to_bind_list = []
635        for key in if_list:
636            if key not in self.m_devices:
637                err=" %s does not exist " %key;
638                raise DpdkSetup(err)
639
640            if self.m_devices[key].get('Driver_str') not in (dpdk_nic_bind.dpdk_drivers + dpdk_nic_bind.dpdk_and_kernel):
641                to_bind_list.append(key)
642
643        if to_bind_list:
644            if Mellanox_cnt:
645                ret = self.do_bind_all('mlx5_core', to_bind_list)
646                if ret:
647                    raise DpdkSetup('Unable to bind interfaces to driver mlx5_core.')
648                return MLX_EXIT_CODE
649            else:
650                # if igb_uio is ready, use it as safer choice, afterwards try vfio-pci
651                if load_igb_uio():
652                    print('Trying to bind to igb_uio ...')
653                    ret = self.do_bind_all('igb_uio', to_bind_list)
654                    if ret:
655                        raise DpdkSetup('Unable to bind interfaces to driver igb_uio.') # module present, loaded, but unable to bind
656                    return
657
658                try:
659                    print('Trying to bind to vfio-pci ...')
660                    self.try_bind_to_vfio_pci(to_bind_list)
661                    return
662                except VFIOBindErr as e:
663                    pass
664                    #print(e)
665
666                print('Trying to compile and bind to igb_uio ...')
667                compile_and_load_igb_uio()
668                ret = self.do_bind_all('igb_uio', to_bind_list)
669                if ret:
670                    raise DpdkSetup('Unable to bind interfaces to driver igb_uio.')
671        elif Mellanox_cnt:
672            return MLX_EXIT_CODE
673
674    def do_return_to_linux(self):
675        if not self.m_devices:
676            self.run_dpdk_lspci()
677        dpdk_interfaces = []
678        check_drivers = set()
679        for device in self.m_devices.values():
680            if device.get('Driver_str') in dpdk_nic_bind.dpdk_drivers:
681                dpdk_interfaces.append(device['Slot'])
682                check_drivers.add(device['Driver_str'])
683        if not dpdk_interfaces:
684            print('No DPDK bound interfaces.')
685            return
686        any_driver_used = False
687        for driver in check_drivers:
688            if dpdk_nic_bind.is_module_used(driver):
689                any_driver_used = True
690        if any_driver_used:
691            pid = dpdk_nic_bind.get_pid_using_pci(dpdk_interfaces)
692            if pid:
693                cmdline = dpdk_nic_bind.read_pid_cmdline(pid)
694                print('DPDK interfaces are in use. Unbinding them might cause following process to hang:\npid: %s, cmd: %s' % (pid, cmdline))
695                if not dpdk_nic_bind.confirm('Confirm (y/N):'):
696                    sys.exit(-1)
697
698        # DPDK => Linux
699        drivers_table = {
700            'net_ixgbe': 'ixgbe',
701            'net_ixgbe_vf': 'ixgbevf',
702            'net_e1000_igb': 'igb',
703            'net_i40e': 'i40e',
704            'net_i40e_vf': 'i40evf',
705            'net_e1000_em': 'e1000',
706            'net_vmxnet3': 'vmxnet3',
707            'net_virtio': 'virtio-pci',
708            'net_enic': 'enic',
709        }
710        nics_info = dpdk_nic_bind.get_info_from_trex(dpdk_interfaces)
711        if not nics_info:
712            raise DpdkSetup('Could not determine interfaces information. Try to run manually: sudo ./t-rex-64 --dump-interfaces')
713        for pci, info in nics_info.items():
714            if pci not in self.m_devices:
715                raise DpdkSetup('Internal error: PCI %s is not found among devices' % pci)
716            dev = self.m_devices[pci]
717            if info['TRex_Driver'] not in drivers_table:
718                raise DpdkSetup("Got unknown driver '%s', description: %s" % (info['TRex_Driver'], dev['Device_str']))
719            linux_driver = drivers_table[info['TRex_Driver']]
720            if linux_driver not in dpdk_nic_bind.get_loaded_modules():
721                print("No Linux driver installed, or wrong module name: %s" % linux_driver)
722            else:
723                print('Returning to Linux %s' % pci)
724                dpdk_nic_bind.bind_one(pci, linux_driver, False)
725
726    def _get_cpu_topology(self):
727        cpu_topology_file = '/proc/cpuinfo'
728        # physical processor -> physical core -> logical processing units (threads)
729        cpu_topology = OrderedDict()
730        if not os.path.exists(cpu_topology_file):
731            raise DpdkSetup('File with CPU topology (%s) does not exist.' % cpu_topology_file)
732        with open(cpu_topology_file) as f:
733            for lcore in f.read().split('\n\n'):
734                if not lcore:
735                    continue
736                lcore_dict = OrderedDict()
737                for line in lcore.split('\n'):
738                    key, val = line.split(':', 1)
739                    lcore_dict[key.strip()] = val.strip()
740                if 'processor' not in lcore_dict:
741                    continue
742                numa = int(lcore_dict.get('physical id', -1))
743                if numa not in cpu_topology:
744                    cpu_topology[numa] = OrderedDict()
745                core = int(lcore_dict.get('core id', lcore_dict['processor']))
746                if core not in cpu_topology[numa]:
747                    cpu_topology[numa][core] = []
748                cpu_topology[numa][core].append(int(lcore_dict['processor']))
749        if not cpu_topology:
750            raise DpdkSetup('Could not determine CPU topology from %s' % cpu_topology_file)
751        return cpu_topology
752
753    # input: list of different descriptions of interfaces: index, pci, name etc.
754    # Binds to dpdk wanted interfaces, not bound to any driver.
755    # output: list of maps of devices in dpdk_* format (self.m_devices.values())
756    def _get_wanted_interfaces(self, input_interfaces, get_macs = True):
757        if type(input_interfaces) is not list:
758            raise DpdkSetup('type of input interfaces should be list')
759        if not len(input_interfaces):
760            raise DpdkSetup('Please specify interfaces to use in the config')
761        if len(input_interfaces) % 2:
762            raise DpdkSetup('Please specify even number of interfaces')
763        wanted_interfaces = []
764        sorted_pci = sorted(self.m_devices.keys())
765        for interface in input_interfaces:
766            dev = None
767            try:
768                interface = int(interface)
769                if interface < 0 or interface >= len(sorted_pci):
770                    raise DpdkSetup('Index of an interfaces should be in range 0:%s' % (len(sorted_pci) - 1))
771                dev = self.m_devices[sorted_pci[interface]]
772            except ValueError:
773                for d in self.m_devices.values():
774                    if interface in (d['Interface'], d['Slot'], d['Slot_str']):
775                        dev = d
776                        break
777            if not dev:
778                raise DpdkSetup('Could not find information about this interface: %s' % interface)
779            if dev in wanted_interfaces:
780                raise DpdkSetup('Interface %s is specified twice' % interface)
781            dev['Interface_argv'] = interface
782            wanted_interfaces.append(dev)
783
784        if get_macs:
785            unbound = []
786            dpdk_bound = []
787            for interface in wanted_interfaces:
788                if 'Driver_str' not in interface:
789                    unbound.append(interface['Slot'])
790                elif interface.get('Driver_str') in dpdk_nic_bind.dpdk_drivers:
791                    dpdk_bound.append(interface['Slot'])
792            if unbound or dpdk_bound:
793                for pci, info in dpdk_nic_bind.get_info_from_trex(unbound + dpdk_bound).items():
794                    if pci not in self.m_devices:
795                        raise DpdkSetup('Internal error: PCI %s is not found among devices' % pci)
796                    self.m_devices[pci].update(info)
797
798        return wanted_interfaces
799
800    def do_create(self):
801
802        ips = map_driver.args.ips
803        def_gws = map_driver.args.def_gws
804        dest_macs = map_driver.args.dest_macs
805        if map_driver.args.force_macs:
806            ip_config = False
807            if ips:
808                raise DpdkSetup("If using --force-macs, should not specify ips")
809            if def_gws:
810                raise DpdkSetup("If using --force-macs, should not specify default gateways")
811        elif ips:
812            ip_config = True
813            if not def_gws:
814                raise DpdkSetup("If specifying ips, must specify also def-gws")
815            if dest_macs:
816                raise DpdkSetup("If specifying ips, should not specify dest--macs")
817            if len(ips) != len(def_gws) or len(ips) != len(map_driver.args.create_interfaces):
818                raise DpdkSetup("Number of given IPs should equal number of given def-gws and number of interfaces")
819        else:
820            if dest_macs:
821                ip_config = False
822            else:
823                ip_config = True
824
825        # gather info about NICS from dpdk_nic_bind.py
826        if not self.m_devices:
827            self.run_dpdk_lspci()
828        wanted_interfaces = self._get_wanted_interfaces(map_driver.args.create_interfaces, get_macs = not ip_config)
829
830        for i, interface in enumerate(wanted_interfaces):
831            dual_index = i + 1 - (i % 2) * 2
832            if ip_config:
833                if isinstance(ips, list) and len(ips) > i:
834                    interface['ip'] = ips[i]
835                else:
836                    interface['ip'] = '.'.join([str(i+1) for _ in range(4)])
837                if isinstance(def_gws, list) and len(def_gws) > i:
838                    interface['def_gw'] = def_gws[i]
839                else:
840                    interface['def_gw'] = '.'.join([str(dual_index+1) for _ in range(4)])
841            else:
842                dual_if = wanted_interfaces[dual_index]
843                if 'MAC' not in interface:
844                    raise DpdkSetup('Could not determine MAC of interface: %s. Please verify with -t flag.' % interface['Interface_argv'])
845                if 'MAC' not in dual_if:
846                    raise DpdkSetup('Could not determine MAC of interface: %s. Please verify with -t flag.' % dual_if['Interface_argv'])
847                interface['src_mac'] = interface['MAC']
848                if isinstance(dest_macs, list) and len(dest_macs) > i:
849                    interface['dest_mac'] = dest_macs[i]
850                else:
851                    interface['dest_mac'] = dual_if['MAC']
852                    interface['loopback_dest'] = True
853
854        config = ConfigCreator(self._get_cpu_topology(), wanted_interfaces, include_lcores = map_driver.args.create_include, exclude_lcores = map_driver.args.create_exclude,
855                               only_first_thread = map_driver.args.no_ht, ignore_numa = map_driver.args.ignore_numa,
856                               prefix = map_driver.args.prefix, zmq_rpc_port = map_driver.args.zmq_rpc_port, zmq_pub_port = map_driver.args.zmq_pub_port)
857        if map_driver.args.output_config:
858            config.create_config(filename = map_driver.args.output_config)
859        else:
860            print('### Dumping config to screen, use -o flag to save to file')
861            config.create_config(print_config = True)
862
863    def do_interactive_create(self):
864        ignore_numa = False
865        cpu_topology = self._get_cpu_topology()
866        total_lcores = sum([len(lcores) for cores in cpu_topology.values() for lcores in cores.values()])
867        if total_lcores < 1:
868            raise DpdkSetup('Script could not determine number of cores of the system, exiting.')
869        elif total_lcores < 2:
870            if dpdk_nic_bind.confirm("You only have 1 core and can't run TRex at all. Ignore and continue? (y/N): "):
871                ignore_numa = True
872            else:
873                sys.exit(1)
874        elif total_lcores < 3:
875            if dpdk_nic_bind.confirm("You only have 2 cores and will be able to run only stateful without latency checks.\nIgnore and continue? (y/N): "):
876                ignore_numa = True
877            else:
878                sys.exit(1)
879
880        if map_driver.args.force_macs:
881            ip_based = False
882        elif dpdk_nic_bind.confirm("By default, IP based configuration file will be created. Do you want to use MAC based config? (y/N)"):
883            ip_based = False
884        else:
885            ip_based = True
886            ip_addr_digit = 1
887
888        if not self.m_devices:
889            self.run_dpdk_lspci()
890        dpdk_nic_bind.show_table(get_macs = not ip_based)
891        print('Please choose even number of interfaces from the list above, either by ID , PCI or Linux IF')
892        print('Stateful will use order of interfaces: Client1 Server1 Client2 Server2 etc. for flows.')
893        print('Stateless can be in any order.')
894        numa = None
895        for dev in self.m_devices.values():
896            if numa is None:
897                numa = dev['NUMA']
898            elif numa != dev['NUMA']:
899                print('For performance, try to choose each pair of interfaces to be on the same NUMA.')
900                break
901        while True:
902            try:
903                input = dpdk_nic_bind.read_line('Enter list of interfaces separated by space (for example: 1 3) : ')
904                create_interfaces = input.replace(',', ' ').replace(';', ' ').split()
905                wanted_interfaces = self._get_wanted_interfaces(create_interfaces)
906                ConfigCreator._verify_devices_same_type(wanted_interfaces)
907            except Exception as e:
908                print(e)
909                continue
910            break
911        print('')
912
913        for interface in wanted_interfaces:
914            if interface['Active']:
915                print('Interface %s is active. Using it by TRex might close ssh connections etc.' % interface['Interface_argv'])
916                if not dpdk_nic_bind.confirm('Ignore and continue? (y/N): '):
917                    sys.exit(-1)
918
919        for i, interface in enumerate(wanted_interfaces):
920            if not ip_based:
921                if 'MAC' not in interface:
922                    raise DpdkSetup('Could not determine MAC of interface: %s. Please verify with -t flag.' % interface['Interface_argv'])
923                interface['src_mac'] = interface['MAC']
924            dual_index = i + 1 - (i % 2) * 2
925            dual_int = wanted_interfaces[dual_index]
926            if not ignore_numa and interface['NUMA'] != dual_int['NUMA']:
927                print('NUMA is different at pair of interfaces: %s and %s. It will reduce performance.' % (interface['Interface_argv'], dual_int['Interface_argv']))
928                if dpdk_nic_bind.confirm('Ignore and continue? (y/N): '):
929                    ignore_numa = True
930                    print('')
931                else:
932                    return
933
934            if ip_based:
935                if ip_addr_digit % 2 == 0:
936                    dual_ip_digit = ip_addr_digit - 1
937                else:
938                    dual_ip_digit = ip_addr_digit + 1
939                ip = '.'.join([str(ip_addr_digit) for _ in range(4)])
940                def_gw= '.'.join([str(dual_ip_digit) for _ in range(4)])
941                ip_addr_digit += 1
942
943                print("For interface %s, assuming loopback to it's dual interface %s." % (interface['Interface_argv'], dual_int['Interface_argv']))
944                if dpdk_nic_bind.confirm("Putting IP %s, default gw %s Change it?(y/N)." % (ip, def_gw)):
945                    while True:
946                        ip = dpdk_nic_bind.read_line('Please enter IP address for interface %s: ' % interface['Interface_argv'])
947                        if not ConfigCreator._verify_ip(ip):
948                            print ("Bad IP address format")
949                        else:
950                            break
951                    while True:
952                        def_gw = dpdk_nic_bind.read_line('Please enter default gateway for interface %s: ' % interface['Interface_argv'])
953                        if not ConfigCreator._verify_ip(def_gw):
954                            print ("Bad IP address format")
955                        else:
956                            break
957                wanted_interfaces[i]['ip'] = ip
958                wanted_interfaces[i]['def_gw'] = def_gw
959            else:
960                dest_mac = dual_int['MAC']
961                loopback_dest = True
962                print("For interface %s, assuming loopback to it's dual interface %s." % (interface['Interface_argv'], dual_int['Interface_argv']))
963                if dpdk_nic_bind.confirm("Destination MAC is %s. Change it to MAC of DUT? (y/N)." % dest_mac):
964                    while True:
965                        input_mac = dpdk_nic_bind.read_line('Please enter new destination MAC of interface %s: ' % interface['Interface_argv'])
966                        try:
967                            if input_mac:
968                                ConfigCreator.verify_mac(input_mac) # verify format
969                                dest_mac = input_mac
970                                loopback_dest = False
971                            else:
972                                print('Leaving the loopback MAC.')
973                        except Exception as e:
974                            print(e)
975                            continue
976                        break
977                wanted_interfaces[i]['dest_mac'] = dest_mac
978                wanted_interfaces[i]['loopback_dest'] = loopback_dest
979
980        config = ConfigCreator(cpu_topology, wanted_interfaces, include_lcores = map_driver.args.create_include, exclude_lcores = map_driver.args.create_exclude,
981                               only_first_thread = map_driver.args.no_ht, ignore_numa = map_driver.args.ignore_numa or ignore_numa,
982                               prefix = map_driver.args.prefix, zmq_rpc_port = map_driver.args.zmq_rpc_port, zmq_pub_port = map_driver.args.zmq_pub_port)
983        if dpdk_nic_bind.confirm('Print preview of generated config? (Y/n)', default = True):
984            config.create_config(print_config = True)
985        if dpdk_nic_bind.confirm('Save the config to file? (Y/n)', default = True):
986            print('Default filename is /etc/trex_cfg.yaml')
987            filename = dpdk_nic_bind.read_line('Press ENTER to confirm or enter new file: ')
988            if not filename:
989                filename = '/etc/trex_cfg.yaml'
990            config.create_config(filename = filename)
991
992
993def parse_parent_cfg (parent_cfg):
994    parent_parser = argparse.ArgumentParser(add_help = False)
995    parent_parser.add_argument('-?', '-h', '--help', dest = 'help', action = 'store_true')
996    parent_parser.add_argument('--cfg', default='')
997    parent_parser.add_argument('--dump-interfaces', nargs='*', default=None)
998    parent_parser.add_argument('--no-ofed-check', action = 'store_true')
999    parent_parser.add_argument('--no-scapy-server', action = 'store_true')
1000    parent_parser.add_argument('--no-watchdog', action = 'store_true')
1001    parent_parser.add_argument('-i', action = 'store_true', dest = 'stl', default = False)
1002    map_driver.parent_args, _ = parent_parser.parse_known_args(shlex.split(parent_cfg))
1003    if map_driver.parent_args.help:
1004        sys.exit(0)
1005
1006
1007def process_options ():
1008    parser = argparse.ArgumentParser(usage="""
1009
1010Examples:
1011---------
1012
1013To return to Linux the DPDK bound interfaces (for ifconfig etc.)
1014  sudo ./dpdk_set_ports.py -l
1015
1016To create TRex config file using interactive mode
1017  sudo ./dpdk_set_ports.py -i
1018
1019To create a default config file (example)
1020  sudo ./dpdk_setup_ports.py -c 02:00.0 02:00.1 -o /etc/trex_cfg.yaml
1021
1022To show interfaces status
1023  sudo ./dpdk_set_ports.py -s
1024
1025To see more detailed info on interfaces (table):
1026  sudo ./dpdk_set_ports.py -t
1027
1028    """,
1029    description=" unbind dpdk interfaces ",
1030    epilog=" written by hhaim");
1031
1032    parser.add_argument("-l", "--linux", action='store_true',
1033                      help=""" Return all DPDK interfaces to Linux driver """,
1034     )
1035
1036    parser.add_argument("--cfg",
1037                      help=""" configuration file name  """,
1038     )
1039
1040    parser.add_argument("--parent",
1041                      help=argparse.SUPPRESS
1042     )
1043
1044    parser.add_argument('--dump-pci-description', help=argparse.SUPPRESS, dest='dump_pci_desc', action='store_true')
1045
1046    parser.add_argument("-i", "--interactive", action='store_true',
1047                      help=""" Create TRex config in interactive mode """,
1048     )
1049
1050    parser.add_argument("-c", "--create", nargs='*', default=None, dest='create_interfaces', metavar='<interface>',
1051                      help="""Try to create a configuration file by specifying needed interfaces by PCI address or Linux names: eth1 etc.""",
1052     )
1053
1054    parser.add_argument("--ci", "--cores-include", nargs='*', default=[], dest='create_include', metavar='<cores>',
1055                      help="""White list of cores to use. Make sure there is enough for each NUMA.""",
1056     )
1057
1058    parser.add_argument("--ce", "--cores-exclude", nargs='*', default=[], dest='create_exclude', metavar='<cores>',
1059                      help="""Black list of cores to exclude. Make sure there will be enough for each NUMA.""",
1060     )
1061
1062    parser.add_argument("--no-ht", default=False, dest='no_ht', action='store_true',
1063                      help="""Use only one thread of each Core in created config yaml (No Hyper-Threading).""",
1064     )
1065
1066    parser.add_argument("--dest-macs", nargs='*', default=[], action='store',
1067                      help="""Destination MACs to be used in created yaml file. Without them, will assume loopback (0<->1, 2<->3 etc.)""",
1068     )
1069
1070    parser.add_argument("--force-macs", default=False, action='store_true',
1071                      help="""Use MACs in created config file.""",
1072     )
1073
1074    parser.add_argument("--ips", nargs='*', default=[], action='store',
1075                      help="""IP addresses to be used in created yaml file. Without them, will assume loopback (0<->1, 2<->3 etc.)""",
1076     )
1077
1078    parser.add_argument("--def-gws", nargs='*', default=[], action='store',
1079                      help="""Default gateways to be used in created yaml file. Without them, will assume loopback (0<->1, 2<->3 etc.)""",
1080     )
1081
1082    parser.add_argument("-o", default=None, action='store', metavar='PATH', dest = 'output_config',
1083                      help="""Output the config to this file.""",
1084     )
1085
1086    parser.add_argument("--prefix", default=None, action='store',
1087                      help="""Advanced option: prefix to be used in TRex config in case of parallel instances.""",
1088     )
1089
1090    parser.add_argument("--zmq-pub-port", default=None, action='store',
1091                      help="""Advanced option: ZMQ Publisher port to be used in TRex config in case of parallel instances.""",
1092     )
1093
1094    parser.add_argument("--zmq-rpc-port", default=None, action='store',
1095                      help="""Advanced option: ZMQ RPC port to be used in TRex config in case of parallel instances.""",
1096     )
1097
1098    parser.add_argument("--ignore-numa", default=False, action='store_true',
1099                      help="""Advanced option: Ignore NUMAs for config creation. Use this option only if you have to, as it will reduce performance.""",
1100     )
1101
1102    parser.add_argument("-s", "--show", action='store_true',
1103                      help=""" show the status """,
1104     )
1105
1106    parser.add_argument("-t", "--table", action='store_true',
1107                      help=""" show table with NICs info """,
1108     )
1109
1110    parser.add_argument('--version', action='version',
1111                        version="0.2" )
1112
1113    map_driver.args = parser.parse_args();
1114    if map_driver.args.parent :
1115        parse_parent_cfg (map_driver.args.parent)
1116        if map_driver.parent_args.cfg:
1117            map_driver.cfg_file = map_driver.parent_args.cfg;
1118    if  map_driver.args.cfg :
1119        map_driver.cfg_file = map_driver.args.cfg;
1120
1121def main ():
1122    try:
1123        if os.getuid() != 0:
1124            raise DpdkSetup('Please run this program as root/with sudo')
1125
1126        process_options ()
1127
1128        if map_driver.args.show:
1129            dpdk_nic_bind.show_status()
1130            return
1131
1132        if map_driver.args.table:
1133            dpdk_nic_bind.show_table()
1134            return
1135
1136        if map_driver.args.dump_pci_desc:
1137            dpdk_nic_bind.dump_pci_description()
1138            return
1139
1140        obj =CIfMap(map_driver.cfg_file);
1141
1142        if map_driver.args.create_interfaces is not None:
1143            obj.do_create();
1144        elif map_driver.args.interactive:
1145            obj.do_interactive_create();
1146        elif map_driver.args.linux:
1147            obj.do_return_to_linux();
1148        else:
1149            exit(obj.do_run());
1150        print('')
1151    except DpdkSetup as e:
1152        print(e)
1153        exit(-1)
1154    except Exception:
1155        traceback.print_exc()
1156        exit(-1)
1157    except KeyboardInterrupt:
1158        sys.exit(-1)
1159
1160
1161
1162if __name__ == '__main__':
1163    main()
1164