diff --git a/src/config/api-server/vnc_cfg_api_server/resources/_policy_base.py b/src/config/api-server/vnc_cfg_api_server/resources/_policy_base.py index 75c293a60c7..3ff62b79221 100644 --- a/src/config/api-server/vnc_cfg_api_server/resources/_policy_base.py +++ b/src/config/api-server/vnc_cfg_api_server/resources/_policy_base.py @@ -6,6 +6,7 @@ import itertools import uuid +from cfgm_common import protocols from netaddr import IPNetwork @@ -28,14 +29,16 @@ def check_policy_rules(entries, network_policy_rule=False): for rule in rules: if not rule.get('rule_uuid'): rule['rule_uuid'] = str(uuid.uuid4()) + # TODO(sahid): This all check can be factorized in + # cfgm_common.protocols protocol = rule['protocol'] if protocol.isdigit(): if int(protocol) < 0 or int(protocol) > 255: return (False, (400, 'Rule with invalid protocol : %s' % protocol)) else: - valids = ['any', 'icmp', 'tcp', 'udp', 'icmp6'] - if protocol not in valids: + protocol = protocol.lower() + if protocol not in protocols.IP_PROTOCOL_NAMES: return (False, (400, 'Rule with invalid protocol : %s' % protocol)) src_sg_list = [addr.get('security_group') for addr in diff --git a/src/config/api-server/vnc_cfg_api_server/resources/firewall_rule.py b/src/config/api-server/vnc_cfg_api_server/resources/firewall_rule.py index dca7c4cd00b..3efc3d868e4 100644 --- a/src/config/api-server/vnc_cfg_api_server/resources/firewall_rule.py +++ b/src/config/api-server/vnc_cfg_api_server/resources/firewall_rule.py @@ -2,7 +2,7 @@ # Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. # -from cfgm_common import proto_dict +from cfgm_common import protocols from cfgm_common.exceptions import NoIdError from sandesh_common.vns.constants import DEFAULT_MATCH_TAG_TYPE from vnc_api.gen.resource_common import AddressGroup @@ -58,15 +58,25 @@ def _frs_fix_service(cls, service, service_group_refs): @classmethod def _frs_fix_service_protocol(cls, obj_dict): if obj_dict.get('service') and obj_dict['service'].get('protocol'): + # TODO(sahid): This all check can be factorized in + # cfgm_common.protocols protocol = obj_dict['service']['protocol'] if protocol.isdigit(): protocol_id = int(protocol) if protocol_id < 0 or protocol_id > 255: return False, (400, "Invalid protocol: %s" % protocol) - elif protocol not in proto_dict: + else: + protocol = protocol.lower() + if protocol not in protocols.IP_PROTOCOL_NAMES: return False, (400, "Invalid protocol: %s" % protocol) else: - protocol_id = proto_dict[protocol] + protocol_id = protocols.IP_PROTOCOL_MAP[protocol] + # This is a hack that we are expecting to remove at + # some point. It seems that we were using different + # convention in api-server/cfg_common/dm/st + if protocol == 'any': + protocol_id = 0 + obj_dict['service']['protocol_id'] = protocol_id return True, "" diff --git a/src/config/api-server/vnc_cfg_api_server/resources/service_group.py b/src/config/api-server/vnc_cfg_api_server/resources/service_group.py index 2aa03b8c0b5..d01c0847d7f 100644 --- a/src/config/api-server/vnc_cfg_api_server/resources/service_group.py +++ b/src/config/api-server/vnc_cfg_api_server/resources/service_group.py @@ -2,7 +2,7 @@ # Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. # -from cfgm_common import proto_dict +from cfgm_common import protocols from vnc_api.gen.resource_common import ServiceGroup from vnc_cfg_api_server.resources._security_base import SecurityResourceBase @@ -25,15 +25,25 @@ def pre_dbe_create(cls, tenant_name, obj_dict, db_conn): for service in firewall_services: if service.get('protocol') is None: continue + # TODO(sahid): This all check can be factorized in + # cfgm_common.protocols protocol = service['protocol'] if protocol.isdigit(): protocol_id = int(protocol) if protocol_id < 0 or protocol_id > 255: return False, (400, 'Invalid protocol: %s' % protocol) - elif protocol not in proto_dict: + else: + protocol = protocol.lower() + if protocol not in protocols.IP_PROTOCOL_NAMES: return False, (400, 'Invalid protocol: %s' % protocol) else: - protocol_id = proto_dict[protocol] + protocol_id = protocols.IP_PROTOCOL_MAP[protocol] + # This is a hack that we are expecting to remove at + # some point. It seems that we were using different + # convention in api-server/cfg_common/dm/st + if protocol == 'any': + protocol_id = 0 + service['protocol_id'] = protocol_id return True, '' diff --git a/src/config/common/cfgm_common/__init__.py b/src/config/common/cfgm_common/__init__.py index 088b03b1452..789f59ce10d 100644 --- a/src/config/common/cfgm_common/__init__.py +++ b/src/config/common/cfgm_common/__init__.py @@ -49,14 +49,6 @@ PERMS2_VALID_SHARE_TYPES = ['tenant', 'domain'] DOMAIN_SHARING_PERMS = PERMS_RW -proto_dict = { - 'any': 0, - 'icmp': 1, - 'tcp': 6, - 'udp': 17, - 'ipv6-icmp': 58, -} - def get_bgp_rtgt_min_id(asn): if int(asn) > 0xFFFF: return _BGP_RTGT_MIN_ID_TYPE1_2 diff --git a/src/config/common/cfgm_common/protocols.py b/src/config/common/cfgm_common/protocols.py new file mode 100644 index 00000000000..1274401bec0 --- /dev/null +++ b/src/config/common/cfgm_common/protocols.py @@ -0,0 +1,100 @@ +# +# Copyright (c) 2020 Juniper Networks, Inc. All rights reserved. +# + +"""Internet protocols. + +See also http://www.iana.org/assignments/protocol-numbers +""" + +# Mostly inspired by: +# https://github.com/openstack/neutron-lib/blob/master/neutron_lib/constants.py + +PROTO_NAME_AH = 'ah' +PROTO_NAME_DCCP = 'dccp' +PROTO_NAME_EGP = 'egp' +PROTO_NAME_ESP = 'esp' +PROTO_NAME_GRE = 'gre' +PROTO_NAME_HOPOPT = 'hopopt' +PROTO_NAME_ICMP = 'icmp' +PROTO_NAME_IGMP = 'igmp' +PROTO_NAME_IP = 'ip' +PROTO_NAME_IPIP = 'ipip' +PROTO_NAME_IPV6_ENCAP = 'ipv6-encap' +PROTO_NAME_IPV6_FRAG = 'ipv6-frag' +PROTO_NAME_IPV6_ICMP = 'ipv6-icmp' +PROTO_NAME_IPV6_NONXT = 'ipv6-nonxt' +PROTO_NAME_IPV6_OPTS = 'ipv6-opts' +PROTO_NAME_IPV6_ROUTE = 'ipv6-route' +PROTO_NAME_OSPF = 'ospf' +PROTO_NAME_PGM = 'pgm' +PROTO_NAME_RSVP = 'rsvp' +PROTO_NAME_SCTP = 'sctp' +PROTO_NAME_TCP = 'tcp' +PROTO_NAME_UDP = 'udp' +PROTO_NAME_UDPLITE = 'udplite' +PROTO_NAME_VRRP = 'vrrp' +# Contrail specific +PROTO_NAME_ICMP6 = 'icmp6' +PROTO_NAME_ANY = 'any' + + +PROTO_NUM_AH = 51 +PROTO_NUM_DCCP = 33 +PROTO_NUM_EGP = 8 +PROTO_NUM_ESP = 50 +PROTO_NUM_GRE = 47 +PROTO_NUM_HOPOPT = 0 +PROTO_NUM_ICMP = 1 +PROTO_NUM_IGMP = 2 +PROTO_NUM_IP = 0 +PROTO_NUM_IPIP = 4 +PROTO_NUM_IPV6_ENCAP = 41 +PROTO_NUM_IPV6_FRAG = 44 +PROTO_NUM_IPV6_ICMP = 58 +PROTO_NUM_IPV6_NONXT = 59 +PROTO_NUM_IPV6_OPTS = 60 +PROTO_NUM_IPV6_ROUTE = 43 +PROTO_NUM_OSPF = 89 +PROTO_NUM_PGM = 113 +PROTO_NUM_RSVP = 46 +PROTO_NUM_SCTP = 132 +PROTO_NUM_TCP = 6 +PROTO_NUM_UDP = 17 +PROTO_NUM_UDPLITE = 136 +PROTO_NUM_VRRP = 112 +# Contrail specific +PROTO_NUM_ICMP6 = 58 +PROTO_NUM_ANY = 'any' + + +IP_PROTOCOL_MAP = { + PROTO_NAME_AH: PROTO_NUM_AH, + PROTO_NAME_DCCP: PROTO_NUM_DCCP, + PROTO_NAME_EGP: PROTO_NUM_EGP, + PROTO_NAME_ESP: PROTO_NUM_ESP, + PROTO_NAME_GRE: PROTO_NUM_GRE, + PROTO_NAME_HOPOPT: PROTO_NUM_HOPOPT, + PROTO_NAME_ICMP: PROTO_NUM_ICMP, + PROTO_NAME_IGMP: PROTO_NUM_IGMP, + PROTO_NAME_IP: PROTO_NUM_IP, + PROTO_NAME_IPIP: PROTO_NUM_IPIP, + PROTO_NAME_IPV6_ENCAP: PROTO_NUM_IPV6_ENCAP, + PROTO_NAME_IPV6_FRAG: PROTO_NUM_IPV6_FRAG, + PROTO_NAME_IPV6_ICMP: PROTO_NUM_IPV6_ICMP, + PROTO_NAME_IPV6_NONXT: PROTO_NUM_IPV6_NONXT, + PROTO_NAME_IPV6_OPTS: PROTO_NUM_IPV6_OPTS, + PROTO_NAME_IPV6_ROUTE: PROTO_NUM_IPV6_ROUTE, + PROTO_NAME_OSPF: PROTO_NUM_OSPF, + PROTO_NAME_PGM: PROTO_NUM_PGM, + PROTO_NAME_RSVP: PROTO_NUM_RSVP, + PROTO_NAME_SCTP: PROTO_NUM_SCTP, + PROTO_NAME_TCP: PROTO_NUM_TCP, + PROTO_NAME_UDP: PROTO_NUM_UDP, + PROTO_NAME_UDPLITE: PROTO_NUM_UDPLITE, + PROTO_NAME_VRRP: PROTO_NUM_VRRP, + PROTO_NAME_ICMP6: PROTO_NUM_ICMP6, + PROTO_NAME_ANY: PROTO_NUM_ANY} + + +IP_PROTOCOL_NAMES = list(IP_PROTOCOL_MAP.keys()) diff --git a/src/config/common/tox.ini b/src/config/common/tox.ini index c781fce2c97..021a318e54e 100644 --- a/src/config/common/tox.ini +++ b/src/config/common/tox.ini @@ -84,3 +84,4 @@ filename = */tests/unit/test_dependency_tracker.py */tests/cassandra_fake_impl.py */datastore/drivers/cassandra_cql.py + */protocols.py \ No newline at end of file diff --git a/src/config/schema-transformer/schema_transformer/resources/security_group.py b/src/config/schema-transformer/schema_transformer/resources/security_group.py index 4885b76286c..a3368d65c6d 100644 --- a/src/config/schema-transformer/schema_transformer/resources/security_group.py +++ b/src/config/schema-transformer/schema_transformer/resources/security_group.py @@ -5,7 +5,8 @@ from builtins import str import copy - +from cfgm_common import protocols +import six from vnc_api.gen.resource_xsd import AclEntriesType, AclRuleType from vnc_api.gen.resource_xsd import ActionListType, MatchConditionType from vnc_api.gen.resource_xsd import PortType @@ -14,8 +15,7 @@ _access_control_list_update from schema_transformer.resources._resource_base import ResourceBaseST from schema_transformer.sandesh.st_introspect import ttypes as sandesh -from schema_transformer.utils import _create_pprinted_prop_list, \ - _PROTO_STR_TO_NUM_IPV4, _PROTO_STR_TO_NUM_IPV6 +from schema_transformer.utils import _create_pprinted_prop_list # a struct to store attributes related to Security Group needed by schema @@ -148,6 +148,7 @@ def _convert_security_group_name_to_id(self, addr): return True # end _convert_security_group_name_to_id + # TODO(sahid): This method is duplicated in virtual_network.py @staticmethod def protocol_policy_to_acl(pproto, ethertype): # convert policy proto input(in str) to acl proto (num) @@ -155,10 +156,16 @@ def protocol_policy_to_acl(pproto, ethertype): return None if pproto.isdigit(): return pproto - if ethertype == 'IPv6': - return _PROTO_STR_TO_NUM_IPV6.get(pproto.lower()) - else: # IPv4 - return _PROTO_STR_TO_NUM_IPV4.get(pproto.lower()) + pproto = pproto.lower() + if ethertype == 'IPv6' and pproto == protocols.PROTO_NAME_ICMP: + # Previsouly we were convertir this transparently, so we + # have to keep it. + pproto = protocols.PROTO_NAME_IPV6_ICMP + return six.text_type( + # Protocol ID should be returned in string according the + # spec. TODO(sahid): Creating helper function in + # protocols's module would make more sense. + protocols.IP_PROTOCOL_MAP[pproto]) def policy_to_acl_rule(self, prule): ingress_acl_rule_list = [] diff --git a/src/config/schema-transformer/schema_transformer/resources/virtual_network.py b/src/config/schema-transformer/schema_transformer/resources/virtual_network.py index 8b64c28d6dd..7f7b4d982d7 100644 --- a/src/config/schema-transformer/schema_transformer/resources/virtual_network.py +++ b/src/config/schema-transformer/schema_transformer/resources/virtual_network.py @@ -16,10 +16,12 @@ from time import time as TIME import cfgm_common as common +from cfgm_common import protocols from cfgm_common.exceptions import NoIdError, RefsExistError from cfgm_common.uve.virtual_network.ttypes import UveVirtualNetworkConfig from cfgm_common.uve.virtual_network.ttypes import UveVirtualNetworkConfigTrace from netaddr import IPNetwork +import six from vnc_api.gen.resource_client import InstanceIp from vnc_api.gen.resource_xsd import AclEntriesType, AclRuleType from vnc_api.gen.resource_xsd import ActionListType, AddressType @@ -32,8 +34,6 @@ _access_control_list_update from schema_transformer.resources._resource_base import ResourceBaseST from schema_transformer.sandesh.st_introspect import ttypes as sandesh -from schema_transformer.utils import _PROTO_STR_TO_NUM_IPV4 -from schema_transformer.utils import _PROTO_STR_TO_NUM_IPV6 from schema_transformer.utils import RULE_IMPLICIT_ALLOW_UUID from schema_transformer.utils import RULE_IMPLICIT_DENY_UUID @@ -808,6 +808,7 @@ def process_analyzer(self, action): return # end process_analyzer + # TODO(sahid): This method is duplicated in security_group.py @staticmethod def protocol_policy_to_acl(pproto, ethertype): # convert policy proto input(in str) to acl proto (num) @@ -815,10 +816,16 @@ def protocol_policy_to_acl(pproto, ethertype): return 'any' if pproto.isdigit(): return pproto - if ethertype == 'IPv6': - return _PROTO_STR_TO_NUM_IPV6.get(pproto.lower()) - else: # IPv4 - return _PROTO_STR_TO_NUM_IPV4.get(pproto.lower()) + pproto = pproto.lower() + if ethertype == 'IPv6' and pproto == protocols.PROTO_NAME_ICMP: + # Previsouly we were convertir this transparently, so we + # have to keep it. + pproto = protocols.PROTO_NAME_IPV6_ICMP + return six.text_type( + # Protocol ID should be returned in string according the + # spec. TODO(sahid): Creating helper function in + # protocols's module would make more sense. + protocols.IP_PROTOCOL_MAP[pproto]) # end protocol_policy_to_acl def address_list_policy_to_acl(self, addr): diff --git a/src/config/schema-transformer/schema_transformer/tests/test_security_group.py b/src/config/schema-transformer/schema_transformer/tests/test_security_group.py index 5c1de0e8009..ca09fc23603 100644 --- a/src/config/schema-transformer/schema_transformer/tests/test_security_group.py +++ b/src/config/schema-transformer/schema_transformer/tests/test_security_group.py @@ -8,7 +8,9 @@ import json import uuid +from cfgm_common import protocols from cfgm_common import rest +import six from vnc_api.vnc_api import NoIdError from vnc_api.vnc_api import SecurityGroup @@ -19,15 +21,6 @@ from .test_policy import VerifyPolicy -_PROTO_STR_TO_NUM = { - 'icmp6': '58', - 'icmp': '1', - 'tcp': '6', - 'udp': '17', - 'any': 'any', -} - - class VerifySecurityGroup(VerifyPolicy): def __init__(self, vnc_lib): @@ -98,7 +91,9 @@ def check_acl_match_protocol(self, fq_name, acl_name, protocol): self.assertTrue(acl is not None) for rule in acl.access_control_list_entries.acl_rule: self.assertEqual(rule.match_condition.protocol, - _PROTO_STR_TO_NUM.get(protocol.lower())) + six.text_type( + protocols.IP_PROTOCOL_MAP.get( + protocol.lower()))) @retries(5) def check_no_policies_for_sg(self, fq_name): diff --git a/src/config/schema-transformer/schema_transformer/utils.py b/src/config/schema-transformer/schema_transformer/utils.py index a70e3e4d667..f2d63ffc0bf 100644 --- a/src/config/schema-transformer/schema_transformer/utils.py +++ b/src/config/schema-transformer/schema_transformer/utils.py @@ -13,21 +13,6 @@ from schema_transformer.sandesh.st_introspect import ttypes as sandesh -_PROTO_STR_TO_NUM_IPV4 = { - 'icmp6': '58', - 'icmp': '1', - 'tcp': '6', - 'udp': '17', - 'any': 'any', -} -_PROTO_STR_TO_NUM_IPV6 = { - 'icmp6': '58', - 'icmp': '58', - 'tcp': '6', - 'udp': '17', - 'any': 'any', -} - RULE_IMPLICIT_ALLOW_UUID = common.RULE_IMPLICIT_ALLOW_UUID RULE_IMPLICIT_DENY_UUID = common.RULE_IMPLICIT_DENY_UUID