Loading src/device/service/drivers/gnmi_openconfig/handlers/Acl.py +19 −9 Original line number Diff line number Diff line Loading @@ -30,7 +30,8 @@ _TFS_OC_RULE_TYPE = { _TFS_OC_FWD_ACTION = { 'ACLFORWARDINGACTION_DROP': 'DROP', 'ACLFORWARDINGACTION_ACCEPT': 'ACCEPT', 'ACLFORWARDINGACTION_REJECT': 'REJECT', #'ACLFORWARDINGACTION_REJECT': 'REJECT', # Correct according to OpenConfig. 'ACLFORWARDINGACTION_REJECT': 'DROP', # - Arista EOS only supports ACCEPT/DROP } _OC_TFS_RULE_TYPE = {v: k for k, v in _TFS_OC_RULE_TYPE.items()} Loading Loading @@ -89,7 +90,7 @@ class AclHandler(_Handler): y_entries = y_set.create_path('acl-entries') for entry in rs.get('entries', []): seq = int(entry['sequence_id']) m_ = entry['match'] m_ = entry.get('match', dict()) src_address = m_.get('src_address', '0.0.0.0/0') dst_address = m_.get('dst_address', '0.0.0.0/0') src_port = m_.get('src_port') Loading @@ -110,10 +111,9 @@ class AclHandler(_Handler): if src_port or dst_port: y_trans = y_e.create_path('transport') if src_port: y_trans.create_path("config/source-port", int(src_port)) y_trans.create_path('config/source-port', int(src_port)) if dst_port: y_trans.create_path("config/destination-port", int(dst_port)) y_ipv4.create_path('config/protocol', int(proto)) y_trans.create_path('config/destination-port', int(dst_port)) y_act = y_e.create_path('actions') y_act.create_path('config/forwarding-action', act) Loading Loading @@ -183,14 +183,24 @@ class AclHandler(_Handler): act = ace.get('actions', {}).get('config', {}).get('forwarding-action', 'DROP') fwd_tfs = _OC_TFS_FWD_ACTION[act] ipv4_cfg = ace.get('ipv4', {}).get('config', {}) transport_cfg = ace.get('transport', {}).get('config', {}) match_conditions = dict() if 'source-address' in ipv4_cfg: match_conditions['src_address'] = ipv4_cfg['source-address'] if 'destination-address' in ipv4_cfg: match_conditions['dst_address'] = ipv4_cfg['destination-address'] if 'protocol' in ipv4_cfg: match_conditions['protocol'] = ipv4_cfg['protocol'] if 'source-port' in transport_cfg: match_conditions['src_port'] = transport_cfg['source-port'] if 'destination-port' in transport_cfg: match_conditions['dst_port'] = transport_cfg['destination-port'] rule_set['entries'].append( { 'sequence_id': seq, 'match': { 'src_address': ipv4_cfg.get('source-address', ''), 'dst_address': ipv4_cfg.get('destination-address', ''), }, 'match': match_conditions, 'action': {'forward_action': fwd_tfs}, } ) Loading src/nbi/service/ietf_acl/Acl.py +6 −1 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ # limitations under the License. import json, logging, re from flask import jsonify from flask_restful import Resource from werkzeug.exceptions import NotFound from common.proto.context_pb2 import ConfigActionEnum, ConfigRule Loading @@ -20,6 +21,7 @@ from common.tools.context_queries.Device import get_device from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from nbi.service._tools.Authentication import HTTP_AUTH from nbi.service._tools.HttpStatusCodes import HTTP_NOCONTENT from .ietf_acl_parser import ietf_acl_from_config_rule_resource_value LOGGER = logging.getLogger(__name__) Loading Loading @@ -72,4 +74,7 @@ class Acl(Resource): del device.device_config.config_rules[:] device.device_config.config_rules.extend(delete_config_rules) device_client.ConfigureDevice(device) return None response = jsonify({}) response.status_code = HTTP_NOCONTENT return response src/nbi/service/ietf_acl/Acls.py +5 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ from common.tools.grpc.Tools import grpc_message_to_json_string from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from nbi.service._tools.Authentication import HTTP_AUTH from nbi.service._tools.HttpStatusCodes import HTTP_CREATED from .ietf_acl_parser import AclDirectionEnum, config_rule_from_ietf_acl from .YangValidator import YangValidator Loading Loading @@ -129,4 +130,7 @@ class Acls(Resource): device_client = DeviceClient() device_client.ConfigureDevice(device) return jsonify({}) response = jsonify({}) response.status_code = HTTP_CREATED return response src/nbi/service/ietf_acl/ietf_acl_parser.py +39 −15 Original line number Diff line number Diff line Loading @@ -28,9 +28,12 @@ class AclDirectionEnum(Enum): class Ipv4(BaseModel): dscp: int = 0 source_ipv4_network: str = Field(serialization_alias='source-ipv4-network', default='') destination_ipv4_network: str = Field( serialization_alias='destination-ipv4-network', default='' protocol: int = 0 source_ipv4_network: Optional[str] = Field( serialization_alias='source-ipv4-network', default=None ) destination_ipv4_network: Optional[str] = Field( serialization_alias='destination-ipv4-network', default=None ) Loading @@ -45,9 +48,15 @@ class Tcp(BaseModel): destination_port: Optional[Port] = Field(serialization_alias='destination-port', default=None) class Udp(BaseModel): source_port: Optional[Port] = Field(serialization_alias='source-port', default=None) destination_port: Optional[Port] = Field(serialization_alias='destination-port', default=None) class Matches(BaseModel): ipv4: Ipv4 = Ipv4() tcp: Optional[Tcp] = None udp: Optional[Udp] = None class Action(BaseModel): Loading Loading @@ -237,27 +246,42 @@ def config_rule_from_ietf_acl( def ietf_acl_from_config_rule_resource_value(config_rule_rv: Dict) -> Dict: rule_set = config_rule_rv['rule_set'] rule_set = config_rule_rv.get('rule_set', dict()) ace = [] for acl_entry in rule_set['entries']: match_ = acl_entry['match'] for acl_entry in rule_set.get('entries', list()): match_ = acl_entry.get('match', dict()) protocol = match_.get('protocol', 0) ipv4 = Ipv4( dscp=match_['dscp'], source_ipv4_network=match_['src_address'], destination_ipv4_network=match_['dst_address'], dscp=match_.get('dscp', 0), protocol=protocol, source_ipv4_network=match_.get('src_address'), destination_ipv4_network=match_.get('dst_address'), ) src_port = match_.get('src_port') src_port = None if src_port is None else Port(port=src_port) dst_port = match_.get('dst_port') dst_port = None if dst_port is None else Port(port=dst_port) tcp = None if match_['tcp_flags']: udp = None if protocol == 6: tcp = Tcp( flags=match_['tcp_flags'], source_port=Port(port=match_['src_port']), destination_port=Port(port=match_['dst_port']), flags=match_.get('tcp_flags', 0), source_port=src_port, destination_port=dst_port, ) matches = Matches(ipv4=ipv4, tcp=tcp) elif protocol == 17: udp = Udp( source_port=src_port, destination_port=dst_port, ) matches = Matches(ipv4=ipv4, tcp=tcp, udp=udp) ace.append( Ace( name=acl_entry['description'], name=acl_entry.get('description', ''), matches=matches, actions=Action( forwarding=TFS_IETF_FORWARDING_ACTION_MAPPING[ Loading src/tests/.gitlab-ci.yml +1 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ include: #- local: '/src/tests/ofc25/.gitlab-ci.yml' #- local: '/src/tests/ryu-openflow/.gitlab-ci.yml' - local: '/src/tests/qkd_end2end/.gitlab-ci.yml' - local: '/src/tests/acl_end2end/.gitlab-ci.yml' - local: '/src/tests/tools/mock_tfs_nbi_dependencies/.gitlab-ci.yml' - local: '/src/tests/tools/mock_qkd_node/.gitlab-ci.yml' Loading Loading
src/device/service/drivers/gnmi_openconfig/handlers/Acl.py +19 −9 Original line number Diff line number Diff line Loading @@ -30,7 +30,8 @@ _TFS_OC_RULE_TYPE = { _TFS_OC_FWD_ACTION = { 'ACLFORWARDINGACTION_DROP': 'DROP', 'ACLFORWARDINGACTION_ACCEPT': 'ACCEPT', 'ACLFORWARDINGACTION_REJECT': 'REJECT', #'ACLFORWARDINGACTION_REJECT': 'REJECT', # Correct according to OpenConfig. 'ACLFORWARDINGACTION_REJECT': 'DROP', # - Arista EOS only supports ACCEPT/DROP } _OC_TFS_RULE_TYPE = {v: k for k, v in _TFS_OC_RULE_TYPE.items()} Loading Loading @@ -89,7 +90,7 @@ class AclHandler(_Handler): y_entries = y_set.create_path('acl-entries') for entry in rs.get('entries', []): seq = int(entry['sequence_id']) m_ = entry['match'] m_ = entry.get('match', dict()) src_address = m_.get('src_address', '0.0.0.0/0') dst_address = m_.get('dst_address', '0.0.0.0/0') src_port = m_.get('src_port') Loading @@ -110,10 +111,9 @@ class AclHandler(_Handler): if src_port or dst_port: y_trans = y_e.create_path('transport') if src_port: y_trans.create_path("config/source-port", int(src_port)) y_trans.create_path('config/source-port', int(src_port)) if dst_port: y_trans.create_path("config/destination-port", int(dst_port)) y_ipv4.create_path('config/protocol', int(proto)) y_trans.create_path('config/destination-port', int(dst_port)) y_act = y_e.create_path('actions') y_act.create_path('config/forwarding-action', act) Loading Loading @@ -183,14 +183,24 @@ class AclHandler(_Handler): act = ace.get('actions', {}).get('config', {}).get('forwarding-action', 'DROP') fwd_tfs = _OC_TFS_FWD_ACTION[act] ipv4_cfg = ace.get('ipv4', {}).get('config', {}) transport_cfg = ace.get('transport', {}).get('config', {}) match_conditions = dict() if 'source-address' in ipv4_cfg: match_conditions['src_address'] = ipv4_cfg['source-address'] if 'destination-address' in ipv4_cfg: match_conditions['dst_address'] = ipv4_cfg['destination-address'] if 'protocol' in ipv4_cfg: match_conditions['protocol'] = ipv4_cfg['protocol'] if 'source-port' in transport_cfg: match_conditions['src_port'] = transport_cfg['source-port'] if 'destination-port' in transport_cfg: match_conditions['dst_port'] = transport_cfg['destination-port'] rule_set['entries'].append( { 'sequence_id': seq, 'match': { 'src_address': ipv4_cfg.get('source-address', ''), 'dst_address': ipv4_cfg.get('destination-address', ''), }, 'match': match_conditions, 'action': {'forward_action': fwd_tfs}, } ) Loading
src/nbi/service/ietf_acl/Acl.py +6 −1 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ # limitations under the License. import json, logging, re from flask import jsonify from flask_restful import Resource from werkzeug.exceptions import NotFound from common.proto.context_pb2 import ConfigActionEnum, ConfigRule Loading @@ -20,6 +21,7 @@ from common.tools.context_queries.Device import get_device from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from nbi.service._tools.Authentication import HTTP_AUTH from nbi.service._tools.HttpStatusCodes import HTTP_NOCONTENT from .ietf_acl_parser import ietf_acl_from_config_rule_resource_value LOGGER = logging.getLogger(__name__) Loading Loading @@ -72,4 +74,7 @@ class Acl(Resource): del device.device_config.config_rules[:] device.device_config.config_rules.extend(delete_config_rules) device_client.ConfigureDevice(device) return None response = jsonify({}) response.status_code = HTTP_NOCONTENT return response
src/nbi/service/ietf_acl/Acls.py +5 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ from common.tools.grpc.Tools import grpc_message_to_json_string from context.client.ContextClient import ContextClient from device.client.DeviceClient import DeviceClient from nbi.service._tools.Authentication import HTTP_AUTH from nbi.service._tools.HttpStatusCodes import HTTP_CREATED from .ietf_acl_parser import AclDirectionEnum, config_rule_from_ietf_acl from .YangValidator import YangValidator Loading Loading @@ -129,4 +130,7 @@ class Acls(Resource): device_client = DeviceClient() device_client.ConfigureDevice(device) return jsonify({}) response = jsonify({}) response.status_code = HTTP_CREATED return response
src/nbi/service/ietf_acl/ietf_acl_parser.py +39 −15 Original line number Diff line number Diff line Loading @@ -28,9 +28,12 @@ class AclDirectionEnum(Enum): class Ipv4(BaseModel): dscp: int = 0 source_ipv4_network: str = Field(serialization_alias='source-ipv4-network', default='') destination_ipv4_network: str = Field( serialization_alias='destination-ipv4-network', default='' protocol: int = 0 source_ipv4_network: Optional[str] = Field( serialization_alias='source-ipv4-network', default=None ) destination_ipv4_network: Optional[str] = Field( serialization_alias='destination-ipv4-network', default=None ) Loading @@ -45,9 +48,15 @@ class Tcp(BaseModel): destination_port: Optional[Port] = Field(serialization_alias='destination-port', default=None) class Udp(BaseModel): source_port: Optional[Port] = Field(serialization_alias='source-port', default=None) destination_port: Optional[Port] = Field(serialization_alias='destination-port', default=None) class Matches(BaseModel): ipv4: Ipv4 = Ipv4() tcp: Optional[Tcp] = None udp: Optional[Udp] = None class Action(BaseModel): Loading Loading @@ -237,27 +246,42 @@ def config_rule_from_ietf_acl( def ietf_acl_from_config_rule_resource_value(config_rule_rv: Dict) -> Dict: rule_set = config_rule_rv['rule_set'] rule_set = config_rule_rv.get('rule_set', dict()) ace = [] for acl_entry in rule_set['entries']: match_ = acl_entry['match'] for acl_entry in rule_set.get('entries', list()): match_ = acl_entry.get('match', dict()) protocol = match_.get('protocol', 0) ipv4 = Ipv4( dscp=match_['dscp'], source_ipv4_network=match_['src_address'], destination_ipv4_network=match_['dst_address'], dscp=match_.get('dscp', 0), protocol=protocol, source_ipv4_network=match_.get('src_address'), destination_ipv4_network=match_.get('dst_address'), ) src_port = match_.get('src_port') src_port = None if src_port is None else Port(port=src_port) dst_port = match_.get('dst_port') dst_port = None if dst_port is None else Port(port=dst_port) tcp = None if match_['tcp_flags']: udp = None if protocol == 6: tcp = Tcp( flags=match_['tcp_flags'], source_port=Port(port=match_['src_port']), destination_port=Port(port=match_['dst_port']), flags=match_.get('tcp_flags', 0), source_port=src_port, destination_port=dst_port, ) matches = Matches(ipv4=ipv4, tcp=tcp) elif protocol == 17: udp = Udp( source_port=src_port, destination_port=dst_port, ) matches = Matches(ipv4=ipv4, tcp=tcp, udp=udp) ace.append( Ace( name=acl_entry['description'], name=acl_entry.get('description', ''), matches=matches, actions=Action( forwarding=TFS_IETF_FORWARDING_ACTION_MAPPING[ Loading
src/tests/.gitlab-ci.yml +1 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ include: #- local: '/src/tests/ofc25/.gitlab-ci.yml' #- local: '/src/tests/ryu-openflow/.gitlab-ci.yml' - local: '/src/tests/qkd_end2end/.gitlab-ci.yml' - local: '/src/tests/acl_end2end/.gitlab-ci.yml' - local: '/src/tests/tools/mock_tfs_nbi_dependencies/.gitlab-ci.yml' - local: '/src/tests/tools/mock_qkd_node/.gitlab-ci.yml' Loading