Merge "Add support for MACVLAN/IPVLAN"
This commit is contained in:
commit
6d1ac5b3f1
|
@ -68,6 +68,10 @@ class UnsupportedTransportException(DragonflowException):
|
|||
message = _("Transport protocol is not supported: %(transport)s")
|
||||
|
||||
|
||||
class UnsupportedSegmentationTypeException(DragonflowException):
|
||||
message = _("Segmentation type is not supported: %(segmentation_type)s")
|
||||
|
||||
|
||||
class DBLockFailed(DragonflowException):
|
||||
message = _("The DB Lock cannot be acquired for object=%(oid)s in"
|
||||
"the session=%(sid)s.")
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
from neutron_lib import constants as n_const
|
||||
from oslo_log import log
|
||||
from ryu.ofproto import ether
|
||||
|
||||
from dragonflow.common import exceptions
|
||||
from dragonflow.controller.common import constants
|
||||
|
@ -62,6 +63,36 @@ class TrunkApp(df_base_app.DFlowApp):
|
|||
child_port_segmentation.segmentation_id)
|
||||
return {'vlan_vid': vlan_vid}
|
||||
|
||||
def _get_classification_params_ip(self, child_port_segmentation):
|
||||
child = child_port_segmentation.port
|
||||
child_ip = child.ip
|
||||
child_ip_version = child_ip.version
|
||||
if child_ip_version == n_const.IP_VERSION_4:
|
||||
ip_field = 'ipv4_src'
|
||||
eth_type = ether.ETH_TYPE_IP
|
||||
elif child_ip_version == n_const.IP_VERSION_6:
|
||||
ip_field = 'ipv6_src'
|
||||
eth_type = ether.ETH_TYPE_IPV6
|
||||
else:
|
||||
LOG.warning('Unknown version %s for IP %r',
|
||||
child_ip_version, child_ip)
|
||||
raise exceptions.InvalidIPAddressException(key=child_ip)
|
||||
return ip_field, eth_type, child_ip
|
||||
|
||||
def _get_classification_params_ipvlan(self, child_port_segmentation):
|
||||
ip_field, eth_type, child_ip = self._get_classification_params_ip(
|
||||
child_port_segmentation)
|
||||
return {'eth_src': child_port_segmentation.parent.mac,
|
||||
'eth_type': eth_type,
|
||||
ip_field: child_ip}
|
||||
|
||||
def _get_classification_params_macvlan(self, child_port_segmentation):
|
||||
ip_field, eth_type, child_ip = self._get_classification_params_ip(
|
||||
child_port_segmentation)
|
||||
return {'eth_src': child_port_segmentation.port.mac,
|
||||
'eth_type': eth_type,
|
||||
ip_field: child_ip}
|
||||
|
||||
def _get_classification_match(self, child_port_segmentation):
|
||||
params = {'reg6': child_port_segmentation.parent.unique_key}
|
||||
segmentation_type = child_port_segmentation.segmentation_type
|
||||
|
@ -69,15 +100,34 @@ class TrunkApp(df_base_app.DFlowApp):
|
|||
params.update(
|
||||
self._get_classification_params_vlan(child_port_segmentation),
|
||||
)
|
||||
elif trunk.TYPE_MACVLAN == segmentation_type:
|
||||
params.update(
|
||||
self._get_classification_params_macvlan(
|
||||
child_port_segmentation),
|
||||
)
|
||||
elif trunk.TYPE_IPVLAN == segmentation_type:
|
||||
params.update(
|
||||
self._get_classification_params_ipvlan(
|
||||
child_port_segmentation),
|
||||
)
|
||||
else:
|
||||
raise exceptions.UnsupportedSegmentationType(
|
||||
raise exceptions.UnsupportedSegmentationTypeException(
|
||||
segmentation_type=segmentation_type)
|
||||
return self.parser.OFPMatch(**params)
|
||||
|
||||
def _add_classification_actions_vlan(self,
|
||||
actions, child_port_segmentation):
|
||||
def _add_classification_actions_vlan(self, actions,
|
||||
child_port_segmentation):
|
||||
actions.append(self.parser.OFPActionPopVlan())
|
||||
|
||||
def _add_classification_actions_ipvlan(self, actions,
|
||||
child_port_segmentation):
|
||||
"""
|
||||
Replace packet MAC from parent to child
|
||||
(Parent doesn't know child MAC)
|
||||
"""
|
||||
actions.append(self.parser.OFPActionSetField(
|
||||
eth_src=child_port_segmentation.port.mac))
|
||||
|
||||
def _get_classification_actions(self, child_port_segmentation):
|
||||
segmentation_type = child_port_segmentation.segmentation_type
|
||||
lport = child_port_segmentation.port
|
||||
|
@ -91,8 +141,13 @@ class TrunkApp(df_base_app.DFlowApp):
|
|||
if n_const.TYPE_VLAN == segmentation_type:
|
||||
self._add_classification_actions_vlan(actions,
|
||||
child_port_segmentation)
|
||||
elif trunk.TYPE_MACVLAN == segmentation_type:
|
||||
pass # No action needed
|
||||
elif trunk.TYPE_IPVLAN == segmentation_type:
|
||||
self._add_classification_actions_ipvlan(actions,
|
||||
child_port_segmentation)
|
||||
else:
|
||||
raise exceptions.UnsupportedSegmentationType(
|
||||
raise exceptions.UnsupportedSegmentationTypeException(
|
||||
segmentation_type=segmentation_type
|
||||
)
|
||||
|
||||
|
@ -132,13 +187,27 @@ class TrunkApp(df_base_app.DFlowApp):
|
|||
LOG.info("trunk_app:_add_dispatch_actions_vlan: Setting vlan_id: %s",
|
||||
hex(vlan_tag))
|
||||
|
||||
def _add_dispatch_actions_ipvlan(self, actions, child_port_segmentation):
|
||||
"""
|
||||
Replace packet MAC from child to parent
|
||||
(Parent doesn't know child MAC)
|
||||
"""
|
||||
# TODO(oanson) Maybe add MAC to child_port_segmentation model
|
||||
# so we won't have to guess which MAC?
|
||||
actions.append(self.parser.OFPActionSetField(
|
||||
eth_dst=child_port_segmentation.parent.mac))
|
||||
|
||||
def _get_dispatch_actions(self, child_port_segmentation):
|
||||
actions = []
|
||||
segmentation_type = child_port_segmentation.segmentation_type
|
||||
if n_const.TYPE_VLAN == segmentation_type:
|
||||
self._add_dispatch_actions_vlan(actions, child_port_segmentation)
|
||||
elif trunk.TYPE_MACVLAN == segmentation_type:
|
||||
pass # No action needed
|
||||
elif trunk.TYPE_IPVLAN == segmentation_type:
|
||||
self._add_dispatch_actions_ipvlan(actions, child_port_segmentation)
|
||||
else:
|
||||
raise exceptions.UnsupportedSegmentationType(
|
||||
raise exceptions.UnsupportedSegmentationTypeException(
|
||||
segmentation_type=segmentation_type
|
||||
)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
import uuid
|
||||
|
||||
from jsonmodels import errors
|
||||
from jsonmodels import fields
|
||||
from neutron_lib import constants as n_const
|
||||
|
||||
|
@ -23,7 +24,9 @@ from dragonflow.db.models import l2
|
|||
from dragonflow.db.models import mixins
|
||||
|
||||
|
||||
SUPPORTED_SEGMENTATION_TYPES = (n_const.TYPE_VLAN, )
|
||||
TYPE_MACVLAN = 'macvlan'
|
||||
TYPE_IPVLAN = 'ipvlan'
|
||||
SUPPORTED_SEGMENTATION_TYPES = (n_const.TYPE_VLAN, TYPE_MACVLAN, TYPE_IPVLAN)
|
||||
UUID_NAMESPACE = uuid.UUID('a11fee2a-d833-4e22-be31-f915b55f1f77')
|
||||
|
||||
|
||||
|
@ -50,4 +53,16 @@ class ChildPortSegmentation(mf.ModelBase, mixins.Topic, mixins.BasicEvents):
|
|||
port = df_fields.ReferenceField(l2.LogicalPort, required=True)
|
||||
segmentation_type = df_fields.EnumField(SUPPORTED_SEGMENTATION_TYPES,
|
||||
required=True)
|
||||
segmentation_id = fields.IntField(required=True)
|
||||
segmentation_id = fields.IntField()
|
||||
|
||||
def validate(self):
|
||||
"""
|
||||
Verify that the correct fields are filled for the correct type.
|
||||
e.g. for VLAN, segmentation_id is not None.
|
||||
"""
|
||||
super(ChildPortSegmentation, self).validate()
|
||||
if self.segmentation_type == n_const.TYPE_VLAN:
|
||||
if self.segmentation_id is None:
|
||||
raise errors.ValidationError("segmentation_id required if "
|
||||
"segmentation_type is " +
|
||||
n_const.TYPE_VLAN)
|
||||
|
|
Loading…
Reference in New Issue