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 test_rule_api(): rid1 = cfg.process_vrf_svcs_rule_add(cfg.VrfSvcsRuleType.RULE_TYPE_ACL, 'test_management', cfg.VrfSvcsRuleAction.RULE_ACTION_DENY, socket.AF_INET, src_ip = socket.inet_pton(socket.AF_INET, '1.1.1.0'), src_prefix_len = 24, dst_ip = socket.inet_pton(socket.AF_INET, '8.8.8.0'), dst_prefix_len = 24, seq_num = 100) assert rid1 is not None rid2 = cfg.process_vrf_svcs_rule_add(cfg.VrfSvcsRuleType.RULE_TYPE_ACL, 'test_management', cfg.VrfSvcsRuleAction.RULE_ACTION_ALLOW, socket.AF_INET6, src_ip = socket.inet_pton(socket.AF_INET6, '1:1::'), src_prefix_len = 64, dst_ip = socket.inet_pton(socket.AF_INET6, '2:2::'), dst_prefix_len = 64, seq_num = 101) assert rid2 is not None rid3 = cfg.process_vrf_svcs_rule_add(cfg.VrfSvcsRuleType.RULE_TYPE_IP, 'test_management', cfg.VrfSvcsRuleAction.RULE_ACTION_DNAT, socket.AF_INET, protocol = cfg.VrfSvcsRuleProto.RULE_PROTO_TCP, dst_port = 1234, dst_ip = socket.inet_pton(socket.AF_INET, '3.3.3.3')) assert rid3 is not None rid4 = cfg.process_vrf_svcs_rule_add(cfg.VrfSvcsRuleType.RULE_TYPE_IP, 'test_management', cfg.VrfSvcsRuleAction.RULE_ACTION_DNAT, socket.AF_INET6, protocol = cfg.VrfSvcsRuleProto.RULE_PROTO_TCP, dst_port = 1235, dst_ip = socket.inet_pton(socket.AF_INET6, '3::3')) assert rid4 is not None assert cfg.process_vrf_svcs_rule_set(rid1, src_ip = socket.inet_pton(socket.AF_INET, '2.2.2.0')) assert cfg.process_vrf_svcs_rule_set(rid2, seq_num = 200) assert not cfg.process_vrf_svcs_rule_del(cfg.VrfSvcsRuleType.RULE_TYPE_ACL, 'test_management', cfg.VrfSvcsRuleAction.RULE_ACTION_DENY, socket.AF_INET, src_ip = socket.inet_pton(socket.AF_INET, '1.1.1.0'), src_prefix_len = 24) assert cfg.process_vrf_svcs_rule_del(cfg.VrfSvcsRuleType.RULE_TYPE_ACL, 'test_management', cfg.VrfSvcsRuleAction.RULE_ACTION_DENY, socket.AF_INET, src_ip = socket.inet_pton(socket.AF_INET, '2.2.2.0'), src_prefix_len = 24, dst_ip = socket.inet_pton(socket.AF_INET, '8.8.8.0'), dst_prefix_len = 24) assert not cfg.process_vrf_svcs_rule_del_by_id(rid1) assert cfg.process_vrf_svcs_rule_del_by_id(rid2) resp = [] assert cfg.process_vrf_svcs_rule_get(resp) assert len(resp) == 2 assert cfg.process_vrf_svcs_rule_del_by_id(rid3) assert cfg.process_vrf_svcs_rule_del_by_id(rid4)
def create_default_lo_pkts_rule(): loopback_ip_str = '127.0.0.1' loopback_intf = 'lo' rule_id = process_vrf_svcs_rule_add( VrfSvcsRuleType.RULE_TYPE_IP, 'default', VrfSvcsRuleAction.RULE_ACTION_ALLOW, socket.AF_INET, src_ip=socket.inet_pton(socket.AF_INET, loopback_ip_str), src_prefix_len=32, dst_ip=socket.inet_pton(socket.AF_INET, loopback_ip_str), dst_prefix_len=32, high_prio=True, in_intf=loopback_intf) if rule_id is None: log_err('Failed to create default rule to accept pkts on lo') return (False, rule_id) return (True, rule_id)
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 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 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