def create_vrf_default_rules(vrf_name, vrf_id, rule_id_list=None): for af in [socket.AF_INET, socket.AF_INET6]: any_ip_str = '0.0.0.0' if af == socket.AF_INET else '::' intf_list = ['lo'] if vrf_name == 'default': intf_list.append('vdef-nsid%s' % str(vrf_id)) else: intf_list.append('veth-nsid%s' % str(vrf_id)) for intf in intf_list: rule_id = process_vrf_svcs_rule_add( VrfIncomingSvcsRule.RULE_TYPE_ACL, vrf_name, VrfIncomingSvcsRule.RULE_ACTION_ALLOW, af, src_ip=socket.inet_pton(af, any_ip_str), prefix_len=0, high_prio=True, in_intf=intf) if rule_id is None: log_err( 'Failed to create default ACL rules: VRF %s af %d intf %s' % (vrf_name, af, intf)) return False if rule_id_list is not None: log_info('Deault rule created: VRF %s af %d intf %s ID %d' % (vrf_name, af, intf, rule_id)) rule_id_list.append(rule_id) return True
def clear_all_rules(cls, flt_vrf=None, flt_af=None): log_info('Handling clear all rules for VRF %s and AF %s' % (flt_vrf if flt_vrf is not None else '-', str(flt_af) if flt_af is not None else '-')) cls.mutex.acquire() for af in [socket.AF_INET, socket.AF_INET6]: if flt_af is not None and flt_af != af: continue for vrf_name, rule_list in cls.ip_rules[af].items(): if flt_vrf is not None and flt_vrf != vrf_name: continue for rule in rule_list: IptablesHandler.proc_rule('delete', rule) cls.id_generator.release_id(rule.rule_id) rule_list.clear() del cls.ip_rules[af][vrf_name] for vrf_name, rule_list in cls.acl_rules[af].items(): if flt_vrf is not None and flt_vrf != vrf_name: continue for rule in rule_list: IptablesHandler.proc_rule('delete', rule) cls.id_generator.release_id(rule.rule_id) rule_list.clear() del cls.acl_rules[af][vrf_name] cls.mutex.release()
def set_vrf_intf_cb_int(methods, params): obj = cps_object.CPSObject(obj=params['change']) if_name = None vrf_name = None if_name = 'if/interfaces/interface/name' if_type = 'if/interfaces/interface/type' vrf_name = 'ni/if/interfaces/interface/bind-ni-name' try: if_name = obj.get_attr_data(if_name) vrf_name = obj.get_attr_data(vrf_name) # Dont mandate interface type for mgmt interface when it is getting moved to mgmt VRF, # since we dont need to alloc. MAC for the same. if vrf_name != _management_vrf_name: if_type = obj.get_attr_data(if_type) except ValueError as e: log_msg = 'Missing mandatory attribute ' + e.args[0] log_err(log_msg) return False operation = params['operation'] try: if operation == 'set': return False else: op = True if operation == 'delete': op = False log_msg = 'VRF ' + vrf_name + ' intf ' + if_name + ' request ' + operation log_info(log_msg) ret_val, v_if_name, v_if_index, v_mac_str = dn_base_vrf_tool.process_vrf_intf_config( op, if_name, vrf_name, if_type) if ret_val is True: if op: cps_obj = cps_object.CPSObject( module='vrf-mgmt/ni/if/interfaces/interface', qual='target', data={ intf_attr('name'): if_name, ni_intf_attr('bind-ni-name'): vrf_name, vrf_mgmt_intf_attr('ifname'): v_if_name, vrf_mgmt_intf_attr('ifindex'): v_if_index, vrf_mgmt_intf_attr('mac-addr'): v_mac_str, }) params['change'] = cps_obj.get() return True log_msg = 'Failed to execute VRF ' + vrf_name + ' intf ' + if_name + ' request ' + operation log_err(log_msg) except Exception as e: logging.exception(e) log_msg = 'Faild to commit operation.' + str(e) + params log_err(log_msg) return False
def insert_rule(cls, rule): log_info('Handling add rule: %s' % rule) cls.mutex.acquire() rule_list = cls.ip_rules[ rule.af] if rule.rule_type == rule.RULE_TYPE_IP else cls.acl_rules[ rule.af] if rule.vrf_name not in rule_list: rule_list[rule.vrf_name] = VrfIncomingSvcsRuleList() if rule.rule_id is None: rule.rule_id = cls.id_generator.get_new_id() if rule.rule_id is None: log_err('Could not generate new rule ID') log_info(str(cls.id_generator)) cls.mutex.release() return False else: if cls.id_generator.is_id_used(rule.rule_id): log_err('Given rule ID %d is used' % rule.rule_id) log_info(str(cls.id_generator)) cls.mutex.release() return False if not cls.id_generator.reserve_id(rule.rule_id): log_err('Failed to reserve rule ID %d' % rule.rule_id) log_info(str(cls.id_generator)) cls.mutex.release() return False ret_val = True idx = rule_list[rule.vrf_name].insert(rule) if idx is not None: if not IptablesHandler.proc_rule('insert', rule, idx): log_err('Failed to call iptables to insert ACL rule') # rollback rule_list[rule.vrf_name].remove(rule) ret_val = False else: log_err('Failed to insert rule to cache') cls.id_generator.release_id(rule.rule_id) ret_val = False cls.mutex.release() if ret_val: log_info('Rule added, ID=%d' % rule.rule_id) return ret_val
def replace_rule(cls, rule_id, new_rule): log_info('Handling replace rule with ID %d' % rule_id) cls.mutex.acquire() ret_val = True found_rule = cls.find_rule_by_id(rule_id) if found_rule is not None: old_rule, idx = found_rule rule_list = cls.ip_rules[old_rule.af] \ if old_rule.rule_type == old_rule.RULE_TYPE_IP else cls.acl_rules[old_rule.af] if not IptablesHandler.proc_rule('replace', new_rule, idx): log_err('Failed to call iptables to replace ACL rule') ret_val = False else: rule_list[old_rule.vrf_name][idx] = new_rule else: log_err('Rule ID %d not found for replace' % rule_id) ret_val = False cls.mutex.release() if ret_val: log_info('Rule replaced') return ret_val
def set_vrf_cb_int(methods, params): obj = cps_object.CPSObject(obj=params['change']) vrf_name = None vrf_name = ip_ni_attr('name') vrf_id = vrf_mgmt_ni_attr('vrf-id') try: vrf_name = obj.get_attr_data(vrf_name) vrf_id = obj.get_attr_data(vrf_id) except ValueError as e: log_msg = 'Missing mandatory attribute ' + e.args[0] log_err(log_msg) return False global _vrf_default_rule try: if params['operation'] == 'set': return False elif params['operation'] == 'create': log_msg = 'VRF config create - VRF Name:' + vrf_name + str(vrf_id) log_info(log_msg) # cache cleanup before create new VRF if not process_vrf_svcs_clear_rules(vrf_name): log_err('Failed to delete all rules for VRF %s' % vrf_name) # When we support regular VRF, add the handler accordingly. if dn_base_vrf_tool.process_vrf_config(True, vrf_name, vrf_id): # Create default rules for VRF _vrf_default_rule[vrf_name] = [] if not create_vrf_default_rules(vrf_name, _vrf_default_rule[vrf_name]): log_err( 'Failed to create default ACL rules for VRF %s to VRF ns' % vrf_name) if not create_vrf_default_rules('default', _vrf_default_rule[vrf_name]): log_err( 'Failed to create default ACL rules for VRF %s to default ns' % vrf_name) return True log_msg = 'VRF config create failed - VRF Name:' + vrf_name log_err(log_msg) elif params['operation'] == 'delete': log_msg = 'VRF config delete - VRF Name:' + vrf_name log_info(log_msg) if vrf_name in _vrf_default_rule: for rule_id in _vrf_default_rule[vrf_name]: log_info('Delete default ACl rule %d' % rule_id) process_vrf_svcs_rule_del_by_id(rule_id) del _vrf_default_rule[vrf_name] if dn_base_vrf_tool.process_vrf_config(False, vrf_name, vrf_id): return True log_msg = 'VRF config delete failed - VRF Name:' + vrf_name log_err(log_msg) except Exception as e: logging.exception(e) log_msg = 'Faild to commit operation.' + str(e) + 'params' + params log_err(log_msg) return False
def delete_rule_by_id(cls, rule_id): log_info('Handling delete rule by ID: %d' % rule_id) cls.mutex.acquire() ret_val = True found_rule = cls.find_rule_by_id(rule_id) if found_rule is not None: del_rule, idx = found_rule rule_list = cls.ip_rules[del_rule.af] \ if del_rule.rule_type == del_rule.RULE_TYPE_IP else cls.acl_rules[del_rule.af] if rule_list[del_rule.vrf_name].remove_by_id(rule_id) is None: log_err('Failed to remove rule with ID %d' % rule_id) cls.mutex.release() return False if not IptablesHandler.proc_rule('delete', del_rule, idx): log_err('Failed to call iptables to delete ACL rule') # rollback rule_list = cls.ip_rules[del_rule.af] \ if del_rule.rule_type == del_rule.RULE_TYPE_IP else cls.acl_rules[del_rule.af] rule_list[del_rule.vrf_name].insert(del_rule) ret_val = False if len(rule_list[del_rule.vrf_name]) == 0: del rule_list[del_rule.vrf_name] else: log_err('Rule ID %d not found for delete' % rule_id) ret_val = False cls.mutex.release() if ret_val: if not cls.id_generator.release_id(rule_id): log_err('Failed to release rule ID %d' % rule_id) log_info(str(cls.id_generator)) log_info('Rule deleted') return ret_val
def delete_rule(cls, rule): log_info('Handling delete rule: %s' % rule) cls.mutex.acquire() rule_list = cls.ip_rules[ rule.af] if rule.rule_type == rule.RULE_TYPE_IP else cls.acl_rules[ rule.af] if rule.vrf_name not in rule_list: log_err('VRF name %s not found in cache' % rule.vrf_name) cls.mutex.release() return False ret_val = rule_list[rule.vrf_name].remove(rule) if ret_val is None: log_err('Failed to delete rule from cache') cls.mutex.release() return False del_rule, idx = ret_val ret_val = True if not IptablesHandler.proc_rule('delete', del_rule, idx): log_err('Failed to call iptables to delete ACL rule') # rollback rule_list[del_rule.vrf_name].insert(del_rule) ret_val = False if len(rule_list[rule.vrf_name]) == 0: del rule_list[rule.vrf_name] cls.mutex.release() if ret_val: if not cls.id_generator.release_id(del_rule.rule_id): log_err('Failed to release rule ID %d' % del_rule.rule_id) log_info(str(cls.id_generator)) log_info('Rule deleted') return ret_val
def create_vrf_default_rules(vrf_name, rule_id_list=None): for af in [socket.AF_INET, socket.AF_INET6]: any_ip_str = '0.0.0.0' if af == socket.AF_INET else '::' intf = 'vdst-nsid+' rule_id = process_vrf_svcs_rule_add( VrfSvcsRuleType.RULE_TYPE_ACL, vrf_name, VrfSvcsRuleAction.RULE_ACTION_ALLOW, af, src_ip=socket.inet_pton(af, any_ip_str), src_prefix_len=0, high_prio=True, in_intf=intf) if rule_id is None: log_err( 'Failed to create default ACL rules: VRF %s af %d intf %s' % (vrf_name, af, intf)) return False if rule_id_list is not None: log_info('Default rule created: VRF %s af %d intf %s ID %d' % (vrf_name, af, intf, rule_id)) rule_id_list.append(rule_id) return True
def get_all_rules(cls, rule_type=None, vrf_name=None, **params): log_info('Handling get rules for vrf %s' % (vrf_name if vrf_name is not None else 'ALL')) cls.mutex.acquire() ret_list = [] for af in [socket.AF_INET, socket.AF_INET6]: if rule_type is None or rule_type == VrfIncomingSvcsRule.RULE_TYPE_IP: for vrf, rule_list in cls.ip_rules[af].items(): if vrf_name is not None and vrf != vrf_name: continue for rule in rule_list: if not rule.match(**params): continue ret_list.append(copy.deepcopy(rule)) if rule_type is None or rule_type == VrfIncomingSvcsRule.RULE_TYPE_ACL: for vrf, rule_list in cls.acl_rules[af].items(): if vrf_name is not None and vrf != vrf_name: continue for rule in rule_list: if not rule.match(**params): continue ret_list.append(copy.deepcopy(rule)) cls.mutex.release() return ret_list
def get_incoming_ip_svcs_int(methods, params): log_info('Callback for incoming IP service reading') obj_attr_map = { 'ni-name': 'vrf_name', 'af': 'af', 'src-ip': 'src_ip', 'src-prefix-len': 'prefix_len', 'protocol': 'protocol', 'dst-port': 'dst_port', 'action': 'action', 'seq-num': 'seq_num', 'id': 'rule_id' } obj = cps_object.CPSObject(obj=params['filter']) resp = params['list'] args = {} for key, val in obj_attr_map.items(): attr_name = incoming_ip_svcs_attr(key) try: attr_val = obj.get_attr_data(attr_name) except ValueError: attr_val = None if attr_val is not None: args[val] = attr_val # check af if 'af' in args and args['af'] is not None: af = args['af'] if af != socket.AF_INET and af != socket.AF_INET6: log_err('Invalid address family number %d' % af) return False # check source IP if 'src_ip' in args and args['src_ip'] is not None: af = args['af'] if 'af' in args else None af_ip = check_ip_validity(af, args['src_ip']) if af_ip is None: log_err('Invalid source IP %s for rule reading' % args['src_ip']) return False args['af'], args['src_ip'] = af_ip # add default prefix length af = args['af'] if 'prefix_len' not in args or args['prefix_len'] is None: if af == socket.AF_INET: args['prefix_len'] = 32 else: args['prefix_len'] = 128 log_info('Input parameters:') for name, val in args.items(): if val is not None: log_info(' %-10s : %s' % (name, str(val))) return process_vrf_svcs_rule_get(resp, **args)
d = {} d['get'] = get_outgoing_ip_svcs_cb d['transaction'] = config_outgoing_ip_svcs_cb cps.obj_register(handle, _vrf_outgoing_svc_config_key, d) d = {} d['get'] = get_vrf_intf_cb cps.obj_register(handle, _vrf_get_intf_key, d) d = {} d['transaction'] = set_vrf_intf_ip_cb cps.obj_register(handle, _vrf_intf_ip_key, d) log_msg = 'CPS IP VRF registration done' log_info(log_msg) process_vrf_top_chain_rule(True, 'default') # Create the rule to accept the loopback pkts by default i.e snmpwalk destined # to loopback IP (127.0.0.1) when pinning is on to accept mgmt pkts only from mgmt VRF. lo_pkts_ret_val, rule_id = create_default_lo_pkts_rule() #Start leaked route event handle thread to program leaked routes into the OS. leaked_rt_cfg_thread = threading.Thread(target=handle_leaked_rt_event,\ name="VRF_Leaked_Rt_Cfg") leaked_rt_cfg_thread.setDaemon(True) leaked_rt_cfg_thread.start() # Notify systemd: Daemon is ready systemd.daemon.notify("READY=1") # wait until a signal is received
def dump_rules(cls): cls.mutex.acquire() for af in [socket.AF_INET, socket.AF_INET6]: for vrf_name, rule_list in cls.ip_rules[af].items(): log_info('-------------------------------------') log_info( ' %s IP Rules of VRF %s' % ('IPv4' if af == socket.AF_INET else 'IPv6', vrf_name)) log_info('-------------------------------------') log_info('\n%s\n' % rule_list) for vrf_name, rule_list in cls.acl_rules[af].items(): log_info('-------------------------------------') log_info( ' %s ACL Rules of VRF %s' % ('IPv4' if af == socket.AF_INET else 'IPv6', vrf_name)) log_info('-------------------------------------') log_info('\n%s\n' % rule_list) cls.mutex.release()
def config_outgoing_ip_svcs_cb(methods, params): obj = cps_object.CPSObject(obj=params['change']) vrf_name = outgoing_ip_svcs_attr('ni-name') af = outgoing_ip_svcs_attr('af') public_ip = outgoing_ip_svcs_attr('public-ip') protocol = outgoing_ip_svcs_attr('protocol') public_port = outgoing_ip_svcs_attr('public-port') try: af = obj.get_attr_data(af) vrf_name = obj.get_attr_data(vrf_name) public_ip_data = obj.get_attr_data(public_ip) public_ip = _create_ip_from_attr(public_ip_data, af) protocol = obj.get_attr_data(protocol) public_port = obj.get_attr_data(public_port) except ValueError as e: log_msg = 'Missing mandatory attribute ' + e.args[0] log_err(log_msg) return False operation = params['operation'] log_msg = 'Operation:' + operation + ' VRF:' + vrf_name + ' family:'\ + _af[af] + ' public-ip' + public_ip + ' protocol:' + _protocol[protocol] + ' public-port:'\ + str(public_port) log_info(log_msg) try: if operation == 'set': return False elif operation == 'create': ret_val, private_port, private_ip = dn_base_vrf_tool.process_outgoing_ip_svcs_config(True,\ _af[af], public_ip, _protocol[protocol],\ str(public_port), vrf_name) family = socket.AF_INET if _af[af] == 'ipv6': family = socket.AF_INET6 if ret_val is True: private_ip = binascii.hexlify( socket.inet_pton(family, private_ip)) cps_obj = cps_object.CPSObject( module='vrf-firewall/ns-outgoing-service', qual='target', data={ outgoing_ip_svcs_attr('ni-name'): vrf_name, outgoing_ip_svcs_attr('af'): af, outgoing_ip_svcs_attr('public-ip'): public_ip_data, outgoing_ip_svcs_attr('protocol'): protocol, outgoing_ip_svcs_attr('public-port'): public_port, outgoing_ip_svcs_attr('private-ip'): private_ip, outgoing_ip_svcs_attr('private-port'): private_port }) params['change'] = cps_obj.get() return True elif operation == 'delete': ret_val, private_port, private_ip = dn_base_vrf_tool.process_outgoing_ip_svcs_config(False,\ _af[af], public_ip, _protocol[protocol],\ str(public_port), vrf_name) if ret_val is True: return True except Exception as e: log_msg = 'Faild to commit operation.' + e + params log_err(log_msg) return False log_msg = 'Operation:' + operation + ' VRF:' + vrf_name + ' family:'\ + _af[af] + ' public-ip' + public_ip + ' protocol:' + _protocol[protocol] + ' public-port:'\ + str(public_port) log_err(log_msg) return False
def get_incoming_ip_svcs_int(methods, params): log_info('Callback for incoming IP service reading') obj_attr_map = { 'ni-name': 'vrf_name', 'af': 'af', 'src-ip': 'src_ip', 'src-prefix-len': 'src_prefix_len', 'dst-ip': 'dst_ip', 'dst-prefix-len': 'dst_prefix_len', 'protocol': 'protocol', 'dst-port': 'dst_port', 'lower-dst-port': 'low_dst_port', 'upper-dst-port': 'high_dst_port', 'action': 'action', 'seq-num': 'seq_num', 'ifname': 'in_intf', 'id': 'rule_id' } obj = cps_object.CPSObject(obj=params['filter']) resp = params['list'] args = {} for key, val in obj_attr_map.items(): attr_name = incoming_ip_svcs_attr(key) try: attr_val = obj.get_attr_data(attr_name) except ValueError: attr_val = None if attr_val is not None: args[val] = attr_val # check af if 'af' in args and args['af'] is not None: af = args['af'] if af != socket.AF_INET and af != socket.AF_INET6: log_err('Invalid address family number %d' % af) return False # check source and destination IP if 'src_ip' in args and args['src_ip'] is not None: af = args['af'] if 'af' in args else None pfx_len = args['src_prefix_len'] if 'src_prefix_len' in args else None ip_tuple = normalize_ip_with_prefix(af, args['src_ip'], pfx_len) if ip_tuple is None: log_err('Invalid source IP %s for rule reading' % args['src_ip']) return False args['af'], args['src_ip'], args['src_prefix_len'] = ip_tuple if 'dst_ip' in args and args['dst_ip'] is not None: af = args['af'] if 'af' in args else None pfx_len = args['dst_prefix_len'] if 'dst_prefix_len' in args else None ip_tuple = normalize_ip_with_prefix(af, args['dst_ip'], pfx_len) if ip_tuple is None: log_err('Invalid destination IP %s for rule reading' % args['dst_ip']) return False args['af'], args['dst_ip'], args['dst_prefix_len'] = ip_tuple log_info('Input parameters:') for name, val in args.items(): if val is not None: log_info(' %-10s : %s' % (name, str(val))) return process_vrf_svcs_rule_get(resp, **args)
def config_incoming_ip_svcs_int(methods, params): obj = cps_object.CPSObject(obj=params['change']) in_param_list = {} log_info('Callback for incoming IP service configuration') def get_svcs_attr_val(attr_name, dft_val=None): attr_id = incoming_ip_svcs_attr(attr_name) try: attr_val = obj.get_attr_data(attr_id) except ValueError: attr_val = None if attr_val is None: attr_val = dft_val in_param_list[attr_name] = attr_val return attr_val operation = params['operation'] af = get_svcs_attr_val('af') vrf_name = get_svcs_attr_val('ni-name') protocol = get_svcs_attr_val('protocol') dst_port = get_svcs_attr_val('dst-port') low_dst_port = get_svcs_attr_val('lower-dst-port') high_dst_port = get_svcs_attr_val('upper-dst-port') action = get_svcs_attr_val('action') src_ip = get_svcs_attr_val('src-ip') src_prefix_len = get_svcs_attr_val('src-prefix-len') dst_ip = get_svcs_attr_val('dst-ip') dst_prefix_len = get_svcs_attr_val('dst-prefix-len') in_intf = get_svcs_attr_val('ifname') if operation == 'create': # set default seq number to 0 for create seq_num = get_svcs_attr_val('seq-num', 0) else: seq_num = get_svcs_attr_val('seq-num') rule_id = get_svcs_attr_val('id') # check source and destination IP if src_ip is not None: ip_tuple = normalize_ip_with_prefix(af, src_ip, src_prefix_len) if ip_tuple is None: log_err('Failed to normalize source IP with prefix') return False orig_af = af af, src_ip, src_prefix_len = ip_tuple if orig_af is None: log_info('Address family %d is deduced from input source IP %s' % (af, src_ip)) in_param_list['af'] = af in_param_list['src-ip'] = src_ip in_param_list['src-prefix-len'] = src_prefix_len if dst_ip is not None: ip_tuple = normalize_ip_with_prefix(af, dst_ip, dst_prefix_len) if ip_tuple is None: log_err('Failed to normalize destination IP with prefix') return False orig_af = af af, dst_ip, dst_prefix_len = ip_tuple if orig_af is None: log_info( 'Address family %d is deduced from input destination IP %s' % (af, dst_ip)) in_param_list['af'] = af in_param_list['dst-ip'] = dst_ip in_param_list['dst-prefix-len'] = dst_prefix_len # check lower & upper destination ports if low_dst_port is not None and high_dst_port is None: log_err('Missing upper-dst-port for VTY ACL rule configuration') return False if low_dst_port is None and high_dst_port is not None: log_err('Missing lower-dst-port for VTY ACL rule configuration') return False if (low_dst_port is not None or high_dst_port is not None) and dst_port is not None: log_err('Invalid VTY ACL rule configuration, \ dst port attribute cannot be configured along with dst port range attributes' ) return False """ The input object stands for VTY ACL configuration request if: 1. Destination L4 port attribute is not given or given value is 0, 2. Or Source IP address attribute is given, 3. Or lower & upper destination L4 port attributes are given. For all other cases, input object stands for VRF incoming IP service request. """ def is_vty_acl_config(): if dst_port is None or dst_port == 0: return True if src_ip is not None: return True if low_dst_port is not None and high_dst_port is not None: return True return False log_info('Input parameters:') for name, val in in_param_list.items(): if val is not None: if name == 'src-ip' or name == 'dst-ip': log_info(' %-10s - %s' % (name, binascii.hexlify(val))) else: log_info(' %-10s - %s' % (name, str(val))) if is_vty_acl_config(): log_info('Handle VTY ACL configuration, operation: %s' % operation) rule_type = VrfSvcsRuleType.RULE_TYPE_ACL reqd_input = ['ni-name', 'af', 'src-ip', 'src-prefix-len', 'action'] else: log_info('Handle incoming IP configuration, operation: %s' % operation) rule_type = VrfSvcsRuleType.RULE_TYPE_IP reqd_input = ['af', 'ni-name', 'protocol', 'dst-port'] if vrf_name == 'default': reqd_input.append('action') def check_rule_input(missed_attr_list=None): """ The keys to identify a rule """ if operation == 'delete': """ For delete operation, either rule ID or rule keys need to be given to find rule to be deleted """ if rule_id is not None: return True else: if check_attr_list(reqd_input, in_param_list, missed_attr_list): return True elif operation == 'set': """ For set operation, rule ID is the only required input to find the rule to be updated. And the attributes of the rule will be changed to attribute value given by input """ if rule_id is not None: return True else: if missed_attr_list is not None: missed_attr_list.append('id') elif operation == 'create': """ For create operation, all key attributes plus sequence number need to be given by input """ if check_attr_list(reqd_input + ['seq-num'], in_param_list, missed_attr_list): return True return False not_found_list = [] if not check_rule_input(not_found_list): log_err('Mandatory attributes %s not found for operation %s' % (str(not_found_list), operation)) return False if operation == 'create': if rule_type == VrfSvcsRuleType.RULE_TYPE_IP and vrf_name != 'default': """ If it is IP forwarding rule and the name space is not default, we set its action type as DNAT """ dst_ip = dn_base_vrf_tool.get_veth_ip(af, vrf_name) action = VrfSvcsRuleAction.RULE_ACTION_DNAT else: if (dst_port is not None and protocol != VrfSvcsRuleProto.RULE_PROTO_TCP and protocol != VrfSvcsRuleProto.RULE_PROTO_UDP): log_err( 'L4 destination port filter must with protocol type TCP or UDP' ) return False if (low_dst_port is not None and protocol != VrfSvcsRuleProto.RULE_PROTO_TCP and protocol != VrfSvcsRuleProto.RULE_PROTO_UDP): log_err( 'L4 destination port range filter must with protocol type TCP or UDP' ) return False ret_val = process_vrf_svcs_rule_add(rule_type, vrf_name, action, af, src_ip=src_ip, src_prefix_len=src_prefix_len, dst_ip=dst_ip, dst_prefix_len=dst_prefix_len, seq_num=seq_num, protocol=protocol, dst_port=dst_port, low_dst_port=low_dst_port, high_dst_port=high_dst_port, in_intf=in_intf, rule_id=rule_id) if ret_val is None: log_err( 'Failed to add incoming IP rule: VRF %s AF %s%s%s%s%s%s%s%s%s%s%s' % (vrf_name, _af[af], (' IIF %s' % in_intf if in_intf is not None else ' '), (' SRC %s/%d' % (get_ip_str(af, src_ip), src_prefix_len) if src_ip is not None and src_prefix_len is not None else ''), (' DST %s/%d' % (get_ip_str(af, dst_ip), dst_prefix_len) if dst_ip is not None and dst_prefix_len is not None else ''), (' PROTO %s' % _protocol[protocol] if protocol is not None else ''), (' PORT %d' % dst_port if dst_port is not None else ''), (' PORT RANGE %d-%d' % (low_dst_port, high_dst_port) if low_dst_port is not None else ''), (' SEQ %d' % seq_num if seq_num is not None else ''), (' ACTION %s' % _action[action] if action is not None else ''), (' DST %s' % get_ip_str(af, dst_ip) if dst_ip is not None else ''), (' ID %d' % rule_id if rule_id is not None else ''))) return False if rule_id is not None and ret_val != rule_id: log_err('Given rule id %d is not equal to actually used id %d' % (rule_id, ret_val)) obj.add_attr(incoming_ip_svcs_attr('id'), ret_val) params['change'] = obj.get() elif operation == 'set': ret_val = process_vrf_svcs_rule_set(rule_id, src_ip=src_ip, src_prefix_len=src_prefix_len, protocol=protocol, dst_ip=dst_ip, dst_prefix_len=dst_prefix_len, dst_port=dst_port, action=action, low_dst_port=low_dst_port, high_dst_port=high_dst_port, seq_num=seq_num, in_intf=in_intf) if not ret_val: log_err('Failed to update rule with ID %d' % rule_id) return False elif operation == 'delete': if rule_id is None: if rule_type == VrfSvcsRuleType.RULE_TYPE_IP and vrf_name != 'default': """ If it is IP forwarding rule and the name space is not default, we set its action type as DNAT """ dst_ip = dn_base_vrf_tool.get_veth_ip(af, vrf_name) action = VrfSvcsRuleAction.RULE_ACTION_DNAT ret_val = process_vrf_svcs_rule_del(rule_type, vrf_name, action, af, src_ip=src_ip, src_prefix_len=src_prefix_len, dst_ip=dst_ip, dst_prefix_len=dst_prefix_len, protocol=protocol, dst_port=dst_port, low_dst_port=low_dst_port, high_dst_port=high_dst_port, in_intf=in_intf) else: ret_val = process_vrf_svcs_rule_del_by_id(rule_id) if not ret_val: log_err('Failed to delete rule') return False else: log_err('Invalid operation type %s' % operation) return False return True
def proc_rule(op, rule, idx=None): if (op.lower() == 'delete' and rule.vrf_name != 'default' and not IptablesHandler.is_vrf_valid(rule.vrf_name)): log_info('VRF %s is not opened, bypass iptables setting.' % rule.vrf_name) return True if op == 'replace' and idx is None: log_err('Missing rule index for replace operation') return False iptables = 'iptables' if rule.af == socket.AF_INET else 'ip6tables' if rule.vrf_name == 'default': ipt_prefix = ['/sbin/%s' % iptables] tbl_name = (None if rule.rule_type == rule.RULE_TYPE_IP else 'raw') else: ipt_prefix = [iplink_cmd, 'netns', 'exec', rule.vrf_name, iptables] tbl_name = ('nat' if rule.rule_type == rule.RULE_TYPE_IP else 'raw') if tbl_name is not None: ipt_prefix += ['-t', tbl_name] flt_args = [] if rule.src_ip is not None: flt_args += [ '-s', '%s%s' % (socket.inet_ntop(rule.af, rule.src_ip), ('/%d' % rule.prefix_len if rule.prefix_len is not None else '')) ] if rule.protocol is not None: flt_args += ['-p', rule.get_proto_name()] if rule.dst_port is not None: flt_args += ['--dport', str(rule.dst_port)] if rule.rule_type == rule.RULE_TYPE_IP: if rule.vrf_name == 'default': flt_args += ['!', '-i', 'vdef-nsid%d' % MGMT_VRF_ID] chain_name = 'INPUT' else: chain_name = 'VRF' else: chain_name = 'PREROUTING' if rule.in_intf is not None: if rule.negtive: flt_args.append('!') flt_args += ['-i', rule.in_intf] flt_args += ['-j', rule.get_action_name(True).upper()] if rule.action == rule.RULE_ACTION_DNAT: flt_args += [ '--to-destination', socket.inet_ntop(rule.af, rule.dst_ip) ] elif rule.action == rule.RULE_ACTION_REJECT: flt_args += ['--set-mark', str(rej_rule_mark_value)] if op.lower() == 'insert': if idx is None: chain_args = ['-A', chain_name] else: chain_args = ['-I', chain_name, '%d' % (idx + 1)] cmd = ipt_prefix + chain_args + flt_args elif op.lower() == 'delete': chain_args = ['-D', chain_name] if idx is not None: chain_args.append('%d' % (idx + 1)) cmd = ipt_prefix + chain_args if idx is None: cmd += flt_args elif op.lower() == 'replace': chain_args = ['-R', chain_name] chain_args.append('%d' % (idx + 1)) cmd = ipt_prefix + chain_args + flt_args elif op.lower() == 'check': chain_args = ['-C', chain_name] cmd = ipt_prefix + chain_args + flt_args else: log_err('Invalid operation %s' % op) return False log_info('CMD: %s' % ' '.join(cmd)) res = [] return run_command(cmd, res, op.lower() != 'check') == 0
def config_outgoing_ip_svcs_int(methods, params): obj = cps_object.CPSObject(obj=params['change']) in_param_list = {} log_info('Callback for outgoing IP service configuration') def get_svcs_attr_val(attr_name, dft_val=None): attr_id = outgoing_ip_svcs_attr(attr_name) try: attr_val = obj.get_attr_data(attr_id) except ValueError: attr_val = None if attr_val is None: attr_val = dft_val in_param_list[attr_name] = attr_val return attr_val operation = params['operation'] vrf_name = get_svcs_attr_val('ni-name') af = get_svcs_attr_val('af') public_ip_attr = get_svcs_attr_val('public-ip') outgoing_source_ip_attr = get_svcs_attr_val('outgoing-source-ip') protocol = get_svcs_attr_val('protocol') public_port = get_svcs_attr_val('public-port') private_ip_attr = get_svcs_attr_val('private-ip') private_port = get_svcs_attr_val('private-port') rule_id = get_svcs_attr_val('id') orig_af = af public_ip = None # check public IP if public_ip_attr is not None: af_ip = normalize_ip_with_prefix(orig_af, public_ip_attr) if af_ip is None: log_err('Invalid public IP %s for rule configuration' % public_ip_attr) return False af, public_ip, _ = af_ip if orig_af is None: log_info('Address family %d is deducted from input public IP %s' % (af, public_ip_attr)) in_param_list['af'] = af in_param_list['public-ip'] = public_ip orig_af = af outgoing_source_ip = None # check outgoing source IP if outgoing_source_ip_attr is not None: af_ip = normalize_ip_with_prefix(orig_af, outgoing_source_ip_attr) if af_ip is None: log_err('Invalid outgoing source IP %s for rule configuration' % outgoing_source_ip_attr) return False af, outgoing_source_ip, _ = af_ip if orig_af is None: log_info('Address family %d is deducted from input source IP %s' % (af, outgoing_source_ip_attr)) in_param_list['af'] = af in_param_list['outgoing-source-ip'] = outgoing_source_ip orig_af = af private_ip = None # check private IP if private_ip_attr is not None: af_ip = normalize_ip_with_prefix(orig_af, private_ip_attr) if af_ip is None: log_err('Invalid private IP %s for rule configuration' % private_ip_attr) return False af, private_ip, _ = af_ip if orig_af is None: log_info('Address family %d is deducted from input private IP %s' % (af, private_ip_attr)) in_param_list['af'] = af in_param_list['private-ip'] = private_ip """ The input object stands for Source IP configuration request if: 1. Outgoing source IP attribute is given For all other cases, input object stands for VRF outgoing IP service binding request. """ def is_egress_source_ip_config(): if outgoing_source_ip is not None: return True return False log_info('Input parameters:') for name, val in in_param_list.items(): if val is not None: if name == 'public-ip' or name == 'outgoing-source-ip' or name == 'private-ip': log_info(' %-10s - %s' % (name, binascii.hexlify(val))) else: log_info(' %-10s - %s' % (name, str(val))) if is_egress_source_ip_config(): log_info('Handle Outgoing Source IP configuration, operation: %s' % operation) rule_type = VrfSvcsRuleType.RULE_TYPE_SNAT action = VrfSvcsRuleAction.RULE_ACTION_SNAT reqd_input = [ 'ni-name', 'af', 'public-ip', 'protocol', 'public-port', 'outgoing-source-ip' ] else: log_info( 'Handle Outgoing IP service binding configuration, operation: %s' % operation) rule_type = VrfSvcsRuleType.RULE_TYPE_OUT_IP action = VrfSvcsRuleAction.RULE_ACTION_DNAT reqd_input = ['ni-name', 'af', 'public-ip', 'protocol', 'public-port'] def check_rule_input(missed_attr_list=None): """ The keys to identify a rule """ if operation == 'delete': """ For delete operation, either rule ID or rule keys need to be given to find rule to be deleted """ if rule_id is not None: return True else: if check_attr_list(reqd_input, in_param_list, missed_attr_list): return True elif operation == 'set': """ set operation, not supported on outgoing IP service configuration """ return False elif operation == 'create': """ For create operation, all key attributes need to be given """ if check_attr_list(reqd_input, in_param_list, missed_attr_list): return True return False not_found_list = [] if not check_rule_input(not_found_list): log_err( 'Operation not support or Mandatory attributes %s not found for operation %s' % (str(not_found_list), operation)) return False log_info( 'Outgoing IP service rule: Operation %s VRF %s AF %s%s%s%s%s%s' % (operation, vrf_name, (_af[af] if af is not None else ' '), (' public-ip %s' % (get_ip_str(af, public_ip)) if public_ip is not None else ''), (' protocol %s' % _protocol[protocol] if protocol is not None else ''), (' public-port %d' % public_port if public_port is not None else ''), (' outgoing-source-ip %s' % (get_ip_str(af, outgoing_source_ip)) if outgoing_source_ip is not None else ''), (' ID %d' % rule_id if rule_id is not None else ''))) try: if operation == 'set': return False elif operation == 'create': ret_val, private_ip, private_port = process_vrf_outgoing_svcs_rule_add( rule_type, vrf_name, action, af, dst_ip=public_ip, protocol=protocol, dst_port=public_port, out_src_ip=outgoing_source_ip, private_ip=private_ip, private_port=private_port, rule_id=rule_id) log_info( '%s in adding outgoing %s: VRF %s AF %s%s%s%s%s%s%s%s%s' % (('Success' if ret_val is not None else 'Failure'), ('%s rule' % 'SNAT' if rule_type == VrfSvcsRuleType.RULE_TYPE_SNAT else 'IP'), vrf_name, (_af[af] if af is not None else ' '), (' PROTO %s' % _protocol[protocol] if protocol is not None else ''), (' DST IP %s' % get_ip_str(af, public_ip) if public_ip is not None else ''), (' PORT %d' % public_port if public_port is not None else ''), (' ACTION %s' % _action[action] if action is not None else ''), (' SRC IP %s' % get_ip_str(af, outgoing_source_ip) if outgoing_source_ip is not None else ''), (' PRIVATE IP %s' % get_ip_str(af, private_ip) if private_ip is not None else ''), (' PRIVATE PORT %d' % private_port if private_port is not None else ''), (' ID %d' % ret_val if ret_val is not None else ''))) if ret_val is not None: if rule_type == VrfSvcsRuleType.RULE_TYPE_SNAT: #SNAT flow obj.add_attr(outgoing_ip_svcs_attr('id'), ret_val) params['change'] = obj.get() else: #DNAT - service binding flow private_ip = binascii.hexlify(private_ip) cps_obj = cps_object.CPSObject( module='vrf-firewall/ns-outgoing-service', qual='target', data={ outgoing_ip_svcs_attr('id'): ret_val, outgoing_ip_svcs_attr('ni-name'): vrf_name, outgoing_ip_svcs_attr('af'): af, outgoing_ip_svcs_attr('public-ip'): public_ip_attr, outgoing_ip_svcs_attr('protocol'): protocol, outgoing_ip_svcs_attr('public-port'): public_port, outgoing_ip_svcs_attr('private-ip'): private_ip, outgoing_ip_svcs_attr('private-port'): private_port }) params['change'] = cps_obj.get() return True elif operation == 'delete': if rule_id is None: ret_val = process_vrf_outgoing_svcs_rule_del( rule_type, vrf_name, action, af, dst_ip=public_ip, protocol=protocol, dst_port=public_port, out_src_ip=outgoing_source_ip, private_ip=private_ip, private_port=private_port) else: ret_val = process_vrf_outgoing_svcs_rule_del_by_id(rule_id) if ret_val is True: #deleted successfully return True except Exception as e: log_msg = ('%s %s %s' % ('Failed to commit operation.', e, params)) log_err(log_msg) return False log_err( 'Outgoing IP service rule: Operation %s Failed VRF %s AF %s%s%s%s%s%s' % (operation, vrf_name, (_af[af] if af is not None else ' '), (' public-ip %s' % (get_ip_str(af, public_ip)) if public_ip is not None else ''), (' protocol %s' % _protocol[protocol] if protocol is not None else ''), (' public-port %d' % public_port if public_port is not None else ''), (' outgoing-source-ip %s' % (get_ip_str(af, outgoing_source_ip)) if outgoing_source_ip is not None else ''), (' ID %d' % rule_id if rule_id is not None else ''))) return False
def update_rule(cls, rule_id, **params): log_info('Handling update rule: ID %d param %s' % (rule_id, params)) cls.mutex.acquire() found_rule = cls.find_rule_by_id(rule_id) if found_rule is None: log_err('Rule ID %d not found for update' % rule_id) cls.mutex.release() return False old_rule, _ = found_rule upd_rule = copy.deepcopy(old_rule) changed_attrs = set() def check_and_set(rule, key, val): try: orig_val = getattr(rule, key) except AttributeError: orig_val = None if val != orig_val: if val is not None: setattr(rule, key, val) else: delattr(rule, key) changed_attrs.add(key) for key, val in params.items(): if val is not None: check_and_set(upd_rule, key, val) if len(changed_attrs) == 0: log_info('There is no change to be updated, just return') cls.mutex.release() return True log_info('old_rule: %s' % old_rule) log_info('new_rule: %s' % upd_rule) match_rule = cls.find_rule_by_match(upd_rule) if match_rule is not None and match_rule.rule_id != old_rule.rule_id: log_err('The updating rule already exists') cls.mutex.release() return False repl_attrs = { 'src_ip', 'prefix_len', 'protocol', 'dst_port', 'action', 'in_intf' } no_repl_attrs = changed_attrs.difference(repl_attrs) if len(no_repl_attrs) > 0: log_info( 'Non-replacable attributes %s changed, delete and add rule' % no_repl_attrs) if not cls.delete_rule_by_id(rule_id): log_err('Failed to delete existing rule by ID') cls.mutex.release() return False ret_val = cls.insert_rule(upd_rule) if not ret_val: log_err('Failed to insert updated rule') cls.insert_rule(old_rule) else: log_info('Only replacable attributes changed, just replace rule') ret_val = cls.replace_rule(rule_id, upd_rule) if not ret_val: log_err('Failed to replace rule') cls.mutex.release() if ret_val: log_info('Rule updated') return ret_val
def get_outgoing_ip_svcs_int(methods, params): log_info('Callback for outgoing IP service reading') obj_attr_map = { 'ni-name': 'vrf_name', 'af': 'af', 'public-ip': 'dst_ip', 'protocol': 'protocol', 'public-port': 'dst_port', 'private-ip': 'private_ip', 'private-port': 'private_port', 'outgoing-source-ip': 'out_src_ip', 'id': 'rule_id' } obj = cps_object.CPSObject(obj=params['filter']) resp = params['list'] args = {} for key, val in obj_attr_map.items(): attr_name = outgoing_ip_svcs_attr(key) try: attr_val = obj.get_attr_data(attr_name) except ValueError: attr_val = None if attr_val is not None: args[val] = attr_val # check af if 'af' in args and args['af'] is not None: af = args['af'] if af != socket.AF_INET and af != socket.AF_INET6: log_err('Invalid address family number %d' % af) return False # check public IP if 'dst_ip' in args and args['dst_ip'] is not None: af = args['af'] if 'af' in args else None af_ip = normalize_ip_with_prefix(af, args['dst_ip']) if af_ip is None: log_err('Invalid public IP %s for rule reading' % args['dst_ip']) return False args['af'], args['dst_ip'], _ = af_ip # check source IP if 'out_src_ip' in args and args['out_src_ip'] is not None: af = args['af'] if 'af' in args else None af_ip = normalize_ip_with_prefix(af, args['out_src_ip']) if af_ip is None: log_err('Invalid outgoing source IP %s for rule reading' % args['out_src_ip']) return False args['af'], args['out_src_ip'], _ = af_ip # check private IP if 'private_ip' in args and args['private_ip'] is not None: af = args['af'] if 'af' in args else None af_ip = normalize_ip_with_prefix(af, args['private_ip']) if af_ip is None: log_err('Invalid private IP %s for rule reading' % args['private_ip']) return False args['af'], args['private_ip'], _ = af_ip log_info('Input parameters:') for name, val in args.items(): if val is not None: if name == 'dst_ip' or name == 'out_src_ip': log_info(' %-10s - %s' % (name, binascii.hexlify(val))) else: log_info(' %-10s : %s' % (name, str(val))) return process_vrf_outgoing_svcs_rule_get(resp, **args)
def config_incoming_ip_svcs_int(methods, params): obj = cps_object.CPSObject(obj=params['change']) in_param_list = {} log_info('Callback for incoming IP service configuration') def get_svcs_attr_val(attr_name, dft_val=None): attr_id = incoming_ip_svcs_attr(attr_name) try: attr_val = obj.get_attr_data(attr_id) except ValueError: attr_val = None if attr_val is None: attr_val = dft_val in_param_list[attr_name] = attr_val return attr_val operation = params['operation'] af = get_svcs_attr_val('af') vrf_name = get_svcs_attr_val('ni-name') protocol = get_svcs_attr_val('protocol') dst_port = get_svcs_attr_val('dst-port') action = get_svcs_attr_val('action') src_ip = get_svcs_attr_val('src-ip') prefix_len = get_svcs_attr_val('src-prefix-len') if operation == 'create': # set default seq number to 0 for create seq_num = get_svcs_attr_val('seq-num', 0) else: seq_num = get_svcs_attr_val('seq-num') rule_id = get_svcs_attr_val('id') # check source IP if src_ip is not None: af_ip = check_ip_validity(af, src_ip) if af_ip is None: log_err('Invalid source IP %s for rule configuration' % src_ip) return False orig_af = af af, src_ip = af_ip if orig_af is None: log_info('Address family %d is deducted from input source IP %s' % (af, src_ip)) in_param_list['af'] = af in_param_list['src-ip'] = src_ip # set default prefix len if prefix_len is None and af is not None: if af == socket.AF_INET: prefix_len = 32 elif af == socket.AF_INET6: prefix_len = 128 in_param_list['src-prefix-len'] = prefix_len """ The input object stands for VTY ACL configuration request if: 1. Destination L4 port attribute is not given or given value is 0. 2. Or Source IP address attribute is given For all other cases, input object stands for VRF incoming IP service request. """ def is_vty_acl_config(): if dst_port is None or dst_port == 0: return True if src_ip is not None: return True return False def check_attr_list(attr_list, missed_list=None): ret_val = True for attr in attr_list: if attr not in in_param_list or in_param_list[attr] is None: ret_val = False if missed_list is not None: missed_list.append(attr) return ret_val def get_ip_str(ip_bin): for af in [socket.AF_INET, socket.AF_INET6]: try: ip_str = socket.inet_ntop(af, ip_bin) return ip_str except ValueError: continue return '-' log_info('Input parameters:') for name, val in in_param_list.items(): if val is not None: if name == 'src-ip': log_info(' %-10s - %s' % (name, binascii.hexlify(val))) else: log_info(' %-10s - %s' % (name, str(val))) if is_vty_acl_config(): log_info('Handle VTY ACL configuration, operation: %s' % operation) rule_type = VrfIncomingSvcsRule.RULE_TYPE_ACL reqd_input = ['ni-name', 'af', 'src-ip', 'src-prefix-len', 'action'] else: log_info('Handle incoming IP configuration, operation: %s' % operation) rule_type = VrfIncomingSvcsRule.RULE_TYPE_IP reqd_input = ['af', 'ni-name', 'protocol', 'dst-port'] if vrf_name == 'default': reqd_input.append('action') def check_rule_input(missed_attr_list=None): """ The keys to identify a rule """ if operation == 'delete': """ For delete operation, either rule ID or rule keys need to be given to find rule to be deleted """ if rule_id is not None: return True else: if check_attr_list(reqd_input, missed_attr_list): return True elif operation == 'set': """ For set operation, rule ID is the only required input to find the rule to be updated. And the attributes of the rule will be changed to attribute value given by input """ if rule_id is not None: return True else: if missed_attr_list is not None: missed_attr_list.append('id') elif operation == 'create': """ For create operation, all key attributes plus sequence number need to be given by input """ if check_attr_list(reqd_input + ['seq-num'], missed_attr_list): return True return False not_found_list = [] if not check_rule_input(not_found_list): log_err('Mandatory attributes %s not found for operation %s' % (str(not_found_list), operation)) return False if operation == 'create': if rule_type == VrfIncomingSvcsRule.RULE_TYPE_IP and vrf_name != 'default': """ If it is IP forwarding rule and the name space is not default, we set its action type as DNAT """ dst_ip = dn_base_vrf_tool.get_veth_ip(af, vrf_name) action = VrfIncomingSvcsRule.RULE_ACTION_DNAT else: if (dst_port is not None and protocol != VrfIncomingSvcsRule.RULE_PROTO_TCP and protocol != VrfIncomingSvcsRule.RULE_PROTO_UDP): log_err( 'L4 destination port filter must with protocol type TCP or UDP' ) return False dst_ip = None ret_val = process_vrf_svcs_rule_add(rule_type, vrf_name, action, af, src_ip=src_ip, prefix_len=prefix_len, dst_ip=dst_ip, seq_num=seq_num, protocol=protocol, dst_port=dst_port, rule_id=rule_id) if ret_val is None: log_err( 'Failed to add incoming IP rule: VRF %s AF %s%s%s%s%s%s%s%s' % (vrf_name, _af[af], (' SRC %s/%d' % (get_ip_str(src_ip), prefix_len) if src_ip is not None and prefix_len is not None else ''), (' PROTO %s' % _protocol[protocol] if protocol is not None else ''), (' PORT %d' % dst_port if dst_port is not None else ''), (' SEQ %d' % seq_num if seq_num is not None else ''), (' ACTION %s' % _action[action] if action is not None else ''), (' DST %s' % get_ip_str(dst_ip) if dst_ip is not None else ''), (' ID %d' % rule_id if rule_id is not None else ''))) return False if rule_id is not None and ret_val != rule_id: log_err('Given rule id %d is not equal to actually used id %d' % (rule_id, ret_val)) obj.add_attr(incoming_ip_svcs_attr('id'), ret_val) params['change'] = obj.get() elif operation == 'set': ret_val = process_vrf_svcs_rule_set(rule_id, src_ip=src_ip, prefix_len=prefix_len, protocol=protocol, dst_port=dst_port, action=action, seq_num=seq_num) if not ret_val: log_err('Failed to update rule with ID %d' % rule_id) return False elif operation == 'delete': if rule_id is None: if rule_type == VrfIncomingSvcsRule.RULE_TYPE_IP and vrf_name != 'default': """ If it is IP forwarding rule and the name space is not default, we set its action type as DNAT """ dst_ip = dn_base_vrf_tool.get_veth_ip(af, vrf_name) action = VrfIncomingSvcsRule.RULE_ACTION_DNAT else: dst_ip = None ret_val = process_vrf_svcs_rule_del(rule_type, vrf_name, action, af, src_ip=src_ip, prefix_len=prefix_len, dst_ip=dst_ip, protocol=protocol, dst_port=dst_port) else: ret_val = process_vrf_svcs_rule_del_by_id(rule_id) if not ret_val: log_err('Failed to delete rule') return False else: log_err('Invalid operation type %s' % operation) return False return True