def interface_db_set_vlan_member(db, is_add, vid, interface_name, untagged=True): vlan_name = 'Vlan{}'.format(vid) vlan = db.get_entry('VLAN', vlan_name) if len(vlan) == 0: util_utl.utl_err("{} doesn't exist".format(vlan_name)) return if is_add: members = vlan.get('members', []) if interface_name in members: util_utl.utl_log("{} is already a member of {}".format(interface_name, vlan_name)) return members.append(interface_name) vlan['members'] = members db.set_entry('VLAN', vlan_name, vlan) db.set_entry('VLAN_MEMBER', (vlan_name, interface_name), {'tagging_mode': "untagged" if untagged else "tagged"}) else: members = vlan.get('members', []) if interface_name not in members: util_utl.utl_log("{} is not a member of {}".format(interface_name, vlan_name)) return members.remove(interface_name) if len(members) == 0: del vlan['members'] else: vlan['members'] = members db.set_entry('VLAN', vlan_name, vlan) db.set_entry('VLAN_MEMBER', (vlan_name, interface_name), None)
def interface_set_trunk_vlans(oc_yph, pkey_ar, val, is_create, disp_args): # not support create if is_create: return False vlan_output = interface_get_vlan_output(disp_args) (old_tvlan, old_uvlan) = interface_fill_inf_vlanmbr_info(None, pkey_ar[0], vlan_output) # handle syntax error exception try: new_tvlan = [] if val == "" else eval(val) except: return False del_tvlan = [] for vid in old_tvlan: int_vid = int(vid) if int_vid not in new_tvlan: del_tvlan.append(int_vid) else: new_tvlan.remove(int_vid) # check if all new tvlan exists if new_tvlan and not interface_is_vlan_lst_valid(oc_yph, new_tvlan, disp_args): util_utl.utl_err("new vlan list is not valid !") return False # remove inf from vlan for vid in del_tvlan: interface_db_set_vlan_member(disp_args.cfgdb, False, vid, pkey_ar[0]) # add inf into vlan for vid in new_tvlan: interface_db_set_vlan_member(disp_args.cfgdb, True, vid, pkey_ar[0], False) return True
def nwi_pf_add_one_rule(oc_pol, rule_name, rule_data, msess_lst): # {0} : entry name # {1} : field # {2} : value #pdb.set_trace() EXEC_STR_TMPL = '{0}.{1} = {2}' seq_id = RULE_MAX_PRI - int(rule_data['PRIORITY']) oc_rule = oc_pol.rules.rule.add(seq_id) for d_key in rule_data.keys(): if d_key in OCYANG_FLDMAP_TBL: if OCYANG_FLDMAP_TBL[d_key]['type'] == NON_TYPE: continue value_str = rule_data[d_key] if value_str == 'None': continue if d_key == 'MIRROR_ACTION': nwi_pf_add_one_mirror_action(oc_rule, value_str, msess_lst) value_str = None elif d_key == 'PACKET_ACTION': nwi_pf_add_one_pol_rt_action(oc_rule, value_str) value_str = None elif d_key == 'TCP_FLAGS': value_str = acl_cnv_to_oc_tcp_flags(value_str) if value_str: if OCYANG_FLDMAP_TBL[d_key]['type'] == STR_TYPE: value_str = '"{0}"'.format(value_str) exec_str = EXEC_STR_TMPL.format( "oc_rule", OCYANG_FLDMAP_TBL[d_key]['str'], value_str) exec(exec_str) else: util_utl.utl_err("field(%s) is not supported !" % d_key)
def acl_rule_copy_cfg(rule_yang, rule_sonic, key, msess_tbl): if key in ['actions', 'action']: return acl_rule_copy_action(rule_yang, rule_sonic, msess_tbl) is_copy = False is_empty = True if key in rule_yang and 'config' in rule_yang[ key] and key in SONIC_FLDMAP_TBL: fld_tbl = SONIC_FLDMAP_TBL[key] for fld in rule_yang[key]['config'].keys(): is_empty = False if fld in fld_tbl: val = rule_yang[key]['config'][fld] if fld == 'tcp-flags': val = acl_cnv_to_sonic_tcp_flags(val) if val: rule_sonic[fld_tbl[fld]] = val is_copy = True else: util_utl.utl_err("field(%s) is not supported !" % fld) return is_empty or is_copy
def create_portchannel(oc_yph, pkey_ar, val, disp_args): """Create port channel""" try: portchannel = SonicPortchannel.Portchannel.FromString(val) for list_key in portchannel.portchannel_list: name = list_key.portchannel_name min_links = list_key.portchannel_list.min_links mtu = list_key.portchannel_list.mtu # Delete portchannel and its members when the porchannel exists portchannel_member_list = disp_args.cfgdb.get_table(PORTCHANNEL_MEMBER_TABLE) for k, v in portchannel_member_list: if k == name: disp_args.cfgdb.set_entry(PORTCHANNEL_MEMBER_TABLE, (k, v), None) if disp_args.cfgdb.get_entry(PORTCHANNEL_TABLE, name) is not None: disp_args.cfgdb.set_entry(PORTCHANNEL_TABLE, name, None) # Create new portchannel and add members to it fvs = {'admin_status': 'up'} fvs['min_links'] = str(min_links.value) fvs['mtu'] = str(mtu.value) # fvs['fallback'] = 'true' disp_args.cfgdb.set_entry(PORTCHANNEL_TABLE, name, fvs) for member in list_key.portchannel_list.members: member_name = member.value disp_args.cfgdb.set_entry(PORTCHANNEL_MEMBER_TABLE, (name, member_name), {'NULL': 'NULL'}) except Exception as e: util_utl.utl_err("create portchannel failed: " + e.message) return False return True
def set_vlan_dhcp_relay(config_db, vid, ip_addresses): for ip_addr in ip_addresses: if not is_ipaddress(ip_addr): util_utl.utl_err("{} is an invalid IP address".format(ip_addr)) return False vlan_name = "Vlan{}".format(vid) vlan = config_db.get_entry('VLAN', vlan_name) if len(vlan) == 0: util_utl.utl_err("{} does not exist".format(vlan_name)) return False dhcp_relays = vlan.get('dhcp_servers', []) if len(ip_addresses) == 0: del vlan['dhcp_servers'] else: del dhcp_relays[:] for ip_addr in ip_addresses: dhcp_relays.append(ip_addr) vlan['dhcp_servers'] = dhcp_relays config_db.set_entry('VLAN', vlan_name, vlan) util_utl.utl_log("Set DHCP relay destination addresses {} for {}".format( ip_addresses, vlan_name)) # try: # util_utl.utl_execute_cmd("systemctl restart dhcp_relay") # except SystemExit as e: # util_utl.utl_err("Restart service dhcp_relay failed with error {}" # .format(e)) # return False return True
def del_vlan_dhcp_relay(config_db, vid, ip_addr): if not is_ipaddress(ip_addr): util_utl.utl_err("{} is an invalid IP address".format(ip_addr)) return False vlan_name = "Vlan{}".format(vid) vlan = config_db.get_entry('VLAN', vlan_name) if len(vlan) == 0: util_utl.utl_err("{} does not exist".format(vlan_name)) return False dhcp_relays = vlan.get('dhcp_servers', []) if ip_addr not in dhcp_relays: util_utl.utl_log("{} is not a DHCP relay destination for {}".format( ip_addr, vlan_name)) else: dhcp_relays.remove(ip_addr) if len(dhcp_relays) == 0: del vlan['dhcp_servers'] else: vlan['dhcp_servers'] = dhcp_relays config_db.set_entry('VLAN', vlan_name, vlan) util_utl.utl_log( "Remove DHCP relay destination address {} from {}".format( ip_addr, vlan_name)) # try: # util_utl.utl_execute_cmd("systemctl restart dhcp_relay") # except SystemExit as e: # util_utl.utl_err("Restart service dhcp_relay failed with error {}" # .format(e)) # return False return True
def interface_set_native_vlan(oc_yph, pkey_ar, val, is_create, disp_args): # not support create if is_create: return False vlan_output = interface_get_vlan_output(disp_args) (old_tvlan, old_uvlan) = interface_fill_inf_vlanmbr_info(None, pkey_ar[0], vlan_output) if val == "": new_uvlan = 0 else: new_uvlan = interface_extract_vid(val) if new_uvlan == 0: return False # check if new uvlan exists if not interface_is_vlan_lst_valid(oc_yph, [new_uvlan], disp_args): util_utl.utl_err("native vlan is not valid !") return False # remove inf from old uvlan for vid in old_uvlan: interface_db_set_vlan_member(disp_args.cfgdb, False, vid, pkey_ar[0]) # add inf into new uvlan if new_uvlan != 0: interface_db_set_vlan_member(disp_args.cfgdb, True, new_uvlan, pkey_ar[0]) return True
def interface_remove_all_ipprefix(oc_yph, pkey_ar, disp_args): try: port_name = pkey_ar[0] except Exception as e: util_utl.utl_err("remove interface's ip failed: " + e.message) return False return interface_db_clear_ip(disp_args.cfgdb, port_name)
def is_vrf_name_valid(vrf_name): if not vrf_name.startswith( "Vrf") and vrf_name != 'mgmt' and vrf_name != 'management': util_utl.utl_err( "{} is not start with Vrf, mgmt or management!".format(vrf_name)) return False if len(vrf_name) > 15: util_utl.utl_err("{} is too long!".format(vrf_name)) return False return True
def interface_delete_interface(oc_yph, pkey_ar, disp_args): # support to delete loopback and vlan only if pkey_ar[0].find('Loopback') != 0 and pkey_ar[0].find('Vlan') != 0: util_utl.utl_err("Only support to delete loopback and vlan interface") return False if pkey_ar[0].find('Loopback') == 0: return del_loopback(disp_args.cfgdb, pkey_ar[0]) elif pkey_ar[0].find('Vlan') == 0: return interface_db_clear_ip(disp_args.cfgdb, pkey_ar[0]) return False
def interface_db_set_vlan(db, vid, is_add): vlan = 'Vlan{}'.format(vid) if is_add: if len(db.get_entry('VLAN', vlan)) != 0: util_utl.utl_err("{} already exists".format(vlan)) else: db.set_entry('VLAN', vlan, {'vlanid': vid}) else: # remove all vlan member of vid keys = [ (k, v) for k, v in db.get_table('VLAN_MEMBER') if k == 'Vlan{}'.format(vid) ] for k in keys: db.set_entry('VLAN_MEMBER', k, None) db.set_entry('VLAN', 'Vlan{}'.format(vid), None)
def interface_remove_ipprefix(oc_yph, pkey_ar, disp_args): try: ip_prefix = pkey_ar[0] port_name = pkey_ar[1] table_name = interface_db_get_intf_table_name(port_name) if table_name: disp_args.cfgdb.set_entry(table_name, (port_name, ip_prefix), None) except Exception as e: util_utl.utl_err("remove interface's ip failed: " + e.message) return False return True
def bcm_get_port_name(is_phy, src_port_name): bcm_get_diag_port_map() ret_port_name = None map_tbl = BCM_PHY_PORT_MAP if is_phy else BCM_USR_PORT_MAP if src_port_name in map_tbl: if 'index' in map_tbl[src_port_name]: ret_port_name = 'xe%s' % map_tbl[src_port_name]['index'] else: ret_port_name = map_tbl[src_port_name] else: util_utl.utl_err("Failed to convert port name (%s)" % src_port_name) return ret_port_name
def bcm_get_mirror_mode_by_type(in_mode, in_type): out_type = ['gtag', 'diag'][in_type == 'gtag'] ret_val = None for key in BCM_MIRROR_MODE_TBL.keys(): if BCM_MIRROR_MODE_TBL[key][in_type] == in_mode: ret_val = BCM_MIRROR_MODE_TBL[key][out_type] break if not ret_val: util_utl.utl_err("Failed to get mirror mode (%s/%s)" % (in_mode, in_type)) return ret_val
def portchannel_add_member(oc_yph, pkey_ar, val, is_create, disp_args): """Add given port to portchannel's member""" try: portchannel = SonicPortchannel.Portchannel.FromString(val) for list_key in portchannel.portchannel_list: name = list_key.portchannel_name for member in list_key.portchannel_list.members: disp_args.cfgdb.set_entry(PORTCHANNEL_MEMBER_TABLE, (name, member), {'NULL': 'NULL'}) except Exception as e: util_utl.utl_err("add member to portchannel failed: " + e.message) return False return True
def acl_rule_copy_action(rule_yang, rule_sonic, msess_tbl): #pdb.set_trace() ret_val = False if msess_tbl == None: # for acl: actions.config.forwarding-action if "actions" in rule_yang: act_tbl = {'ACCEPT': 'FORWARD', 'DROP': 'DROP'} try: val = rule_yang["actions"]["config"]["forwarding-action"] if val in act_tbl: val = act_tbl[val] rule_sonic["PACKET_ACTION"] = val ret_val = True except: pass else: # for pf: action.config.next-hop # action.encapsulate-gre.targets if "action" in rule_yang: if "config" in rule_yang["action"]: # "REDIRECT:ip" try: val = rule_yang["action"]["config"]["next-hop"] rule_sonic["PACKET_ACTION"] = "REDIRECT:%s" % val ret_val = True except: pass elif 'encapsulate-gre' in rule_yang['action']: try: trg_cfgs = rule_yang["action"]["encapsulate-gre"][ "targets"]["target"] for trg in trg_cfgs: rule_sonic["MIRROR_ACTION"] = trg if trg in msess_tbl: break #ret_val = acl_add_one_mirror_session(trg, trg_cfgs[trg]) msess_tbl[trg] = trg_cfgs[trg] break # support only one session ??? ret_val = True except: pass if not ret_val: util_utl.utl_err("No action for %s rule !!!" % ["pf", "acl"][msess_tbl == None]) return ret_val
def qos_get_fwdgrp_info(oc_qos, disp_args): tc2q_lst = disp_args.cfgdb.get_table(util_utl.CFGDB_TABLE_NAME_TC2Q_MAP) for tc2q in tc2q_lst: for tc in tc2q_lst[tc2q]: fwdgrp_name = FWDGRP_NAME_FMT.format(tc2q, tc) if fwdgrp_name not in oc_qos.forwarding_groups.forwarding_group: oc_fwd = oc_qos.forwarding_groups.forwarding_group.add( fwdgrp_name) else: oc_fwd = oc_qos.forwarding_groups.forwarding_group[fwdgrp_name] oc_fwd.config.fabric_priority = int(tc) q_name = tc2q_lst[tc2q][tc] if q_name in oc_qos.queues.queue: oc_fwd.config.output_queue = q_name else: util_utl.utl_err("queue (%d) does not exist !" % q_name)
def interface_set_loopback_interface(oc_yph, pkey_ar, val, is_create, disp_args): try: loopback = SonicLoopbackInterface.LoopbackInterface.FromString(val) for key in loopback.loopback_interface_ipprefix_list: name = key.loopback_interface_name ip = key.ip_prefix if name.find('Loopback') != 0: util_utl.utl_err("Invalid loopback name") continue add_loopback(disp_args.cfgdb, name, ip) except: return False return True
def add_vrf(config_db, vrf_name, vlan_ids): """Add vrf""" if not is_vrf_name_valid(vrf_name): return False if vrf_name == 'mgmt' or vrf_name == 'management': vrf_add_management_vrf(config_db) else: config_db.set_entry('VRF', vrf_name, {"NULL": "NULL"}) for vlan_id in vlan_ids: vlan_name = "Vlan{}".format(vlan_id) if bind_interface_to_vrf(config_db, vlan_name, vrf_name): util_utl.utl_err("bind {} to {} failed".format( vlan_name, vrf_name)) return True
def bind_interface_to_vrf(config_db, interface_name, vrf_name): """bind interface to vrf""" table_name = get_interface_table_name(interface_name) if table_name == "": util_utl.utl_err("interface name is not valid.") return False if is_interface_bind_to_vrf(config_db, interface_name) is True and \ config_db.get_entry(table_name, interface_name).get('vrf_name') == vrf_name: return True # Clean ip addresses if interface configured interface_dependent = interface_ipaddr_dependent_on_interface( config_db, interface_name) for interface in interface_dependent: config_db.set_entry(table_name, interface, None) config_db.set_entry(table_name, interface_name, {"vrf_name": vrf_name}) # if does not work, please reference config source code return True
def interface_set_ip(oc_yph, pkey_ar, val, is_create, disp_args): try: interface = SonicInterface.Interface.FromString(val) for ip_list_key in interface.interface_ipprefix_list: name = ip_list_key.port_name ip = ip_list_key.ip_prefix table_name = interface_db_get_intf_table_name(name) if table_name: disp_args.cfgdb.set_entry(table_name, (name, ip), {}) # TODO(sgk): process InterfaceListKey when wlan support vrf except Exception as e: util_utl.utl_err("{}", e) return False return True
def interface_config_interface(oc_yph, pkey_ar, val, is_create, disp_args): # support loopback interface only try: tmp_cfg = {} if val == "" or val == "{}" else eval(val) ip_addr = tmp_cfg.get('ip') role = tmp_cfg.get('role') except: util_utl.utl_err("Invalid parameter") return False if not ip_addr: return False # support to add/delete loopback interface now if pkey_ar[0].find('Loopback') != 0: util_utl.utl_err("Invalid loopback name") return False return add_loopback(disp_args.cfgdb, pkey_ar[0], ip_addr)
def acl_rule_yang2sonic(rule_yang, msess_tbl=None): rule_sonic = {} rule_name = acl_rule_get_name_and_pri(rule_yang, rule_sonic) if rule_name: is_copy = False for key in rule_yang.keys(): if key in [ "ipv4", "l2", "transport", "actions" if msess_tbl == None else "action" ]: is_copy_tmp = acl_rule_copy_cfg(rule_yang, rule_sonic, key, msess_tbl) if not is_copy_tmp: util_utl.utl_err("Failed to get rule field (%s:%s)!!!" % (key, rule_yang[key])) is_copy = is_copy or is_copy_tmp elif key not in ["sequence-id", "config"]: util_utl.utl_err("Unrecognized key (%s:%s)!!!" % (key, rule_yang[key])) if not is_copy: rule_sonic = None else: util_utl.utl_err("Failed to get rule name (%s)!!!" % rule_yang) return rule_name, rule_sonic
def acl_add_one_rule(oc_acl_set, rule_name, rule_data): # {0} : entry name # {1} : field # {2} : value #pdb.set_trace() EXEC_STR_TMPL = '{0}.{1} = {2}' seq_id = RULE_MAX_PRI - int(rule_data['PRIORITY']) oc_rule = oc_acl_set.acl_entries.acl_entry.add(seq_id) oc_rule.config.description = rule_name for d_key in rule_data.keys(): if d_key in OCYANG_FLDMAP_TBL: if OCYANG_FLDMAP_TBL[d_key]['type'] == NON_TYPE: continue value_str = rule_data[d_key] if value_str == 'None': continue if d_key == 'PACKET_ACTION': if value_str in OCYANG_ACTMAP_TBL: value_str = OCYANG_ACTMAP_TBL[value_str] else: util_utl.utl_err("action(%s) is not valid !" % value_str) value_str = None elif d_key == 'TCP_FLAGS': value_str = acl_cnv_to_oc_tcp_flags(value_str) if value_str: if OCYANG_FLDMAP_TBL[d_key]['type'] == STR_TYPE: value_str = '"{0}"'.format(value_str) exec_str = EXEC_STR_TMPL.format( "oc_rule", OCYANG_FLDMAP_TBL[d_key]['str'], value_str) exec(exec_str) else: util_utl.utl_err("field(%s) is not supported !" % d_key)
def qos_get_schdlr_info(oc_qos, disp_args): schdlr_lst = disp_args.cfgdb.get_table(util_utl.CFGDB_TABLE_NAME_SCHDLR) if schdlr_lst: # default WRR, seq 1 (0 reserved for strict priority) oc_schd_policy = oc_qos.scheduler_policies.scheduler_policy[ 'DEFAULT_EGRESS'] if 1 not in oc_schd_policy.schedulers.scheduler: oc_schdlr = oc_schd_policy.schedulers.scheduler.add(1) oc_schdlr.output.config.output_type = 'INTERFACE' # oc_schdlr.config.type = 1r2c or 2r3c # oc_schdlr.config.priority = 'STRICT' else: oc_schdlr = oc_schd_policy.schedulers.scheduler[1] for schdlr in schdlr_lst: if schdlr not in oc_schdlr.inputs.input: # ex: scheduler.0 oc_inp = oc_schdlr.inputs.input.add(schdlr) else: oc_inp = oc_schdlr.inputs.input[schdlr] # IN_PROFILE/OUT_PROFILE/QUEUE oc_inp.config.input_type = 'QUEUE' oc_inp.config.weight = int(schdlr_lst[schdlr]['weight']) queue_lst = disp_args.cfgdb.get_table(util_utl.CFGDB_TABLE_NAME_QUEUE) pat_obj = re.compile(r'\[SCHEDULER\|(.*)\]') for inf_q in queue_lst: inf, qid = inf_q # TODO multi q mapped to one scheduler if '-' in qid: util_utl.utl_err("extract qid (%s) failed !" % qid) continue sched_key = queue_lst[inf_q]['scheduler'] m = pat_obj.match(sched_key) if m: if m.group(1) in oc_schdlr.inputs.input: oc_inp = oc_schdlr.inputs.input[m.group(1)] oc_inp.config.queue = qid else: util_utl.utl_err("scheduler (%s) does not exist !" % m.group(1)) else: util_utl.utl_err("extract scheduler (%s) from QUEUE failed !" % sched_key)
def interface_get_pc_inf_info(oc_infs, fill_info_bmp, key_ar, out_tbl, disp_args): global OLD_AGG_MBR_LST, OLD_PC_INF_LST # 1. clear all port's aggregate-id info if fill_info_bmp & FILL_INFO_PC: for inf in OLD_AGG_MBR_LST: inf.ethernet.config._unset_aggregate_id() OLD_AGG_MBR_LST = [] ret_val = False new_pc_inf_lst = [] pc_lst = disp_args.cfgdb.get_table(util_utl.CFGDB_TABLE_NAME_PC) if pc_lst: is_key_pc = True if key_ar and key_ar[0].find('PortChannel') == 0 else False is_key_et = True if key_ar and key_ar[0].find('Ethernet') == 0 else False ret_val = True for pc in pc_lst: # case 1, key: PortChannelX if is_key_pc and key_ar[0] != pc: continue if pc not in oc_infs.interface: oc_inf = oc_infs.interface.add(pc) else: oc_inf = oc_infs.interface[pc] new_pc_inf_lst.append(pc) if not is_key_et: if fill_info_bmp & FILL_INFO_STATE: interface_fill_inf_state(oc_inf, pc, disp_args.appdb, FILL_INFO_PC) if fill_info_bmp & FILL_INFO_VLAN: interface_fill_inf_vlanmbr_info(oc_inf, pc, out_tbl["vlan_output"]) if fill_info_bmp & FILL_INFO_IP: interface_fill_inf_ip_info(oc_inf, pc, out_tbl) if fill_info_bmp & FILL_INFO_PC: oc_inf._unset_aggregation() exec_cmd = 'teamdctl %s state dump' % pc (is_ok, output) = util_utl.utl_get_execute_cmd_output(exec_cmd) if is_ok: pc_state = json.loads(output) if not is_key_et: if pc_state["setup"]["runner_name"] == "lacp": oc_inf.aggregation.state._set_lag_type('LACP') else: oc_inf.aggregation.state._set_lag_type('STATIC') if "ports" in pc_state: for port in pc_state["ports"]: if port in oc_infs.interface: if not is_key_et: OLD_AGG_MBR_LST.append(oc_infs.interface[port]) oc_inf.aggregation.state.member.append(port) oc_infs.interface[port].ethernet.config._set_aggregate_id(pc) else: util_utl.utl_err("pc [%s]'s mbr port [%s] does not exist !!!" % (pc, port)) # case 2, key: EthernetX if is_key_et and key_ar[0] == port: break # remove no existing pc for pc in OLD_PC_INF_LST: if pc not in new_pc_inf_lst and pc in oc_infs.interface: oc_infs.interface.delete(pc) OLD_PC_INF_LST = new_pc_inf_lst return ret_val