+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
| networking-odl_ | ml2,l3,lb,fw | yes | no | [C] | Kilo |
+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
-| networking-ofagent_ | ml2 | yes | no | [B] | |
+| networking-ofagent_ | ml2 | yes | no | [C] | Kilo |
+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
| networking-ovs-dpdk_ | | | | | |
+-------------------------------+-----------------------+-----------+------------------+---------+--------------+
+++ /dev/null
-# neutron-rootwrap command filters for nodes on which
-# neutron-ofagent-agent is expected to control network
-#
-# This file should be owned by (and only-writeable by) the root user
-
-# format seems to be
-# cmd-name: filter-name, raw-command, user, args
-
-[Filters]
-
-# ovs_lib
-ovs-vsctl: CommandFilter, ovs-vsctl, root
-
-# ip_lib
-ip: IpFilter, ip, root
-ip_exec: IpNetnsExecFilter, ip, root
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 Fumihiko Kakuma <kakuma at valinux co jp>
-# All Rights Reserved.
-#
-# Based on openvswitch mechanism driver.
-#
-# Copyright (c) 2013 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from neutron.agent import securitygroups_rpc
-from neutron.common import constants
-from neutron.extensions import portbindings
-from neutron.openstack.common import log
-from neutron.plugins.common import constants as p_constants
-from neutron.plugins.ml2.drivers import mech_agent
-
-LOG = log.getLogger(__name__)
-
-
-class OfagentMechanismDriver(mech_agent.SimpleAgentMechanismDriverBase):
- """Attach to networks using ofagent L2 agent.
-
- The OfagentMechanismDriver integrates the ml2 plugin with the
- ofagent L2 agent. Port binding with this driver requires the
- ofagent agent to be running on the port's host, and that agent
- to have connectivity to at least one segment of the port's
- network.
- """
-
- def __init__(self):
- sg_enabled = securitygroups_rpc.is_firewall_enabled()
- vif_details = {portbindings.CAP_PORT_FILTER: sg_enabled,
- portbindings.OVS_HYBRID_PLUG: sg_enabled}
- super(OfagentMechanismDriver, self).__init__(
- constants.AGENT_TYPE_OFA,
- portbindings.VIF_TYPE_OVS,
- vif_details)
-
- def get_allowed_network_types(self, agent):
- return (agent['configurations'].get('tunnel_types', []) +
- [p_constants.TYPE_LOCAL, p_constants.TYPE_FLAT,
- p_constants.TYPE_VLAN])
-
- def get_mappings(self, agent):
- return dict(agent['configurations'].get('interface_mappings', {}))
+++ /dev/null
-This directory includes agent for OpenFlow Agent mechanism driver.
-
-# -- Installation
-
-For how to install/set up ML2 mechanism driver for OpenFlow Agent, please refer to
-https://github.com/osrg/ryu/wiki/OpenStack
-
-# -- Notes for updating from Icehouce
-
-OVS.bridge_mappings is deprecated for ofagent. It was removed in Kilo.
-Please use AGENT.physical_interface_mappings instead.
-To mimic an existing setup with bridge_mapping, you can create
-a veth pair, link one side of it to the bridge, and then specify
-the other side in physical_interface_mappings.
-For example, if you have the following:
-
- [OVS]
- bridge_mappings=public:br-ex
-
-You can do:
-
- # ip link add int-public type veth peer name phy-public
- # ip link set int-public up
- # ip link set phy-public up
- # ovs-vsctl add-port br-ex phy-public
-
-and then replace the bridge_mappings with:
-
- [AGENT]
- physical_interface_mappings=public:int-public
-
-After Icehouce, most of the functionality have been folded into
-a single bridge, the integration bridge. (aka. br-int)
-The integration bridge is the only bridge which would have an
-OpenFlow connection to the embedded controller in ofagent now.
-
-- ofagent no longer uses a separate bridge for tunneling.
- Please remove br-tun if you have one.
-
- # ovs-vsctl del-br br-tun
-
-- ofagent no longer acts as an OpenFlow controller for physical bridges.
- Please remove set-controller configuration from your physical bridges.
-
- # ovs-vsctl del-controller ${PHYSICAL_BRIDGE}
-
-The support of ancillary bridges has been removed after Icehouce.
-While you can still use these bridges to provide connectivity,
-neutron-ofagent-agent no longer reports port state changes (up/down)
-for these bridges. If it is a problem for you, please consider
-tweaking your configuration to avoid using ancillary bridges.
-We recommend to use a provider network instead as the following:
-
-- Make l3-agent external_network_bridge configuration empty.
- eg.
- [DEFAULT]
- external_network_bridge=
-
-- (Re-)create a network (and subnet) for public connectivity with
- a flat provider network.
- eg.
- neutron net-create $PUBLIC_NETWORK -- \
- --router:external=True \
- --provider:network_type:flat \
- --provider:physical_network=$PUBLIC_PHYSICAL_NETWORK
-
-- Associate your neutron router to the above network.
- eg.
- neutron router-gateway-clear $ROUTER_ID
- neutron router-gateway-set $ROUTER_ID $PUBLIC_NETWORK
-
-- Add the corresponding entry to bridge_mappings.
- eg.
- [OVS]
- bridge_mappings=$PUBLIC_PHYSICAL_NETWORK:$PUBLIC_BRIDGE
-
-The port naming scheme for ofagent has been changed after Icehouce.
-If you are using security groups, you should switch firewall_driver
-accordingly.
- From:
- [securitygroup]
- firewall_driver=neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
- To:
- [securitygroup]
- firewall_driver=neutron.agent.linux.iptables_firewall.IptablesFirewallDriver
-
-# -- Ryu General
-
-For general Ryu stuff, please refer to
-http://osrg.github.io/ryu/
-
-Ryu is available at github
-git://github.com/osrg/ryu.git
-https://github.com/osrg/ryu
-
-The mailing is at
-ryu-devel@lists.sourceforge.net
-https://lists.sourceforge.net/lists/listinfo/ryu-devel
-
-Enjoy!
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 Fumihiko Kakuma <kakuma at valinux co jp>
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from ryu.app.ofctl import api as ryu_api
-from ryu.lib import dpid as dpid_lib
-from ryu.lib.packet import arp
-from ryu.lib.packet import ethernet
-from ryu.lib.packet import packet
-from ryu.lib.packet import vlan
-
-from neutron.common import log
-from neutron.i18n import _LI
-from neutron.openstack.common import log as logging
-import neutron.plugins.ofagent.agent.metadata as meta
-
-
-LOG = logging.getLogger(__name__)
-
-
-class ArpLib(object):
-
- def __init__(self, ryuapp):
- """Constructor.
-
- Define the internal table mapped an ip and a mac in a network.
- self._arp_tbl:
- {network1: {ip_addr: mac, ...},
- network2: {ip_addr: mac, ...},
- ...,
- }
-
- :param ryuapp: object of the ryu app.
- """
- self.ryuapp = ryuapp
- self._arp_tbl = {}
- self.br = None
-
- def set_bridge(self, br):
- self.br = br
-
- @log.log
- def _send_arp_reply(self, datapath, port, pkt):
- ofp = datapath.ofproto
- ofpp = datapath.ofproto_parser
- pkt.serialize()
- data = pkt.data
- actions = [ofpp.OFPActionOutput(port=port)]
- out = ofpp.OFPPacketOut(datapath=datapath,
- buffer_id=ofp.OFP_NO_BUFFER,
- in_port=ofp.OFPP_CONTROLLER,
- actions=actions,
- data=data)
- ryu_api.send_msg(self.ryuapp, out)
-
- @log.log
- def _send_unknown_packet(self, msg, in_port, out_port):
- datapath = msg.datapath
- ofp = datapath.ofproto
- ofpp = datapath.ofproto_parser
- data = None
- if msg.buffer_id == ofp.OFP_NO_BUFFER:
- data = msg.data
- actions = [ofpp.OFPActionOutput(port=out_port)]
- out = ofpp.OFPPacketOut(datapath=datapath,
- buffer_id=msg.buffer_id,
- in_port=in_port,
- actions=actions,
- data=data)
- ryu_api.send_msg(self.ryuapp, out)
-
- def _respond_arp(self, datapath, port, arptbl,
- pkt_ethernet, pkt_vlan, pkt_arp):
- if pkt_arp.opcode != arp.ARP_REQUEST:
- LOG.debug("unknown arp op %s", pkt_arp.opcode)
- return False
- ip_addr = pkt_arp.dst_ip
- hw_addr = arptbl.get(ip_addr)
- if hw_addr is None:
- LOG.debug("unknown arp request %s", ip_addr)
- return False
- LOG.debug("responding arp request %(ip_addr)s -> %(hw_addr)s",
- {'ip_addr': ip_addr, 'hw_addr': hw_addr})
- pkt = packet.Packet()
- pkt.add_protocol(ethernet.ethernet(ethertype=pkt_ethernet.ethertype,
- dst=pkt_ethernet.src,
- src=hw_addr))
- if pkt_vlan:
- pkt.add_protocol(vlan.vlan(cfi=pkt_vlan.cfi,
- ethertype=pkt_vlan.ethertype,
- pcp=pkt_vlan.pcp,
- vid=pkt_vlan.vid))
- pkt.add_protocol(arp.arp(opcode=arp.ARP_REPLY,
- src_mac=hw_addr,
- src_ip=ip_addr,
- dst_mac=pkt_arp.src_mac,
- dst_ip=pkt_arp.src_ip))
- self._send_arp_reply(datapath, port, pkt)
- return True
-
- @log.log
- def add_arp_table_entry(self, network, ip, mac):
- if network in self._arp_tbl:
- self._arp_tbl[network][ip] = mac
- else:
- self._arp_tbl[network] = {ip: mac}
-
- @log.log
- def del_arp_table_entry(self, network, ip):
- if network not in self._arp_tbl:
- LOG.debug("removal of unknown network %s", network)
- return
- if self._arp_tbl[network].pop(ip, None) is None:
- LOG.debug("removal of unknown ip %s", ip)
- return
- if not self._arp_tbl[network]:
- del self._arp_tbl[network]
-
- def packet_in_handler(self, ev):
- """Check a packet-in message.
-
- Build and output an arp reply if a packet-in message is
- an arp packet.
- """
- msg = ev.msg
- LOG.debug("packet-in msg %s", msg)
- datapath = msg.datapath
- if self.br is None:
- LOG.info(_LI("No bridge is set"))
- return
- if self.br.datapath.id != datapath.id:
- LOG.info(_LI("Unknown bridge %(dpid)s ours %(ours)s"),
- {"dpid": datapath.id, "ours": self.br.datapath.id})
- return
- ofp = datapath.ofproto
- port = msg.match['in_port']
- metadata = msg.match.get('metadata')
- # NOTE(yamamoto): Ryu packet library can raise various exceptions
- # on a corrupted packet.
- try:
- pkt = packet.Packet(msg.data)
- except Exception as e:
- LOG.debug("Unparsable packet: got exception %s", e)
- return
- LOG.debug("packet-in dpid %(dpid)s in_port %(port)s pkt %(pkt)s",
- {'dpid': dpid_lib.dpid_to_str(datapath.id),
- 'port': port, 'pkt': pkt})
-
- if metadata is None:
- LOG.info(_LI("drop non tenant packet"))
- return
- network = metadata & meta.NETWORK_MASK
- pkt_ethernet = pkt.get_protocol(ethernet.ethernet)
- if not pkt_ethernet:
- LOG.debug("drop non-ethernet packet")
- return
- pkt_vlan = pkt.get_protocol(vlan.vlan)
- pkt_arp = pkt.get_protocol(arp.arp)
- if not pkt_arp:
- LOG.debug("drop non-arp packet")
- return
-
- arptbl = self._arp_tbl.get(network)
- if arptbl:
- if self._respond_arp(datapath, port, arptbl,
- pkt_ethernet, pkt_vlan, pkt_arp):
- return
- else:
- LOG.info(_LI("unknown network %s"), network)
-
- # add a flow to skip a packet-in to a controller.
- self.br.arp_passthrough(network=network, tpa=pkt_arp.dst_ip)
- # send an unknown arp packet to the table.
- self._send_unknown_packet(msg, port, ofp.OFPP_TABLE)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-LOCAL_VLAN_MIN = 1
-LOCAL_VLAN_MAX = 0xfff
-LOCAL_VLAN_MASK = 0xfff
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-"""
-OpenFlow1.3 flow table for OFAgent
-
-* requirements
-** plain OpenFlow 1.3. no vendor extensions.
-
-* legends
- xxx: network id (agent internal use)
- yyy: segment id (vlan id, gre key, ...)
- a,b,c: tunnel port (tun_ofports, map[net_id].tun_ofports)
- i,j,k: vm port (map[net_id].vif_ports[vif_id].ofport)
- x,y,z: physical port (int_ofports)
- N: tunnel type (0 for TYPE_GRE, 1 for TYPE_xxx, ...)
- iii: unknown ip address
- uuu: unicast l2 address
-
-* tables (in order)
- CHECK_IN_PORT
- TUNNEL_IN+N
- PHYS_IN
- LOCAL_IN
- ARP_PASSTHROUGH
- ARP_RESPONDER
- TUNNEL_OUT
- LOCAL_OUT
- PHYS_OUT
- TUNNEL_FLOOD+N
- PHYS_FLOOD
- LOCAL_FLOOD
-
-* CHECK_IN_PORT
-
- for each vm ports:
- // check_in_port_add_local_port, check_in_port_delete_port
- in_port=i, write_metadata(LOCAL|xxx),goto(LOCAL_IN)
- TYPE_GRE
- for each tunnel ports:
- // check_in_port_add_tunnel_port, check_in_port_delete_port
- in_port=a, goto(TUNNEL_IN+N)
- TYPE_VLAN
- for each networks ports:
- // provision_tenant_physnet, reclaim_tenant_physnet
- in_port=x,vlan_vid=present|yyy, write_metadata(xxx),goto(PHYS_IN)
- TYPE_FLAT
- // provision_tenant_physnet, reclaim_tenant_physnet
- in_port=x, write_metadata(xxx),goto(PHYS_IN)
- default drop
-
-* TUNNEL_IN+N (per tunnel types) tunnel -> network
-
- for each networks:
- // provision_tenant_tunnel, reclaim_tenant_tunnel
- tun_id=yyy, write_metadata(xxx),goto(TUNNEL_OUT)
-
- default drop
-
-* PHYS_IN
- default goto(TUNNEL_OUT)
-
-* LOCAL_IN
- default goto(next_table)
-
-* ARP_PASSTHROUGH
- for each unknown tpa:
- // arp_passthrough
- arp,arp_op=request,metadata=xxx,tpa=iii, idle_timeout=5, goto(TUNNEL_OUT)
- default goto(next_table)
-
-* ARP_RESPONDER
- arp,arp_op=request, output:controller
- default goto(next_table)
-
-* TUNNEL_OUT
- TYPE_GRE
- // !FLOODING_ENTRY
- // install_tunnel_output, delete_tunnel_output
- metadata=LOCAL|xxx,eth_dst=uuu set_tunnel(yyy),output:a
-
- default goto(next table)
-
-* LOCAL_OUT
- for each known destinations:
- // local_out_add_port, local_out_delete_port
- metadata=xxx,eth_dst=uuu output:i
- default goto(next table)
-
-* PHYS_OUT
-
- NOTE(yamamoto): currently this table is always empty.
-
- default goto(next table)
-
-* TUNNEL_FLOOD+N. (per tunnel types)
-
- network -> tunnel/vlan
- output to tunnel/physical ports
- "next table" might be LOCAL_OUT
- TYPE_GRE
- for each networks:
- // FLOODING_ENTRY
- // install_tunnel_output, delete_tunnel_output
- metadata=LOCAL|xxx, set_tunnel(yyy),output:a,b,c,goto(next table)
-
- default goto(next table)
-
-* PHYS_FLOOD
-
- TYPE_VLAN
- for each networks:
- // provision_tenant_physnet, reclaim_tenant_physnet
- metadata=LOCAL|xxx, push_vlan:0x8100,set_field:present|yyy->vlan_vid,
- output:x,pop_vlan,goto(next table)
- TYPE_FLAT
- for each networks:
- // provision_tenant_physnet, reclaim_tenant_physnet
- metadata=LOCAL|xxx, output:x,goto(next table)
-
- default goto(next table)
-
-* LOCAL_FLOOD
-
- for each networks:
- // local_flood_update, local_flood_delete
- metadata=xxx, output:i,j,k
- or
- metadata=xxx,eth_dst=broadcast, output:i,j,k
-
- default drop
-
-* references
-** OVS agent https://wiki.openstack.org/wiki/Ovs-flow-logic
-*** we use metadata instead of "internal" VLANs
-*** we don't want to use NX learn action
-"""
-
-from ryu.lib.packet import arp
-from ryu.ofproto import ether
-
-from neutron.plugins.common import constants as p_const
-import neutron.plugins.ofagent.agent.metadata as meta
-from neutron.plugins.ofagent.agent import ofswitch
-from neutron.plugins.ofagent.agent import tables
-
-
-class OFAgentIntegrationBridge(ofswitch.OpenFlowSwitch):
- """ofagent br-int specific logic."""
-
- def setup_default_table(self):
- self.delete_flows()
-
- self.install_default_drop(tables.CHECK_IN_PORT)
-
- for t in tables.TUNNEL_IN.values():
- self.install_default_drop(t)
- self.install_default_goto(tables.PHYS_IN, tables.TUNNEL_OUT)
- self.install_default_goto_next(tables.LOCAL_IN)
- self.install_default_goto_next(tables.ARP_PASSTHROUGH)
- self.install_arp_responder(tables.ARP_RESPONDER)
-
- self.install_default_goto_next(tables.TUNNEL_OUT)
- self.install_default_goto_next(tables.LOCAL_OUT)
- self.install_default_goto_next(tables.PHYS_OUT)
-
- for t in tables.TUNNEL_FLOOD.values():
- self.install_default_goto_next(t)
- self.install_default_goto_next(tables.PHYS_FLOOD)
- self.install_default_drop(tables.LOCAL_FLOOD)
-
- def install_arp_responder(self, table_id):
- (dp, ofp, ofpp) = self._get_dp()
- match = ofpp.OFPMatch(eth_type=ether.ETH_TYPE_ARP,
- arp_op=arp.ARP_REQUEST)
- actions = [ofpp.OFPActionOutput(ofp.OFPP_CONTROLLER)]
- instructions = [
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)]
- msg = ofpp.OFPFlowMod(dp,
- table_id=table_id,
- priority=1,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
- self.install_default_goto_next(table_id)
-
- def install_tunnel_output(self, table_id,
- network, segmentation_id,
- ports, goto_next, **additional_matches):
- (dp, ofp, ofpp) = self._get_dp()
- match = ofpp.OFPMatch(metadata=meta.mk_metadata(network, meta.LOCAL),
- **additional_matches)
- actions = [ofpp.OFPActionSetField(tunnel_id=segmentation_id)]
- actions += [ofpp.OFPActionOutput(port=p) for p in ports]
- instructions = [
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions),
- ]
- if goto_next:
- instructions += [
- ofpp.OFPInstructionGotoTable(table_id=table_id + 1),
- ]
- msg = ofpp.OFPFlowMod(dp,
- table_id=table_id,
- priority=1,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
-
- def delete_tunnel_output(self, table_id,
- network, **additional_matches):
- (dp, _ofp, ofpp) = self._get_dp()
- self.delete_flows(table_id=table_id,
- metadata=meta.mk_metadata(network, meta.LOCAL),
- **additional_matches)
-
- def provision_tenant_tunnel(self, network_type, network, segmentation_id):
- (dp, _ofp, ofpp) = self._get_dp()
- match = ofpp.OFPMatch(tunnel_id=segmentation_id)
- metadata = meta.mk_metadata(network)
- instructions = [
- ofpp.OFPInstructionWriteMetadata(metadata=metadata[0],
- metadata_mask=metadata[1]),
- ofpp.OFPInstructionGotoTable(table_id=tables.TUNNEL_OUT),
- ]
- msg = ofpp.OFPFlowMod(dp,
- table_id=tables.TUNNEL_IN[network_type],
- priority=1,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
-
- def reclaim_tenant_tunnel(self, network_type, network, segmentation_id):
- table_id = tables.TUNNEL_IN[network_type]
- self.delete_flows(table_id=table_id, tunnel_id=segmentation_id)
-
- def provision_tenant_physnet(self, network_type, network,
- segmentation_id, phys_port):
- """for vlan and flat."""
- assert(network_type in [p_const.TYPE_VLAN, p_const.TYPE_FLAT])
- (dp, ofp, ofpp) = self._get_dp()
-
- # inbound
- metadata = meta.mk_metadata(network)
- instructions = [
- ofpp.OFPInstructionWriteMetadata(metadata=metadata[0],
- metadata_mask=metadata[1])
- ]
- if network_type == p_const.TYPE_VLAN:
- vlan_vid = segmentation_id | ofp.OFPVID_PRESENT
- match = ofpp.OFPMatch(in_port=phys_port, vlan_vid=vlan_vid)
- actions = [ofpp.OFPActionPopVlan()]
- instructions += [ofpp.OFPInstructionActions(
- ofp.OFPIT_APPLY_ACTIONS, actions)]
- else:
- match = ofpp.OFPMatch(in_port=phys_port)
- instructions += [ofpp.OFPInstructionGotoTable(table_id=tables.PHYS_IN)]
- msg = ofpp.OFPFlowMod(dp,
- priority=1,
- table_id=tables.CHECK_IN_PORT,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
-
- # outbound
- match = ofpp.OFPMatch(metadata=meta.mk_metadata(network, meta.LOCAL))
- if network_type == p_const.TYPE_VLAN:
- actions = [
- ofpp.OFPActionPushVlan(),
- ofpp.OFPActionSetField(vlan_vid=vlan_vid),
- ]
- else:
- actions = []
- actions += [ofpp.OFPActionOutput(port=phys_port)]
- if network_type == p_const.TYPE_VLAN:
- actions += [ofpp.OFPActionPopVlan()]
- instructions = [
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions),
- ofpp.OFPInstructionGotoTable(table_id=tables.PHYS_FLOOD + 1),
- ]
- msg = ofpp.OFPFlowMod(dp,
- priority=1,
- table_id=tables.PHYS_FLOOD,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
-
- def reclaim_tenant_physnet(self, network_type, network,
- segmentation_id, phys_port):
- (_dp, ofp, _ofpp) = self._get_dp()
- vlan_vid = segmentation_id | ofp.OFPVID_PRESENT
- if network_type == p_const.TYPE_VLAN:
- self.delete_flows(table_id=tables.CHECK_IN_PORT,
- in_port=phys_port, vlan_vid=vlan_vid)
- else:
- self.delete_flows(table_id=tables.CHECK_IN_PORT,
- in_port=phys_port)
- self.delete_flows(table_id=tables.PHYS_FLOOD,
- metadata=meta.mk_metadata(network))
-
- def check_in_port_add_tunnel_port(self, network_type, port):
- (dp, _ofp, ofpp) = self._get_dp()
- match = ofpp.OFPMatch(in_port=port)
- instructions = [
- ofpp.OFPInstructionGotoTable(
- table_id=tables.TUNNEL_IN[network_type])
- ]
- msg = ofpp.OFPFlowMod(dp,
- table_id=tables.CHECK_IN_PORT,
- priority=1,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
-
- def check_in_port_add_local_port(self, network, port):
- (dp, ofp, ofpp) = self._get_dp()
- match = ofpp.OFPMatch(in_port=port)
- metadata = meta.mk_metadata(network, meta.LOCAL)
- instructions = [
- ofpp.OFPInstructionWriteMetadata(metadata=metadata[0],
- metadata_mask=metadata[1]),
- ofpp.OFPInstructionGotoTable(table_id=tables.LOCAL_IN),
- ]
- msg = ofpp.OFPFlowMod(dp,
- table_id=tables.CHECK_IN_PORT,
- priority=1,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
-
- def check_in_port_delete_port(self, port):
- self.delete_flows(table_id=tables.CHECK_IN_PORT, in_port=port)
-
- def local_flood_update(self, network, ports, flood_unicast):
- (dp, ofp, ofpp) = self._get_dp()
- match_all = ofpp.OFPMatch(metadata=meta.mk_metadata(network))
- match_multicast = ofpp.OFPMatch(metadata=meta.mk_metadata(network),
- eth_dst=('01:00:00:00:00:00',
- '01:00:00:00:00:00'))
- if flood_unicast:
- match_add = match_all
- match_del = match_multicast
- else:
- match_add = match_multicast
- match_del = match_all
- actions = [ofpp.OFPActionOutput(port=p) for p in ports]
- instructions = [
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions),
- ]
- msg = ofpp.OFPFlowMod(dp,
- table_id=tables.LOCAL_FLOOD,
- priority=1,
- match=match_add,
- instructions=instructions)
- self._send_msg(msg)
- self.delete_flows(table_id=tables.LOCAL_FLOOD, strict=True,
- priority=1, match=match_del)
-
- def local_flood_delete(self, network):
- self.delete_flows(table_id=tables.LOCAL_FLOOD,
- metadata=meta.mk_metadata(network))
-
- def local_out_add_port(self, network, port, mac):
- (dp, ofp, ofpp) = self._get_dp()
- match = ofpp.OFPMatch(metadata=meta.mk_metadata(network), eth_dst=mac)
- actions = [ofpp.OFPActionOutput(port=port)]
- instructions = [
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions),
- ]
- msg = ofpp.OFPFlowMod(dp,
- table_id=tables.LOCAL_OUT,
- priority=1,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
-
- def local_out_delete_port(self, network, mac):
- self.delete_flows(table_id=tables.LOCAL_OUT,
- metadata=meta.mk_metadata(network), eth_dst=mac)
-
- def arp_passthrough(self, network, tpa):
- (dp, ofp, ofpp) = self._get_dp()
- match = ofpp.OFPMatch(metadata=meta.mk_metadata(network),
- eth_type=ether.ETH_TYPE_ARP,
- arp_op=arp.ARP_REQUEST,
- arp_tpa=tpa)
- instructions = [
- ofpp.OFPInstructionGotoTable(table_id=tables.TUNNEL_OUT)]
- msg = ofpp.OFPFlowMod(dp,
- table_id=tables.ARP_PASSTHROUGH,
- priority=1,
- idle_timeout=5,
- match=match,
- instructions=instructions)
- self._send_msg(msg)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 Fumihiko Kakuma <kakuma at valinux co jp>
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from ryu.lib import hub
-hub.patch()
-
-import sys
-
-from oslo_config import cfg
-from ryu.base.app_manager import AppManager
-from ryu import cfg as ryu_cfg
-
-from neutron.common import config as common_config
-
-
-def main():
- common_config.init(sys.argv[1:])
- # the following check is a transitional workaround to make this work
- # with different versions of ryu.
- # TODO(yamamoto) remove this later
- if ryu_cfg.CONF is not cfg.CONF:
- ryu_cfg.CONF(project='ryu', args=[])
- common_config.setup_logging()
- AppManager.run_apps(['neutron.plugins.ofagent.agent.ofa_neutron_agent'])
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from neutron.plugins.ofagent.agent import constants as const
-
-
-# metadata mask
-NETWORK_MASK = const.LOCAL_VLAN_MASK
-LOCAL = 0x10000 # the packet came from local vm ports
-
-
-def mk_metadata(network, flags=0):
- return (flags | network, flags | NETWORK_MASK)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from ryu.app.ofctl import api as ofctl_api
-
-
-class OpenFlowSwitch(object):
- def __init__(self, *args, **kwargs):
- super(OpenFlowSwitch, self).__init__(*args, **kwargs)
- self._dp = None
- # logically app doesn't belong here. just for convenience.
- self._app = None
-
- def set_dp(self, dp):
- self._dp = dp
-
- def set_app(self, app):
- self._app = app
-
- def _get_dp(self):
- """a convenient method for openflow message composers"""
- dp = self._dp
- return (dp, dp.ofproto, dp.ofproto_parser)
-
- def _send_msg(self, msg):
- return ofctl_api.send_msg(self._app, msg)
-
- def delete_flows(self, table_id=None, strict=False, priority=0,
- match=None, **match_kwargs):
- (dp, ofp, ofpp) = self._get_dp()
- if table_id is None:
- table_id = ofp.OFPTT_ALL
- if match is None:
- match = ofpp.OFPMatch(**match_kwargs)
- if strict:
- cmd = ofp.OFPFC_DELETE_STRICT
- else:
- cmd = ofp.OFPFC_DELETE
- msg = ofpp.OFPFlowMod(dp,
- command=cmd,
- table_id=table_id,
- match=match,
- priority=priority,
- out_group=ofp.OFPG_ANY,
- out_port=ofp.OFPP_ANY)
- self._send_msg(msg)
-
- def install_default_drop(self, table_id):
- (dp, _ofp, ofpp) = self._get_dp()
- msg = ofpp.OFPFlowMod(dp,
- table_id=table_id,
- priority=0)
- self._send_msg(msg)
-
- def install_default_goto(self, table_id, dest_table_id):
- (dp, _ofp, ofpp) = self._get_dp()
- instructions = [ofpp.OFPInstructionGotoTable(table_id=dest_table_id)]
- msg = ofpp.OFPFlowMod(dp,
- table_id=table_id,
- priority=0,
- instructions=instructions)
- self._send_msg(msg)
-
- def install_default_goto_next(self, table_id):
- self.install_default_goto(table_id, table_id + 1)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from neutron.common import constants as n_const
-
-
-class OFPort(object):
- def __init__(self, port_name, ofport):
- self.port_name = port_name
- self.ofport = ofport
-
- @classmethod
- def from_ofp_port(cls, ofp_port):
- """Convert from ryu OFPPort."""
- return cls(port_name=ofp_port.name, ofport=ofp_port.port_no)
-
-
-PORT_NAME_LEN = 14
-PORT_NAME_PREFIXES = [
- n_const.TAP_DEVICE_PREFIX, # common cases, including ovs_use_veth=True
- "qvo", # nova hybrid interface driver
- "qr-", # l3-agent INTERNAL_DEV_PREFIX (ovs_use_veth=False)
- "qg-", # l3-agent EXTERNAL_DEV_PREFIX (ovs_use_veth=False)
-]
-
-
-def _is_neutron_port(name):
- """Return True if the port name looks like a neutron port."""
- if len(name) != PORT_NAME_LEN:
- return False
- for pref in PORT_NAME_PREFIXES:
- if name.startswith(pref):
- return True
- return False
-
-
-def get_normalized_port_name(interface_id):
- """Convert from neutron device id (uuid) to "normalized" port name.
-
- This needs to be synced with ML2 plugin's _device_to_port_id().
-
- An assumption: The switch uses an OS's interface name as the
- corresponding OpenFlow port name.
- NOTE(yamamoto): While it's true for Open vSwitch, it isn't
- necessarily true everywhere. For example, LINC uses something
- like "LogicalSwitch0-Port2".
-
- NOTE(yamamoto): The actual prefix might be different. For example,
- with the hybrid interface driver, it's "qvo". However, we always
- use "tap" prefix throughout the agent and plugin for simplicity.
- Some care should be taken when talking to the switch.
- """
- return (n_const.TAP_DEVICE_PREFIX + interface_id)[0:PORT_NAME_LEN]
-
-
-def _normalize_port_name(name):
- """Normalize port name.
-
- See comments in _get_ofport_name.
- """
- for pref in PORT_NAME_PREFIXES:
- if name.startswith(pref):
- return n_const.TAP_DEVICE_PREFIX + name[len(pref):]
- return name
-
-
-class Port(OFPort):
- def __init__(self, *args, **kwargs):
- super(Port, self).__init__(*args, **kwargs)
- self.vif_mac = None
-
- def is_neutron_port(self):
- """Return True if the port looks like a neutron port."""
- return _is_neutron_port(self.port_name)
-
- def normalized_port_name(self):
- return _normalize_port_name(self.port_name)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from neutron.plugins.common import constants as p_const
-
-
-def _seq():
- """Yield sequential numbers starting from 0."""
- i = 0
- while True:
- yield i
- i += 1
-
-_table_id_gen = _seq()
-
-
-def _table_id():
- """A simple table id allocator."""
- return _table_id_gen.next()
-
-# Supported tunnel types.
-TUNNEL_TYPES = [
- p_const.TYPE_GRE,
- p_const.TYPE_VXLAN,
-]
-
-# Reversed version of TUNNEL_TYPES.
-TUNNEL_TYPE_IDX = dict((t, TUNNEL_TYPES.index(t)) for t in TUNNEL_TYPES)
-
-# We use sequential table ids starting from 0.
-# We don't hardcode values here to avoid manual reassignments eg. when adding
-# a new tunnel type.
-# See a big comment in flows.py for how each tables are used.
-CHECK_IN_PORT = _table_id()
-TUNNEL_IN = {}
-for t in TUNNEL_TYPES:
- TUNNEL_IN[t] = _table_id()
-PHYS_IN = _table_id()
-LOCAL_IN = _table_id()
-ARP_PASSTHROUGH = _table_id()
-ARP_RESPONDER = _table_id()
-TUNNEL_OUT = _table_id()
-LOCAL_OUT = _table_id()
-PHYS_OUT = _table_id()
-TUNNEL_FLOOD = {}
-for t in TUNNEL_TYPES:
- TUNNEL_FLOOD[t] = _table_id()
-PHYS_FLOOD = _table_id()
-LOCAL_FLOOD = _table_id()
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 Fumihiko Kakuma <kakuma at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_config import cfg
-
-from neutron.agent.common import config
-from neutron.plugins.openvswitch.common import config as ovs_config
-
-
-agent_opts = [
- cfg.IntOpt('get_datapath_retry_times', default=60,
- help=_("Number of seconds to retry acquiring "
- "an Open vSwitch datapath")),
- cfg.ListOpt('physical_interface_mappings',
- default=[],
- help=_("List of <physical_network>:<physical_interface>")),
-]
-
-
-cfg.CONF.register_opts(ovs_config.ovs_opts, 'OVS')
-cfg.CONF.register_opts(ovs_config.agent_opts, 'AGENT')
-cfg.CONF.register_opts(agent_opts, 'AGENT')
-config.register_agent_state_opts_helper(cfg.CONF)
+++ /dev/null
-# Copyright (c) 2014 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_config import cfg
-
-from neutron.common import constants
-from neutron.extensions import portbindings
-from neutron.plugins.ml2.drivers import mech_ofagent
-from neutron.tests.unit.ml2 import _test_mech_agent as base
-
-
-class OfagentMechanismBaseTestCase(base.AgentMechanismBaseTestCase):
- VIF_TYPE = portbindings.VIF_TYPE_OVS
- VIF_DETAILS = {portbindings.CAP_PORT_FILTER: True,
- portbindings.OVS_HYBRID_PLUG: True}
- AGENT_TYPE = constants.AGENT_TYPE_OFA
-
- GOOD_MAPPINGS = {'fake_physical_network': 'fake_interface'}
- GOOD_TUNNEL_TYPES = ['gre', 'vxlan']
- GOOD_CONFIGS = {'interface_mappings': GOOD_MAPPINGS,
- 'tunnel_types': GOOD_TUNNEL_TYPES}
-
- BAD_MAPPINGS = {'wrong_physical_network': 'wrong_interface'}
- BAD_TUNNEL_TYPES = ['bad_tunnel_type']
- BAD_CONFIGS = {'interface_mappings': BAD_MAPPINGS,
- 'tunnel_types': BAD_TUNNEL_TYPES}
-
- AGENTS = [{'alive': True,
- 'configurations': GOOD_CONFIGS,
- 'host': 'host'}]
- AGENTS_DEAD = [{'alive': False,
- 'configurations': GOOD_CONFIGS,
- 'host': 'dead_host'}]
- AGENTS_BAD = [{'alive': False,
- 'configurations': GOOD_CONFIGS,
- 'host': 'bad_host_1'},
- {'alive': True,
- 'configurations': BAD_CONFIGS,
- 'host': 'bad_host_2'}]
-
- def setUp(self):
- super(OfagentMechanismBaseTestCase, self).setUp()
- self.driver = mech_ofagent.OfagentMechanismDriver()
- self.driver.initialize()
-
-
-class OfagentMechanismSGDisabledBaseTestCase(OfagentMechanismBaseTestCase):
- VIF_DETAILS = {portbindings.CAP_PORT_FILTER: False,
- portbindings.OVS_HYBRID_PLUG: False}
-
- def setUp(self):
- cfg.CONF.set_override('enable_security_group',
- False,
- group='SECURITYGROUP')
- super(OfagentMechanismSGDisabledBaseTestCase, self).setUp()
-
-
-class OfagentMechanismGenericTestCase(OfagentMechanismBaseTestCase,
- base.AgentMechanismGenericTestCase):
- pass
-
-
-class OfagentMechanismLocalTestCase(OfagentMechanismBaseTestCase,
- base.AgentMechanismLocalTestCase):
- pass
-
-
-class OfagentMechanismFlatTestCase(OfagentMechanismBaseTestCase,
- base.AgentMechanismFlatTestCase):
- pass
-
-
-class OfagentMechanismVlanTestCase(OfagentMechanismBaseTestCase,
- base.AgentMechanismVlanTestCase):
- pass
-
-
-class OfagentMechanismGreTestCase(OfagentMechanismBaseTestCase,
- base.AgentMechanismGreTestCase):
- pass
-
-
-class OfagentMechanismSGDisabledLocalTestCase(
- OfagentMechanismSGDisabledBaseTestCase,
- base.AgentMechanismLocalTestCase):
- pass
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 Fumihiko Kakuma <kakuma at valinux co jp>
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import mock
-
-
-class _Eq(object):
- def __eq__(self, other):
- return repr(self) == repr(other)
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
-
-class _Value(_Eq):
- def __or__(self, b):
- return _Op('|', self, b)
-
- def __ror__(self, a):
- return _Op('|', a, self)
-
-
-class _SimpleValue(_Value):
- def __init__(self, name):
- self.name = name
-
- def __repr__(self):
- return self.name
-
-
-class _Op(_Value):
- def __init__(self, op, a, b):
- self.op = op
- self.a = a
- self.b = b
-
- def __repr__(self):
- return '%s%s%s' % (self.a, self.op, self.b)
-
-
-def _mkcls(name):
- class Cls(_Eq):
- _name = name
-
- def __init__(self, *args, **kwargs):
- self._args = args
- self._kwargs = kwargs
- self._hist = []
-
- def __getattr__(self, name):
- return self._kwargs[name]
-
- def __repr__(self):
- args = map(repr, self._args)
- kwargs = sorted(['%s=%s' % (x, y) for x, y in
- self._kwargs.items()])
- return '%s(%s)' % (self._name, ', '.join(args + kwargs))
-
- return Cls
-
-
-class _Mod(object):
- _cls_cache = {}
-
- def __init__(self, name):
- self._name = name
-
- def __getattr__(self, name):
- fullname = '%s.%s' % (self._name, name)
- if '_' in name: # constants are named like OFPxxx_yyy_zzz
- return _SimpleValue(fullname)
- try:
- return self._cls_cache[fullname]
- except KeyError:
- pass
- cls = _mkcls(fullname)
- self._cls_cache[fullname] = cls
- return cls
-
- def __repr__(self):
- return 'Mod(%s)' % (self._name,)
-
-
-def patch_fake_oflib_of():
- ryu_mod = mock.Mock()
- ryu_base_mod = ryu_mod.base
- ryu_ctrl_mod = ryu_mod.controller
- handler = _Mod('ryu.controller.handler')
- handler.set_ev_cls = mock.Mock()
- ofp_event = _Mod('ryu.controller.ofp_event')
- ryu_ctrl_mod.handler = handler
- ryu_ctrl_mod.ofp_event = ofp_event
- ryu_lib_mod = ryu_mod.lib
- ryu_lib_hub = ryu_lib_mod.hub
- ryu_packet_mod = ryu_lib_mod.packet
- packet = _Mod('ryu.lib.packet.packet')
- arp = _Mod('ryu.lib.packet.arp')
- ethernet = _Mod('ryu.lib.packet.ethernet')
- vlan = _Mod('ryu.lib.packet.vlan')
- ryu_packet_mod.packet = packet
- packet.Packet = mock.Mock()
- ryu_packet_mod.arp = arp
- ryu_packet_mod.ethernet = ethernet
- ryu_packet_mod.vlan = vlan
- ryu_ofproto_mod = ryu_mod.ofproto
- ether = _Mod('ryu.ofproto.ether')
- ofp = _Mod('ryu.ofproto.ofproto_v1_3')
- ofpp = _Mod('ryu.ofproto.ofproto_v1_3_parser')
- ryu_ofproto_mod.ether = ether
- ryu_ofproto_mod.ofproto_v1_3 = ofp
- ryu_ofproto_mod.ofproto_v1_3_parser = ofpp
- ryu_app_mod = ryu_mod.app
- ryu_app_ofctl_mod = ryu_app_mod.ofctl
- ryu_ofctl_api = ryu_app_ofctl_mod.api
- modules = {'ryu': ryu_mod,
- 'ryu.base': ryu_base_mod,
- 'ryu.controller': ryu_ctrl_mod,
- 'ryu.controller.handler': handler,
- 'ryu.controller.handler.set_ev_cls': handler.set_ev_cls,
- 'ryu.controller.ofp_event': ofp_event,
- 'ryu.lib': ryu_lib_mod,
- 'ryu.lib.hub': ryu_lib_hub,
- 'ryu.lib.packet': ryu_packet_mod,
- 'ryu.lib.packet.packet': packet,
- 'ryu.lib.packet.packet.Packet': packet.Packet,
- 'ryu.lib.packet.arp': arp,
- 'ryu.lib.packet.ethernet': ethernet,
- 'ryu.lib.packet.vlan': vlan,
- 'ryu.ofproto': ryu_ofproto_mod,
- 'ryu.ofproto.ether': ether,
- 'ryu.ofproto.ofproto_v1_3': ofp,
- 'ryu.ofproto.ofproto_v1_3_parser': ofpp,
- 'ryu.app': ryu_app_mod,
- 'ryu.app.ofctl': ryu_app_ofctl_mod,
- 'ryu.app.ofctl.api': ryu_ofctl_api}
- return mock.patch.dict('sys.modules', modules)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 Fumihiko Kakuma <kakuma at valinux co jp>
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import mock
-from oslo_config import cfg
-from oslo_utils import importutils
-
-from neutron.tests import base
-from neutron.tests.unit.ofagent import fake_oflib
-
-
-class OFATestBase(base.BaseTestCase):
-
- def setUp(self):
- self.fake_oflib_of = fake_oflib.patch_fake_oflib_of()
- self.fake_oflib_of.start()
- self.addCleanup(self.fake_oflib_of.stop)
- super(OFATestBase, self).setUp()
-
- def _mk_test_dp(self, name):
- ofp = importutils.import_module('ryu.ofproto.ofproto_v1_3')
- ofpp = importutils.import_module('ryu.ofproto.ofproto_v1_3_parser')
- dp = mock.Mock()
- dp.ofproto = ofp
- dp.ofproto_parser = ofpp
- dp.__repr__ = mock.Mock(return_value=name)
- return dp
-
- def _mk_test_br(self, name):
- dp = self._mk_test_dp(name)
- br = mock.Mock()
- br.datapath = dp
- br.ofproto = dp.ofproto
- br.ofparser = dp.ofproto_parser
- return br
-
-
-class OFAAgentTestBase(OFATestBase):
-
- _AGENT_NAME = 'neutron.plugins.ofagent.agent.ofa_neutron_agent'
-
- def setUp(self):
- super(OFAAgentTestBase, self).setUp()
- self.mod_agent = importutils.import_module(self._AGENT_NAME)
- self.ryuapp = mock.Mock()
-
- def setup_config(self):
- cfg.CONF.set_default('firewall_driver',
- 'neutron.agent.firewall.NoopFirewallDriver',
- group='SECURITYGROUP')
- cfg.CONF.register_cli_opts([
- cfg.StrOpt('ofp-listen-host', default='',
- help='openflow listen host'),
- cfg.IntOpt('ofp-tcp-listen-port', default=6633,
- help='openflow tcp listen port')
- ])
- super(OFATestBase, self).setup_config()
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 Fumihiko Kakuma <kakuma at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import collections
-import contextlib
-import copy
-
-import mock
-from oslo_utils import importutils
-
-import neutron.plugins.ofagent.agent.metadata as meta
-from neutron.tests.unit.ofagent import ofa_test_base
-
-
-_OFALIB_NAME = 'neutron.plugins.ofagent.agent.arp_lib'
-
-
-class OFAAgentTestCase(ofa_test_base.OFAAgentTestBase):
-
- def setUp(self):
- super(OFAAgentTestCase, self).setUp()
-
- Net = collections.namedtuple('Net', 'net, mac, ip')
- self.nets = [Net(net=10, mac='11:11:11:44:55:66', ip='10.1.2.20'),
- Net(net=10, mac='11:11:11:44:55:67', ip='10.1.2.21'),
- Net(net=20, mac='22:22:22:44:55:66', ip='10.2.2.20')]
-
- self.packet_mod = mock.Mock()
- self.proto_ethernet_mod = mock.Mock()
- self.proto_vlan_mod = mock.Mock()
- self.proto_vlan_mod.vid = 999
- self.proto_arp_mod = mock.Mock()
- self.fake_get_protocol = mock.Mock(return_value=self.proto_vlan_mod)
- self.packet_mod.get_protocol = self.fake_get_protocol
- self.fake_add_protocol = mock.Mock()
- self.packet_mod.add_protocol = self.fake_add_protocol
- self.arp = importutils.import_module('ryu.lib.packet.arp')
- self.ethernet = importutils.import_module('ryu.lib.packet.ethernet')
- self.vlan = importutils.import_module('ryu.lib.packet.vlan')
- mock.patch('ryu.lib.packet.packet.Packet',
- return_value=self.packet_mod).start()
-
- self.ryuapp = 'ryuapp'
- self.inport = '1'
- self.ev = mock.Mock()
- self.datapath = self._mk_test_dp('tun_br')
- self.ofproto = importutils.import_module('ryu.ofproto.ofproto_v1_3')
- self.ofpp = mock.Mock()
- self.datapath.ofproto = self.ofproto
- self.datapath.ofproto_parser = self.ofpp
- self.OFPActionOutput = mock.Mock()
- self.OFPActionOutput.return_value = 'OFPActionOutput'
- self.ofpp.OFPActionOutput = self.OFPActionOutput
- self.msg = mock.Mock()
- self.msg.datapath = self.datapath
- self.msg.buffer_id = self.ofproto.OFP_NO_BUFFER
- self.msg_data = 'test_message_data'
- self.msg.data = self.msg_data
- self.ev.msg = self.msg
- self.msg.match = {'in_port': self.inport,
- 'metadata': meta.LOCAL | self.nets[0].net}
-
-
-class TestArpLib(OFAAgentTestCase):
-
- def setUp(self):
- super(TestArpLib, self).setUp()
-
- self.mod_arplib = importutils.import_module(_OFALIB_NAME)
- self.arplib = self.mod_arplib.ArpLib(self.ryuapp)
- self.packet_mod.get_protocol = self._fake_get_protocol
- self._fake_get_protocol_ethernet = True
- self._fake_get_protocol_vlan = True
- self._fake_get_protocol_arp = True
- self.br = mock.Mock(datapath=self.datapath)
- self.arplib.set_bridge(self.br)
-
- def test__send_unknown_packet_no_buffer(self):
- in_port = 3
- out_port = self.ofproto.OFPP_TABLE
- self.msg.buffer_id = self.ofproto.OFP_NO_BUFFER
- self.arplib._send_unknown_packet(self.msg, in_port, out_port)
- actions = [self.ofpp.OFPActionOutput(self.ofproto.OFPP_TABLE, 0)]
- self.ofpp.OFPPacketOut.assert_called_once_with(
- datapath=self.datapath,
- buffer_id=self.msg.buffer_id,
- in_port=in_port,
- actions=actions,
- data=self.msg_data)
-
- def test__send_unknown_packet_existence_buffer(self):
- in_port = 3
- out_port = self.ofproto.OFPP_TABLE
- self.msg.buffer_id = 256
- self.arplib._send_unknown_packet(self.msg, in_port, out_port)
- actions = [self.ofpp.OFPActionOutput(self.ofproto.OFPP_TABLE, 0)]
- self.ofpp.OFPPacketOut.assert_called_once_with(
- datapath=self.datapath,
- buffer_id=self.msg.buffer_id,
- in_port=in_port,
- actions=actions,
- data=None)
-
- def test__respond_arp(self):
- self.arplib._arp_tbl = {
- self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}}
- port = 3
- arptbl = self.arplib._arp_tbl[self.nets[0].net]
- pkt_ethernet = self.ethernet
- pkt_vlan = self.vlan
- pkt_arp = self.arp
- pkt_arp.opcode = self.arp.ARP_REQUEST
- pkt_arp.dst_ip = self.nets[0].ip
- with mock.patch.object(
- self.arplib, '_send_arp_reply'
- ) as send_arp_rep_fn:
- self.assertTrue(
- self.arplib._respond_arp(self.datapath, port, arptbl,
- pkt_ethernet, pkt_vlan, pkt_arp))
- ethernet_ethernet = self.ethernet.ethernet(
- ethertype=pkt_ethernet.ethertype,
- dst=pkt_ethernet.src,
- src=self.nets[0].mac)
- vlan_vlan = self.vlan.vlan(cfi=pkt_vlan.cfi,
- ethertype=pkt_vlan.ethertype,
- pcp=pkt_vlan.pcp,
- vid=pkt_vlan.vid)
- arp_arp = self.arp.arp(opcode=self.arp.ARP_REPLY,
- src_mac=self.nets[0].mac,
- src_ip=pkt_arp.dst_ip,
- dst_mac=pkt_arp.src_mac,
- dst_ip=pkt_arp.src_ip)
- self.fake_add_protocol.assert_has_calls([mock.call(ethernet_ethernet),
- mock.call(vlan_vlan),
- mock.call(arp_arp)])
- send_arp_rep_fn.assert_called_once_with(
- self.datapath, port, self.packet_mod)
-
- def _test__respond_arp(self, pkt_arp):
- self.arplib._arp_tbl = {
- self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}}
- port = 3
- arptbl = self.arplib._arp_tbl[self.nets[0].net]
- pkt_ethernet = mock.Mock()
- pkt_vlan = mock.Mock()
- self.assertFalse(
- self.arplib._respond_arp(self.datapath, port, arptbl,
- pkt_ethernet, pkt_vlan, pkt_arp))
-
- def test__respond_arp_non_arp_req(self):
- pkt_arp = mock.Mock()
- pkt_arp.opcode = self.arp.ARP_REPLY
- self._test__respond_arp(pkt_arp)
-
- def test__respond_arp_ip_not_found_in_arptable(self):
- pkt_arp = mock.Mock()
- pkt_arp.opcode = self.arp.ARP_REQUEST
- pkt_arp.dst_ip = self.nets[1].ip
- self._test__respond_arp(pkt_arp)
-
- def test_add_arp_table_entry(self):
- self.arplib.add_arp_table_entry(self.nets[0].net,
- self.nets[0].ip, self.nets[0].mac)
- self.assertEqual(
- self.arplib._arp_tbl,
- {self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}})
-
- def test_add_arp_table_entry_multiple_net(self):
- self.arplib.add_arp_table_entry(self.nets[0].net,
- self.nets[0].ip, self.nets[0].mac)
- self.arplib.add_arp_table_entry(self.nets[2].net,
- self.nets[2].ip, self.nets[2].mac)
- self.assertEqual(
- self.arplib._arp_tbl,
- {self.nets[0].net: {self.nets[0].ip: self.nets[0].mac},
- self.nets[2].net: {self.nets[2].ip: self.nets[2].mac}})
-
- def test_add_arp_table_entry_multiple_ip(self):
- self.arplib.add_arp_table_entry(self.nets[0].net,
- self.nets[0].ip, self.nets[0].mac)
- self.arplib.add_arp_table_entry(self.nets[0].net,
- self.nets[1].ip, self.nets[1].mac)
- self.assertEqual(
- self.arplib._arp_tbl,
- {self.nets[0].net: {self.nets[0].ip: self.nets[0].mac,
- self.nets[1].ip: self.nets[1].mac}})
-
- def test_del_arp_table_entry(self):
- self.arplib._arp_tbl = {
- self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}}
- self.arplib.del_arp_table_entry(self.nets[0].net, self.nets[0].ip)
- self.assertEqual(self.arplib._arp_tbl, {})
-
- def test_del_arp_table_entry_unknown_network(self):
- self.arplib._arp_tbl = {
- 100: {"192.0.2.1": "fa:16:3e:e2:37:37"},
- }
- orig = copy.deepcopy(self.arplib._arp_tbl)
- self.arplib.del_arp_table_entry(200, "192.0.2.1")
- self.assertEqual(orig, self.arplib._arp_tbl)
-
- def test_del_arp_table_entry_unknown_ip(self):
- self.arplib._arp_tbl = {
- 100: {"192.0.2.1": "fa:16:3e:e2:37:37"},
- }
- orig = copy.deepcopy(self.arplib._arp_tbl)
- self.arplib.del_arp_table_entry(100, "192.0.2.9")
- self.assertEqual(orig, self.arplib._arp_tbl)
-
- def test_del_arp_table_entry_multiple_net(self):
- self.arplib._arp_tbl = {
- self.nets[0].net: {self.nets[0].ip: self.nets[0].mac},
- self.nets[2].net: {self.nets[2].ip: self.nets[2].mac}}
- self.arplib.del_arp_table_entry(self.nets[0].net, self.nets[0].ip)
- self.assertEqual(
- self.arplib._arp_tbl,
- {self.nets[2].net: {self.nets[2].ip: self.nets[2].mac}})
-
- def test_del_arp_table_entry_multiple_ip(self):
- self.arplib._arp_tbl = {
- self.nets[0].net: {self.nets[0].ip: self.nets[0].mac,
- self.nets[1].ip: self.nets[1].mac}}
- self.arplib.del_arp_table_entry(self.nets[0].net, self.nets[1].ip)
- self.assertEqual(
- self.arplib._arp_tbl,
- {self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}})
-
- def _fake_get_protocol(self, net_type):
- if net_type == self.ethernet.ethernet:
- if self._fake_get_protocol_ethernet:
- return self.proto_ethernet_mod
- else:
- return
- if net_type == self.vlan.vlan:
- if self._fake_get_protocol_vlan:
- return self.proto_vlan_mod
- else:
- return
- if net_type == self.arp.arp:
- if self._fake_get_protocol_arp:
- return self.proto_arp_mod
- else:
- return
-
- def _test_packet_in_handler(self):
- self.arplib._arp_tbl = {
- self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}}
- with contextlib.nested(
- mock.patch.object(self.arplib, '_respond_arp',
- return_value=True),
- mock.patch.object(self.br,
- 'arp_passthrough'),
- mock.patch.object(self.arplib,
- '_send_unknown_packet'),
- ) as (res_arp_fn, add_flow_fn, send_unknown_pk_fn):
- self.arplib.packet_in_handler(self.ev)
- self.assertFalse(add_flow_fn.call_count)
- self.assertFalse(send_unknown_pk_fn.call_count)
- res_arp_fn.assert_called_once_with(
- self.datapath, self.inport,
- self.arplib._arp_tbl[self.nets[0].net],
- self.proto_ethernet_mod,
- self.proto_vlan_mod if self._fake_get_protocol_vlan else None,
- self.proto_arp_mod)
-
- def _test_packet_in_handler_drop(self):
- self.arplib._arp_tbl = {
- self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}}
- with contextlib.nested(
- mock.patch.object(self.arplib, '_respond_arp',
- return_value=True),
- mock.patch.object(self.br, 'arp_passthrough'),
- mock.patch.object(self.arplib,
- '_send_unknown_packet'),
- ) as (res_arp_fn, add_flow_fn, send_unknown_pk_fn):
- self.arplib.packet_in_handler(self.ev)
- self.assertFalse(add_flow_fn.call_count)
- self.assertFalse(send_unknown_pk_fn.call_count)
- self.assertFalse(res_arp_fn.call_count)
-
- def test_packet_in_handler(self):
- self._test_packet_in_handler()
-
- def test_packet_in_handler_non_ethernet(self):
- self._fake_get_protocol_ethernet = False
- self._test_packet_in_handler_drop()
-
- def test_packet_in_handler_non_vlan(self):
- self._fake_get_protocol_vlan = False
- self._test_packet_in_handler()
-
- def test_packet_in_handler_non_arp(self):
- self._fake_get_protocol_arp = False
- self._test_packet_in_handler_drop()
-
- def test_packet_in_handler_corrupted(self):
- mock.patch('ryu.lib.packet.packet.Packet',
- side_effect=ValueError).start()
- self._test_packet_in_handler_drop()
-
- def test_packet_in_handler_unknown_network(self):
- self.arplib._arp_tbl = {
- self.nets[0].net: {self.nets[0].ip: self.nets[0].mac}}
- with contextlib.nested(
- mock.patch.object(self.arplib, '_respond_arp',
- return_value=False),
- mock.patch.object(self.br, 'arp_passthrough'),
- mock.patch.object(self.arplib,
- '_send_unknown_packet'),
- ) as (res_arp_fn, add_flow_fn, send_unknown_pk_fn):
- self.arplib.packet_in_handler(self.ev)
- add_flow_fn.assert_called_once_with(
- network=self.nets[0].net,
- tpa=self.proto_arp_mod.dst_ip)
- send_unknown_pk_fn.assert_called_once_with(
- self.ev.msg, self.msg.match['in_port'],
- self.datapath.ofproto.OFPP_TABLE)
- res_arp_fn.assert_called_once_with(
- self.datapath, self.inport,
- self.arplib._arp_tbl[self.nets[0].net],
- self.proto_ethernet_mod, self.proto_vlan_mod, self.proto_arp_mod)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-
-import mock
-from oslo_utils import importutils
-
-import neutron.plugins.ofagent.agent.metadata as meta
-from neutron.tests.unit.ofagent import ofa_test_base
-
-
-class TestOFAgentFlows(ofa_test_base.OFATestBase):
-
- _MOD = 'neutron.plugins.ofagent.agent.flows'
-
- def setUp(self):
- super(TestOFAgentFlows, self).setUp()
- self.mod = importutils.import_module(self._MOD)
- self.br = self.mod.OFAgentIntegrationBridge()
- self.br.set_dp(self._mk_test_dp("dp"))
-
- def test_setup_default_table(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.setup_default_table()
- (dp, ofp, ofpp) = br._get_dp()
- arp = importutils.import_module('ryu.lib.packet.arp')
- ether = importutils.import_module('ryu.ofproto.ether')
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(), out_group=ofp.OFPG_ANY,
- out_port=ofp.OFPP_ANY, priority=0, table_id=ofp.OFPTT_ALL)),
- call(ofpp.OFPFlowMod(dp, priority=0, table_id=0)),
- call(ofpp.OFPFlowMod(dp, priority=0, table_id=1)),
- call(ofpp.OFPFlowMod(dp, priority=0, table_id=2)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=7)],
- priority=0, table_id=3)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=5)],
- priority=0, table_id=4)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=6)],
- priority=0, table_id=5)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
- [ofpp.OFPActionOutput(ofp.OFPP_CONTROLLER)])],
- match=ofpp.OFPMatch(arp_op=arp.ARP_REQUEST,
- eth_type=ether.ETH_TYPE_ARP), priority=1, table_id=6)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=7)],
- priority=0, table_id=6)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=8)],
- priority=0, table_id=7)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=9)],
- priority=0, table_id=8)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=10)],
- priority=0, table_id=9)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=11)],
- priority=0, table_id=10)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=12)],
- priority=0, table_id=11)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=13)],
- priority=0, table_id=12)),
- call(ofpp.OFPFlowMod(dp, priority=0, table_id=13)),
- ]
- sendmsg.assert_has_calls(expected_calls, any_order=True)
-
- def test_install_arp_responder(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.install_arp_responder(table_id=99)
- (dp, ofp, ofpp) = br._get_dp()
- arp = importutils.import_module('ryu.lib.packet.arp')
- ether = importutils.import_module('ryu.ofproto.ether')
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
- [ofpp.OFPActionOutput(ofp.OFPP_CONTROLLER)])],
- match=ofpp.OFPMatch(arp_op=arp.ARP_REQUEST,
- eth_type=ether.ETH_TYPE_ARP), priority=1, table_id=99)),
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=100)],
- priority=0, table_id=99)),
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_install_tunnel_output(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.install_tunnel_output(table_id=110, network=111,
- segmentation_id=112, ports=[113, 114],
- goto_next=True)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(
- ofpp.OFPFlowMod(
- dp,
- instructions=[
- ofpp.OFPInstructionActions(
- ofp.OFPIT_APPLY_ACTIONS,
- [
- ofpp.OFPActionSetField(tunnel_id=112),
- ofpp.OFPActionOutput(port=113),
- ofpp.OFPActionOutput(port=114)
- ]
- ),
- ofpp.OFPInstructionGotoTable(table_id=111)
- ],
- match=ofpp.OFPMatch(
- metadata=meta.mk_metadata(111, meta.LOCAL)
- ),
- priority=1,
- table_id=110
- )
- )
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_delete_tunnel_output(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.delete_tunnel_output(table_id=110, network=111)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(
- ofpp.OFPFlowMod(
- dp,
- command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(
- metadata=meta.mk_metadata(111, meta.LOCAL)
- ),
- out_group=ofp.OFPG_ANY,
- out_port=ofp.OFPP_ANY, priority=0, table_id=110
- )
- )
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_provision_tenant_tunnel(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.provision_tenant_tunnel(network_type="gre", network=150,
- segmentation_id=151)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionWriteMetadata(metadata=150,
- metadata_mask=meta.NETWORK_MASK),
- ofpp.OFPInstructionGotoTable(table_id=7)],
- match=ofpp.OFPMatch(tunnel_id=151), priority=1, table_id=1))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_reclaim_tenant_tunnel(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.reclaim_tenant_tunnel(network_type="gre", network=150,
- segmentation_id=151)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(tunnel_id=151), out_group=ofp.OFPG_ANY,
- out_port=ofp.OFPP_ANY, priority=0, table_id=1))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_provision_tenant_physnet(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.provision_tenant_physnet(network_type="vlan", network=150,
- segmentation_id=151, phys_port=99)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionWriteMetadata(metadata=150,
- metadata_mask=meta.NETWORK_MASK),
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, [
- ofpp.OFPActionPopVlan()]),
- ofpp.OFPInstructionGotoTable(table_id=3)],
- match=ofpp.OFPMatch(in_port=99,
- vlan_vid=151 | ofp.OFPVID_PRESENT),
- priority=1, table_id=0)),
- call(
- ofpp.OFPFlowMod(
- dp,
- instructions=[
- ofpp.OFPInstructionActions(
- ofp.OFPIT_APPLY_ACTIONS,
- [
- ofpp.OFPActionPushVlan(),
- ofpp.OFPActionSetField(
- vlan_vid=151 | ofp.OFPVID_PRESENT
- ),
- ofpp.OFPActionOutput(port=99),
- ofpp.OFPActionPopVlan()
- ]
- ),
- ofpp.OFPInstructionGotoTable(table_id=13)
- ],
- match=ofpp.OFPMatch(
- metadata=meta.mk_metadata(150, meta.LOCAL)
- ),
- priority=1,
- table_id=12
- )
- )
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_reclaim_tenant_physnet(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.reclaim_tenant_physnet(network_type="vlan", network=150,
- segmentation_id=151, phys_port=99)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(in_port=99,
- vlan_vid=151 | ofp.OFPVID_PRESENT),
- out_group=ofp.OFPG_ANY, out_port=ofp.OFPP_ANY, priority=0,
- table_id=0)),
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(metadata=meta.mk_metadata(150)),
- out_group=ofp.OFPG_ANY, out_port=ofp.OFPP_ANY, priority=0,
- table_id=12))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_check_in_port_add_tunnel_port(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.check_in_port_add_tunnel_port(network_type="gre", port=99)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp,
- instructions=[ofpp.OFPInstructionGotoTable(table_id=1)],
- match=ofpp.OFPMatch(in_port=99), priority=1, table_id=0))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_check_in_port_add_local_port(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.check_in_port_add_local_port(network=123, port=99)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp,
- instructions=[
- ofpp.OFPInstructionWriteMetadata(
- metadata=meta.LOCAL | 123,
- metadata_mask=meta.LOCAL | meta.NETWORK_MASK),
- ofpp.OFPInstructionGotoTable(table_id=4)],
- match=ofpp.OFPMatch(in_port=99), priority=1, table_id=0))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_check_in_port_delete_port(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.check_in_port_delete_port(port=99)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(in_port=99), out_group=ofp.OFPG_ANY,
- out_port=ofp.OFPP_ANY, priority=0, table_id=0))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_local_flood_update(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.local_flood_update(network=1234, ports=[1, 2, 3],
- flood_unicast=True)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp,
- instructions=[ofpp.OFPInstructionActions(
- ofp.OFPIT_APPLY_ACTIONS, [
- ofpp.OFPActionOutput(port=1),
- ofpp.OFPActionOutput(port=2),
- ofpp.OFPActionOutput(port=3)])],
- match=ofpp.OFPMatch(metadata=meta.mk_metadata(1234)),
- priority=1, table_id=13)),
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE_STRICT,
- match=ofpp.OFPMatch(
- eth_dst=('01:00:00:00:00:00', '01:00:00:00:00:00'),
- metadata=meta.mk_metadata(1234)),
- out_group=ofp.OFPG_ANY, out_port=ofp.OFPP_ANY, priority=1,
- table_id=13))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_local_flood_delete(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.local_flood_delete(network=1234)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(metadata=meta.mk_metadata(1234)),
- out_group=ofp.OFPG_ANY, out_port=ofp.OFPP_ANY, priority=0,
- table_id=13))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_local_out_add_port(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.local_out_add_port(network=1234, port=7,
- mac='12:34:56:78:9a:bc')
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
- [ofpp.OFPActionOutput(port=7)])],
- match=ofpp.OFPMatch(eth_dst="12:34:56:78:9a:bc",
- metadata=meta.mk_metadata(1234)), priority=1, table_id=8))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_local_out_delete_port(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.local_out_delete_port(network=1234, mac='12:34:56:78:9a:bc')
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(eth_dst="12:34:56:78:9a:bc",
- metadata=meta.mk_metadata(1234)), out_group=ofp.OFPG_ANY,
- out_port=ofp.OFPP_ANY, priority=0, table_id=8))
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_arp_passthrough(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.arp_passthrough(network=1234, tpa='192.0.2.1')
- (dp, ofp, ofpp) = br._get_dp()
- arp = importutils.import_module('ryu.lib.packet.arp')
- ether = importutils.import_module('ryu.ofproto.ether')
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, idle_timeout=5,
- instructions=[ofpp.OFPInstructionGotoTable(table_id=7)],
- match=ofpp.OFPMatch(arp_op=arp.ARP_REQUEST,
- arp_tpa="192.0.2.1", eth_type=ether.ETH_TYPE_ARP,
- metadata=meta.mk_metadata(1234)), priority=1, table_id=5))
- ]
- sendmsg.assert_has_calls(expected_calls)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 Fumihiko Kakuma <kakuma at valinux co jp>
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Based on test for openvswitch agent(test_ovs_neutron_agent.py).
-#
-# Copyright (c) 2012 OpenStack Foundation.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import collections
-import contextlib
-import copy
-
-import mock
-import netaddr
-from oslo_config import cfg
-from oslo_utils import importutils
-import testtools
-
-from neutron.agent.linux import ovs_lib
-from neutron.common import constants as n_const
-from neutron.plugins.common import constants as p_const
-from neutron.plugins.ml2.drivers.l2pop import rpc as l2pop_rpc
-from neutron.tests.unit.ofagent import ofa_test_base
-
-
-NOTIFIER = ('neutron.plugins.ml2.rpc.AgentNotifierApi')
-FLOODING_ENTRY = l2pop_rpc.PortInfo(*n_const.FLOODING_ENTRY)
-
-
-def _mock_port(is_neutron=True, normalized_name=None):
- p = mock.Mock()
- p.is_neutron_port.return_value = is_neutron
- if normalized_name:
- p.normalized_port_name.return_value = normalized_name
- return p
-
-
-class CreateAgentConfigMap(ofa_test_base.OFAAgentTestBase):
-
- def test_create_agent_config_map_succeeds(self):
- self.assertTrue(self.mod_agent.create_agent_config_map(cfg.CONF))
-
- def test_create_agent_config_map_fails_for_invalid_tunnel_config(self):
- # An ip address is required for tunneling but there is no default,
- # verify this for both gre and vxlan tunnels.
- cfg.CONF.set_override('tunnel_types', [p_const.TYPE_GRE],
- group='AGENT')
- with testtools.ExpectedException(ValueError):
- self.mod_agent.create_agent_config_map(cfg.CONF)
- cfg.CONF.set_override('tunnel_types', [p_const.TYPE_VXLAN],
- group='AGENT')
- with testtools.ExpectedException(ValueError):
- self.mod_agent.create_agent_config_map(cfg.CONF)
-
- def test_create_agent_config_map_fails_no_local_ip(self):
- # An ip address is required for tunneling but there is no default
- cfg.CONF.set_override('tunnel_types', [p_const.TYPE_VXLAN],
- group='AGENT')
- with testtools.ExpectedException(ValueError):
- self.mod_agent.create_agent_config_map(cfg.CONF)
-
- def test_create_agent_config_map_fails_for_invalid_tunnel_type(self):
- cfg.CONF.set_override('tunnel_types', ['foobar'], group='AGENT')
- with testtools.ExpectedException(ValueError):
- self.mod_agent.create_agent_config_map(cfg.CONF)
-
- def test_create_agent_config_map_multiple_tunnel_types(self):
- cfg.CONF.set_override('local_ip', '10.10.10.10', group='OVS')
- cfg.CONF.set_override('tunnel_types', [p_const.TYPE_GRE,
- p_const.TYPE_VXLAN], group='AGENT')
- cfgmap = self.mod_agent.create_agent_config_map(cfg.CONF)
- self.assertEqual(cfgmap['tunnel_types'],
- [p_const.TYPE_GRE, p_const.TYPE_VXLAN])
-
-
-class TestOFANeutronAgentBridge(ofa_test_base.OFAAgentTestBase):
-
- def setUp(self):
- super(TestOFANeutronAgentBridge, self).setUp()
- self.br_name = 'bridge1'
- self.ovs = self.mod_agent.Bridge(
- self.br_name, self.ryuapp)
-
- def test_find_datapath_id(self):
- with mock.patch.object(self.ovs, 'get_datapath_id',
- return_value='12345'):
- self.ovs.find_datapath_id()
- self.assertEqual(self.ovs.datapath_id, '12345')
-
- def _fake_get_datapath(self, app, datapath_id):
- if self.ovs.retry_count >= 2:
- datapath = mock.Mock()
- datapath.ofproto_parser = mock.Mock()
- return datapath
- self.ovs.retry_count += 1
- return None
-
- def test_get_datapath_normal(self):
- self.ovs.retry_count = 0
- with mock.patch.object(self.mod_agent.ryu_api, 'get_datapath',
- new=self._fake_get_datapath):
- self.ovs.datapath_id = '0x64'
- self.ovs.get_datapath(retry_max=4)
- self.assertEqual(self.ovs.retry_count, 2)
-
- def test_get_datapath_retry_out_by_default_time(self):
- cfg.CONF.set_override('get_datapath_retry_times', 3, group='AGENT')
- with mock.patch.object(self.mod_agent.ryu_api, 'get_datapath',
- return_value=None) as mock_get_datapath:
- with testtools.ExpectedException(SystemExit):
- self.ovs.datapath_id = '0x64'
- self.ovs.get_datapath(retry_max=3)
- self.assertEqual(mock_get_datapath.call_count, 3)
-
- def test_get_datapath_retry_out_by_specified_time(self):
- with mock.patch.object(self.mod_agent.ryu_api, 'get_datapath',
- return_value=None) as mock_get_datapath:
- with testtools.ExpectedException(SystemExit):
- self.ovs.datapath_id = '0x64'
- self.ovs.get_datapath(retry_max=2)
- self.assertEqual(mock_get_datapath.call_count, 2)
-
- def test_setup_ofp_default_par(self):
- with contextlib.nested(
- mock.patch.object(self.ovs, 'set_protocols'),
- mock.patch.object(self.ovs, 'set_controller'),
- mock.patch.object(self.ovs, 'find_datapath_id'),
- mock.patch.object(self.ovs, 'get_datapath'),
- ) as (mock_set_protocols, mock_set_controller,
- mock_find_datapath_id, mock_get_datapath):
- self.ovs.setup_ofp()
- mock_set_protocols.assert_called_with('OpenFlow13')
- mock_set_controller.assert_called_with(['tcp:127.0.0.1:6633'])
- mock_get_datapath.assert_called_with(
- cfg.CONF.AGENT.get_datapath_retry_times)
- self.assertEqual(mock_find_datapath_id.call_count, 1)
-
- def test_setup_ofp_specify_par(self):
- controller_names = ['tcp:192.168.10.10:1234', 'tcp:172.17.16.20:5555']
- with contextlib.nested(
- mock.patch.object(self.ovs, 'set_protocols'),
- mock.patch.object(self.ovs, 'set_controller'),
- mock.patch.object(self.ovs, 'find_datapath_id'),
- mock.patch.object(self.ovs, 'get_datapath'),
- ) as (mock_set_protocols, mock_set_controller,
- mock_find_datapath_id, mock_get_datapath):
- self.ovs.setup_ofp(controller_names=controller_names,
- protocols='OpenFlow133',
- retry_max=11)
- mock_set_protocols.assert_called_with('OpenFlow133')
- mock_set_controller.assert_called_with(controller_names)
- mock_get_datapath.assert_called_with(11)
- self.assertEqual(mock_find_datapath_id.call_count, 1)
-
- def test_setup_ofp_with_except(self):
- with contextlib.nested(
- mock.patch.object(self.ovs, 'set_protocols',
- side_effect=RuntimeError),
- mock.patch.object(self.ovs, 'set_controller'),
- mock.patch.object(self.ovs, 'find_datapath_id'),
- mock.patch.object(self.ovs, 'get_datapath'),
- ) as (mock_set_protocols, mock_set_controller,
- mock_find_datapath_id, mock_get_datapath):
- with testtools.ExpectedException(SystemExit):
- self.ovs.setup_ofp()
-
-
-class TestOFANeutronAgent(ofa_test_base.OFAAgentTestBase):
-
- def setUp(self):
- super(TestOFANeutronAgent, self).setUp()
- notifier_p = mock.patch(NOTIFIER)
- notifier_cls = notifier_p.start()
- self.notifier = mock.Mock()
- notifier_cls.return_value = self.notifier
- kwargs = self.mod_agent.create_agent_config_map(cfg.CONF)
-
- class MockFixedIntervalLoopingCall(object):
- def __init__(self, f):
- self.f = f
-
- def start(self, interval=0):
- self.f()
-
- with contextlib.nested(
- mock.patch.object(self.mod_agent.OFANeutronAgent,
- 'setup_integration_br',
- return_value=mock.Mock()),
- mock.patch.object(self.mod_agent.Bridge,
- 'get_local_port_mac',
- return_value='00:00:00:00:00:01'),
- mock.patch('neutron.agent.linux.utils.get_interface_mac',
- return_value='00:00:00:00:00:01'),
- mock.patch('neutron.openstack.common.loopingcall.'
- 'FixedIntervalLoopingCall',
- new=MockFixedIntervalLoopingCall)):
- self.agent = self.mod_agent.OFANeutronAgent(self.ryuapp, **kwargs)
-
- self.agent.sg_agent = mock.Mock()
- self.int_dp = self._mk_test_dp('int_br')
- self.agent.int_br = self._mk_test_br('int_br')
- self.agent.int_br.set_dp(self.int_dp)
- self.agent.int_ofports['phys-net1'] = 666
-
- def _create_tunnel_port_name(self, tunnel_ip, tunnel_type):
- tunnel_ip_hex = '%08x' % netaddr.IPAddress(tunnel_ip, version=4)
- return '%s-%s' % (tunnel_type, tunnel_ip_hex)
-
- def mock_scan_ports(self, port_set=None, registered_ports=None,
- updated_ports=None, port_tags_dict=None):
- port_tags_dict = port_tags_dict or {}
- with contextlib.nested(
- mock.patch.object(self.agent, '_get_ofport_names',
- return_value=port_set),
- mock.patch.object(self.agent.int_br, 'get_port_tag_dict',
- return_value=port_tags_dict)
- ):
- return self.agent.scan_ports(registered_ports, updated_ports)
-
- def test_scan_ports_returns_current_only_for_unchanged_ports(self):
- vif_port_set = set([1, 3])
- registered_ports = set([1, 3])
- expected = {'current': vif_port_set}
- actual = self.mock_scan_ports(vif_port_set, registered_ports)
- self.assertEqual(expected, actual)
-
- def test_scan_ports_returns_port_changes(self):
- vif_port_set = set([1, 3])
- registered_ports = set([1, 2])
- expected = dict(current=vif_port_set, added=set([3]), removed=set([2]))
- actual = self.mock_scan_ports(vif_port_set, registered_ports)
- self.assertEqual(expected, actual)
-
- def _test_scan_ports_with_updated_ports(self, updated_ports):
- vif_port_set = set([1, 3, 4])
- registered_ports = set([1, 2, 4])
- expected = dict(current=vif_port_set, added=set([3]),
- removed=set([2]), updated=set([4]))
- actual = self.mock_scan_ports(vif_port_set, registered_ports,
- updated_ports)
- self.assertEqual(expected, actual)
-
- def test_scan_ports_finds_known_updated_ports(self):
- self._test_scan_ports_with_updated_ports(set([4]))
-
- def test_scan_ports_ignores_unknown_updated_ports(self):
- # the port '5' was not seen on current ports. Hence it has either
- # never been wired or already removed and should be ignored
- self._test_scan_ports_with_updated_ports(set([4, 5]))
-
- def test_scan_ports_ignores_updated_port_if_removed(self):
- vif_port_set = set([1, 3])
- registered_ports = set([1, 2])
- updated_ports = set([1, 2])
- expected = dict(current=vif_port_set, added=set([3]),
- removed=set([2]), updated=set([1]))
- actual = self.mock_scan_ports(vif_port_set, registered_ports,
- updated_ports)
- self.assertEqual(expected, actual)
-
- def test_scan_ports_no_vif_changes_returns_updated_port_only(self):
- vif_port_set = set([1, 2, 3])
- registered_ports = set([1, 2, 3])
- updated_ports = set([2])
- expected = dict(current=vif_port_set, updated=set([2]))
- actual = self.mock_scan_ports(vif_port_set, registered_ports,
- updated_ports)
- self.assertEqual(expected, actual)
-
- def test_treat_devices_added_returns_true_for_missing_device(self):
- with contextlib.nested(
- mock.patch.object(self.agent.plugin_rpc, 'get_device_details',
- side_effect=Exception()),
- mock.patch.object(self.agent, '_get_ports',
- return_value=[_mock_port(True, 'xxx')])):
- self.assertTrue(self.agent.treat_devices_added_or_updated(['xxx']))
-
- def _mock_treat_devices_added_updated(self, details, port, all_ports,
- func_name):
- """Mock treat devices added or updated.
-
- :param details: the details to return for the device
- :param port: port name to process
- :param all_ports: the port that _get_ports return
- :param func_name: the function that should be called
- :returns: whether the named function was called
- """
- with contextlib.nested(
- mock.patch.object(self.agent.plugin_rpc, 'get_device_details',
- return_value=details),
- mock.patch.object(self.agent, '_get_ports',
- return_value=all_ports),
- mock.patch.object(self.agent.plugin_rpc, 'update_device_up'),
- mock.patch.object(self.agent.plugin_rpc, 'update_device_down'),
- mock.patch.object(self.agent, func_name)
- ) as (get_dev_fn, _get_ports, upd_dev_up, upd_dev_down, func):
- self.assertFalse(self.agent.treat_devices_added_or_updated([port]))
- _get_ports.assert_called_once_with(self.agent.int_br)
- return func.called
-
- def test_treat_devices_added_updated_ignores_invalid_ofport(self):
- port_name = 'hoge'
- p1 = _mock_port(True, port_name)
- p1.ofport = -1
- self.assertFalse(self._mock_treat_devices_added_updated(
- mock.MagicMock(), port_name, [p1], 'port_dead'))
-
- def test_treat_devices_added_updated_marks_unknown_port_as_dead(self):
- port_name = 'hoge'
- p1 = _mock_port(True, port_name)
- p1.ofport = 1
- self.assertTrue(self._mock_treat_devices_added_updated(
- mock.MagicMock(), port_name, [p1], 'port_dead'))
-
- def test_treat_devices_added_does_not_process_missing_port(self):
- with contextlib.nested(
- mock.patch.object(self.agent.plugin_rpc, 'get_device_details'),
- mock.patch.object(self.agent.int_br, 'get_vif_port_by_id',
- return_value=None)
- ) as (get_dev_fn, get_vif_func):
- self.assertFalse(get_dev_fn.called)
-
- def test_treat_devices_added_updated_updates_known_port(self):
- port_name = 'tapd3315981-0b'
- p1 = _mock_port(False)
- p2 = _mock_port(True, port_name)
- ports = [p1, p2]
- details = mock.MagicMock()
- details.__contains__.side_effect = lambda x: True
- self.assertTrue(self._mock_treat_devices_added_updated(
- details, port_name, ports, 'treat_vif_port'))
-
- def test_treat_devices_added_updated_put_port_down(self):
- fake_details_dict = {'admin_state_up': False,
- 'port_id': 'xxx',
- 'device': 'xxx',
- 'network_id': 'yyy',
- 'physical_network': 'foo',
- 'segmentation_id': 'bar',
- 'network_type': 'baz'}
- with contextlib.nested(
- mock.patch.object(self.agent.plugin_rpc, 'get_device_details',
- return_value=fake_details_dict),
- mock.patch.object(self.agent, '_get_ports',
- return_value=[_mock_port(True, 'xxx')]),
- mock.patch.object(self.agent.plugin_rpc, 'update_device_up'),
- mock.patch.object(self.agent.plugin_rpc, 'update_device_down'),
- mock.patch.object(self.agent, 'treat_vif_port')
- ) as (get_dev_fn, _get_ports, upd_dev_up,
- upd_dev_down, treat_vif_port):
- self.assertFalse(self.agent.treat_devices_added_or_updated(
- ['xxx']))
- self.assertTrue(treat_vif_port.called)
- self.assertTrue(upd_dev_down.called)
- _get_ports.assert_called_once_with(self.agent.int_br)
-
- def test_treat_devices_removed_returns_true_for_missing_device(self):
- with mock.patch.object(self.agent.plugin_rpc, 'update_device_down',
- side_effect=Exception()):
- self.assertTrue(self.agent.treat_devices_removed([{}]))
-
- def _mock_treat_devices_removed(self, port_exists):
- details = dict(exists=port_exists)
- with mock.patch.object(self.agent.plugin_rpc, 'update_device_down',
- return_value=details):
- with mock.patch.object(self.agent, 'port_unbound') as port_unbound:
- self.assertFalse(self.agent.treat_devices_removed([{}]))
- self.assertTrue(port_unbound.called)
-
- def test_treat_devices_removed_unbinds_port(self):
- self._mock_treat_devices_removed(True)
-
- def test_treat_devices_removed_ignores_missing_port(self):
- self._mock_treat_devices_removed(False)
-
- def _test_process_network_ports(self, port_info):
- with contextlib.nested(
- mock.patch.object(self.agent.sg_agent, "setup_port_filters"),
- mock.patch.object(self.agent, "treat_devices_added_or_updated",
- return_value=False),
- mock.patch.object(self.agent, "treat_devices_removed",
- return_value=False)
- ) as (setup_port_filters, device_added_updated, device_removed):
- self.assertFalse(self.agent.process_network_ports(port_info))
- setup_port_filters.assert_called_once_with(
- port_info['added'], port_info.get('updated', set()))
- device_added_updated.assert_called_once_with(
- port_info['added'] | port_info.get('updated', set()))
- device_removed.assert_called_once_with(port_info['removed'])
-
- def test_process_network_ports(self):
- self._test_process_network_ports(
- {'current': set(['tap0']),
- 'removed': set(['eth0']),
- 'added': set(['eth1'])})
-
- def test_process_network_port_with_updated_ports(self):
- self._test_process_network_ports(
- {'current': set(['tap0', 'tap1']),
- 'updated': set(['tap1', 'eth1']),
- 'removed': set(['eth0']),
- 'added': set(['eth1'])})
-
- def test_report_state(self):
- with mock.patch.object(self.agent.state_rpc,
- "report_state") as report_st:
- self.agent.int_br_device_count = 5
- self.agent._report_state()
- report_st.assert_called_with(self.agent.context,
- self.agent.agent_state)
- self.assertNotIn("start_flag", self.agent.agent_state)
- self.assertEqual(
- self.agent.agent_state["configurations"]["devices"],
- self.agent.int_br_device_count
- )
-
- def test_port_update(self):
- port = {"id": "b1981919-f516-11e3-a8f4-08606e7f74e7",
- "network_id": "124",
- "admin_state_up": False}
- self.agent.port_update("unused_context",
- port=port,
- network_type="vlan",
- segmentation_id="1",
- physical_network="physnet")
- self.assertEqual(set(['tapb1981919-f5']), self.agent.updated_ports)
-
- def test_setup_physical_interfaces(self):
- with mock.patch.object(self.agent.int_br, "add_port") as add_port_fn:
- add_port_fn.return_value = "111"
- self.agent.setup_physical_interfaces({"physnet1": "eth1"})
- add_port_fn.assert_called_once_with("eth1")
- self.assertEqual(111, self.agent.int_ofports["physnet1"])
-
- def test_port_unbound(self):
- with contextlib.nested(
- mock.patch.object(self.agent, "reclaim_local_vlan"),
- mock.patch.object(self.agent, "get_net_uuid",
- return_value="netuid12345"),
- ) as (reclvl_fn, _):
- self.agent.enable_tunneling = True
- lvm = mock.Mock()
- lvm.network_type = "gre"
- lvm.vif_ports = {"vif1": mock.Mock()}
- self.agent.local_vlan_map["netuid12345"] = lvm
- self.agent.port_unbound("vif1")
- self.assertTrue(reclvl_fn.called)
-
- def _prepare_l2_pop_ofports(self, network_type=None):
- LVM = collections.namedtuple('LVM', 'net, vlan, segid, ip')
- self.lvms = [LVM(net='net1', vlan=11, segid=21, ip='1.1.1.1'),
- LVM(net='net2', vlan=12, segid=22, ip='2.2.2.2')]
- self.tunnel_type = 'gre'
- self.tun_name1 = self._create_tunnel_port_name(self.lvms[0].ip,
- self.tunnel_type)
- self.tun_name2 = self._create_tunnel_port_name(self.lvms[1].ip,
- self.tunnel_type)
- if network_type is None:
- network_type = self.tunnel_type
- lvm1 = mock.Mock()
- lvm1.network_type = network_type
- lvm1.vlan = self.lvms[0].vlan
- lvm1.segmentation_id = self.lvms[0].segid
- lvm1.tun_ofports = set([1])
- lvm2 = mock.Mock()
- lvm2.network_type = network_type
- lvm2.vlan = self.lvms[1].vlan
- lvm2.segmentation_id = self.lvms[1].segid
- lvm2.tun_ofports = set([1, 2])
- self.agent.tunnel_types = [self.tunnel_type]
- self.agent.local_vlan_map = {self.lvms[0].net: lvm1,
- self.lvms[1].net: lvm2}
- self.agent.tun_ofports = {self.tunnel_type:
- {self.lvms[0].ip: 1,
- self.lvms[1].ip: 2}}
-
- def test_fdb_ignore_network(self):
- self._prepare_l2_pop_ofports()
- fdb_entry = {'net3': {}}
- with contextlib.nested(
- mock.patch.object(self.agent, '_setup_tunnel_port'),
- mock.patch.object(self.agent, 'cleanup_tunnel_port')
- ) as (add_tun_fn, clean_tun_fn):
- self.agent.fdb_add(None, fdb_entry)
- self.assertFalse(add_tun_fn.called)
- self.agent.fdb_remove(None, fdb_entry)
- self.assertFalse(clean_tun_fn.called)
-
- def test_fdb_ignore_self(self):
- self._prepare_l2_pop_ofports()
- self.agent.local_ip = 'agent_ip'
- fdb_entry = {self.lvms[1].net:
- {'network_type': self.tunnel_type,
- 'segment_id': 'tun2',
- 'ports':
- {'agent_ip':
- [l2pop_rpc.PortInfo('mac', 'ip'),
- FLOODING_ENTRY]}}}
- with contextlib.nested(
- mock.patch.object(self.agent.ryuapp, "add_arp_table_entry"),
- mock.patch.object(self.agent.ryuapp, "del_arp_table_entry"),
- ) as (add_fn, del_fn):
- self.agent.fdb_add(None, copy.deepcopy(fdb_entry))
- add_fn.assert_called_once_with(12, 'ip', 'mac')
- self.assertFalse(del_fn.called)
- self.agent.fdb_remove(None, fdb_entry)
- add_fn.assert_called_once_with(12, 'ip', 'mac')
- del_fn.assert_called_once_with(12, 'ip')
-
- def test_fdb_add_flows(self):
- self._prepare_l2_pop_ofports()
- fdb_entry = {self.lvms[0].net:
- {'network_type': self.tunnel_type,
- 'segment_id': 'tun1',
- 'ports':
- {self.lvms[1].ip:
- [l2pop_rpc.PortInfo('mac', 'ip'),
- FLOODING_ENTRY]}}}
- with contextlib.nested(
- mock.patch.object(self.agent, '_setup_tunnel_port'),
- mock.patch.object(self.agent.int_br, 'install_tunnel_output'),
- mock.patch.object(self.agent.int_br, 'delete_tunnel_output'),
- ) as (add_tun_fn, install_fn, delete_fn):
- add_tun_fn.return_value = 2
- self.agent.fdb_add(None, fdb_entry)
- self.assertEqual(2, install_fn.call_count)
- expected_calls = [
- mock.call(7, 11, 21, set([2]), eth_dst='mac', goto_next=False),
- mock.call(10, 11, 21, set([1, 2]), goto_next=True)
- ]
- install_fn.assert_has_calls(expected_calls)
- self.assertFalse(delete_fn.called)
-
- def test_fdb_del_flows(self):
- self._prepare_l2_pop_ofports()
- fdb_entry = {self.lvms[1].net:
- {'network_type': self.tunnel_type,
- 'segment_id': 'tun2',
- 'ports':
- {self.lvms[1].ip:
- [l2pop_rpc.PortInfo('mac', 'ip'),
- FLOODING_ENTRY]}}}
- with contextlib.nested(
- mock.patch.object(self.agent.int_br, 'install_tunnel_output'),
- mock.patch.object(self.agent.int_br, 'delete_tunnel_output'),
- ) as (install_fn, delete_fn):
- self.agent.fdb_remove(None, fdb_entry)
- install_fn.assert_called_once_with(10, 12, 22, set([1]),
- goto_next=True)
- delete_fn.assert_called_once_with(7, 12, eth_dst='mac')
-
- def test_fdb_add_port(self):
- self._prepare_l2_pop_ofports()
- tunnel_ip = '10.10.10.10'
- tun_name = self._create_tunnel_port_name(tunnel_ip,
- self.tunnel_type)
- fdb_entry = {self.lvms[0].net:
- {'network_type': self.tunnel_type,
- 'segment_id': 'tun1',
- 'ports': {self.lvms[0].ip: [l2pop_rpc.PortInfo('mac',
- 'ip')]}}}
- with mock.patch.object(self.agent, '_setup_tunnel_port') as add_tun_fn:
- self.agent.fdb_add(None, fdb_entry)
- self.assertFalse(add_tun_fn.called)
- fdb_entry[self.lvms[0].net]['ports'][tunnel_ip] = [
- l2pop_rpc.PortInfo('mac', 'ip')]
- self.agent.fdb_add(None, fdb_entry)
- add_tun_fn.assert_called_with(
- self.agent.int_br, tun_name, tunnel_ip, self.tunnel_type)
-
- def test_fdb_del_port(self):
- self._prepare_l2_pop_ofports()
- fdb_entry = {self.lvms[1].net:
- {'network_type': self.tunnel_type,
- 'segment_id': 'tun2',
- 'ports': {self.lvms[1].ip: [FLOODING_ENTRY]}}}
- with mock.patch.object(self.agent.int_br,
- 'delete_port') as del_port_fn:
- self.agent.fdb_remove(None, fdb_entry)
- del_port_fn.assert_called_once_with(self.tun_name2)
-
- def test_add_arp_table_entry(self):
- self._prepare_l2_pop_ofports()
- fdb_entry = {self.lvms[0].net:
- {'network_type': self.tunnel_type,
- 'segment_id': 'tun1',
- 'ports': {self.lvms[0].ip: [
- FLOODING_ENTRY,
- l2pop_rpc.PortInfo('mac1', 'ip1')],
- self.lvms[1].ip: [
- l2pop_rpc.PortInfo('mac2', 'ip2')],
- '192.0.2.1': [
- FLOODING_ENTRY,
- l2pop_rpc.PortInfo('mac3', 'ip3')]}}}
- with mock.patch.object(self.agent,
- 'setup_tunnel_port') as setup_tun_fn:
- self.agent.fdb_add(None, fdb_entry)
- calls = [
- mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan,
- 'ip1', 'mac1'),
- mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan,
- 'ip2', 'mac2')
- ]
- self.ryuapp.add_arp_table_entry.assert_has_calls(calls,
- any_order=True)
- setup_tun_fn.assert_called_once_with(self.agent.int_br,
- '192.0.2.1', 'gre')
-
- def _test_add_arp_table_entry_non_tunnel(self, network_type):
- self._prepare_l2_pop_ofports(network_type=network_type)
- fdb_entry = {self.lvms[0].net:
- {'network_type': network_type,
- 'segment_id': 'tun1',
- 'ports': {self.lvms[0].ip: [
- FLOODING_ENTRY,
- l2pop_rpc.PortInfo('mac1', 'ip1')],
- self.lvms[1].ip: [
- l2pop_rpc.PortInfo('mac2', 'ip2')],
- '192.0.2.1': [
- FLOODING_ENTRY,
- l2pop_rpc.PortInfo('mac3', 'ip3')]}}}
- with mock.patch.object(self.agent,
- 'setup_tunnel_port') as setup_tun_fn:
- self.agent.fdb_add(None, fdb_entry)
- calls = [
- mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan,
- 'ip1', 'mac1'),
- mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan,
- 'ip2', 'mac2')
- ]
- self.ryuapp.add_arp_table_entry.assert_has_calls(calls,
- any_order=True)
- self.assertFalse(setup_tun_fn.called)
-
- def test_add_arp_table_entry_vlan(self):
- self._test_add_arp_table_entry_non_tunnel('vlan')
-
- def test_add_arp_table_entry_flat(self):
- self._test_add_arp_table_entry_non_tunnel('flat')
-
- def test_add_arp_table_entry_local(self):
- self._test_add_arp_table_entry_non_tunnel('local')
-
- def test_del_arp_table_entry(self):
- self._prepare_l2_pop_ofports()
- fdb_entry = {self.lvms[0].net:
- {'network_type': self.tunnel_type,
- 'segment_id': 'tun1',
- 'ports': {self.lvms[0].ip: [
- FLOODING_ENTRY,
- l2pop_rpc.PortInfo('mac1', 'ip1')],
- self.lvms[1].ip: [
- l2pop_rpc.PortInfo('mac2', 'ip2')],
- '192.0.2.1': [
- FLOODING_ENTRY,
- l2pop_rpc.PortInfo('mac3', 'ip3')]}}}
- with mock.patch.object(self.agent,
- 'cleanup_tunnel_port') as cleanup_tun_fn:
- self.agent.fdb_remove(None, fdb_entry)
- calls = [
- mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan,
- 'ip1'),
- mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan,
- 'ip2')
- ]
- self.ryuapp.del_arp_table_entry.assert_has_calls(calls,
- any_order=True)
- cleanup_tun_fn.assert_called_once_with(self.agent.int_br, 1, 'gre')
-
- def _test_del_arp_table_entry_non_tunnel(self, network_type):
- self._prepare_l2_pop_ofports(network_type=network_type)
- fdb_entry = {self.lvms[0].net:
- {'network_type': network_type,
- 'segment_id': 'tun1',
- 'ports': {self.lvms[0].ip: [
- FLOODING_ENTRY,
- l2pop_rpc.PortInfo('mac1', 'ip1')],
- self.lvms[1].ip: [
- l2pop_rpc.PortInfo('mac2', 'ip2')],
- '192.0.2.1': [
- FLOODING_ENTRY,
- l2pop_rpc.PortInfo('mac3', 'ip3')]}}}
- with mock.patch.object(self.agent,
- 'cleanup_tunnel_port') as cleanup_tun_fn:
- self.agent.fdb_remove(None, fdb_entry)
- calls = [
- mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan,
- 'ip1'),
- mock.call(self.agent.local_vlan_map[self.lvms[0].net].vlan,
- 'ip2')
- ]
- self.ryuapp.del_arp_table_entry.assert_has_calls(calls,
- any_order=True)
- self.assertFalse(cleanup_tun_fn.called)
-
- def test_del_arp_table_entry_vlan(self):
- self._test_del_arp_table_entry_non_tunnel('vlan')
-
- def test_del_arp_table_entry_flat(self):
- self._test_del_arp_table_entry_non_tunnel('flat')
-
- def test_del_arp_table_entry_local(self):
- self._test_del_arp_table_entry_non_tunnel('local')
-
- def test_recl_lv_port_to_preserve(self):
- self._prepare_l2_pop_ofports()
- self.agent.enable_tunneling = True
- with mock.patch.object(
- self.agent.int_br, 'delete_port'
- ) as del_port_fn:
- self.agent.reclaim_local_vlan(self.lvms[0].net)
- self.assertFalse(del_port_fn.called)
-
- def test_recl_lv_port_to_remove(self):
- self._prepare_l2_pop_ofports()
- self.agent.enable_tunneling = True
- with mock.patch.object(self.agent.int_br,
- 'delete_port') as del_port_fn:
- self.agent.reclaim_local_vlan(self.lvms[1].net)
- del_port_fn.assert_called_once_with(self.tun_name2)
-
- def test__setup_tunnel_port_error_negative(self):
- with contextlib.nested(
- mock.patch.object(self.agent.int_br, 'add_tunnel_port',
- return_value=ovs_lib.INVALID_OFPORT),
- mock.patch.object(self.mod_agent.LOG, 'error')
- ) as (add_tunnel_port_fn, log_error_fn):
- ofport = self.agent._setup_tunnel_port(
- self.agent.int_br, 'gre-1', 'remote_ip', p_const.TYPE_GRE)
- add_tunnel_port_fn.assert_called_once_with(
- 'gre-1', 'remote_ip', self.agent.local_ip, p_const.TYPE_GRE,
- self.agent.vxlan_udp_port, self.agent.dont_fragment)
- log_error_fn.assert_called_once_with(
- _("Failed to set-up %(type)s tunnel port to %(ip)s"),
- {'type': p_const.TYPE_GRE, 'ip': 'remote_ip'})
- self.assertEqual(ofport, 0)
-
- def test_setup_tunnel_port_returns_zero_for_failed_port_add(self):
- with mock.patch.object(self.agent.int_br, 'add_tunnel_port',
- return_value=ovs_lib.INVALID_OFPORT):
- result = self.agent._setup_tunnel_port(self.agent.int_br, 'gre-1',
- 'remote_ip',
- p_const.TYPE_GRE)
- self.assertEqual(0, result)
-
- def test_tunnel_sync(self):
- self.agent.local_ip = 'agent_ip'
- self.agent.context = 'fake_context'
- self.agent.tunnel_types = ['vxlan']
- self.agent.host = cfg.CONF.host
- with mock.patch.object(
- self.agent.plugin_rpc, 'tunnel_sync'
- ) as tunnel_sync_rpc_fn:
- self.agent.tunnel_sync()
- tunnel_sync_rpc_fn.assert_called_once_with(
- self.agent.context,
- self.agent.local_ip,
- self.agent.tunnel_types[0],
- self.agent.host)
-
- def test__get_ports(self):
- ofpp = importutils.import_module('ryu.ofproto.ofproto_v1_3_parser')
- reply = [ofpp.OFPPortDescStatsReply(body=[ofpp.OFPPort(name='hoge',
- port_no=8)])]
- sendmsg = mock.Mock(return_value=reply)
- self.mod_agent.ryu_api.send_msg = sendmsg
- result = self.agent._get_ports(self.agent.int_br)
- result = list(result) # convert generator to list.
- self.assertEqual(1, len(result))
- self.assertEqual('hoge', result[0].port_name)
- self.assertEqual(8, result[0].ofport)
- expected_msg = ofpp.OFPPortDescStatsRequest(
- datapath=self.agent.int_br.datapath)
- sendmsg.assert_has_calls([mock.call(app=self.agent.ryuapp,
- msg=expected_msg, reply_cls=ofpp.OFPPortDescStatsReply,
- reply_multi=True)])
-
- def test__get_ofport_names(self):
- names = ['p111', 'p222', 'p333']
- ps = [_mock_port(True, x) for x in names]
- with mock.patch.object(self.agent, '_get_ports',
- return_value=ps) as _get_ports:
- result = self.agent._get_ofport_names('hoge')
- _get_ports.assert_called_once_with('hoge')
- self.assertEqual(set(names), result)
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-
-import mock
-
-from neutron.common import constants as n_const
-from neutron.plugins.ofagent.agent import ports
-from neutron.tests import base
-
-
-class TestOFAgentPorts(base.BaseTestCase):
- def test_port(self):
- name = 'foo03b9a237-0b'
- p1 = ports.Port(port_name=name, ofport=999)
- ryu_ofp_port = mock.Mock(port_no=999)
- ryu_ofp_port.name = name
- p2 = ports.Port.from_ofp_port(ofp_port=ryu_ofp_port)
- self.assertEqual(p1.port_name, p2.port_name)
- self.assertEqual(p1.ofport, p2.ofport)
- self.assertFalse(p1.is_neutron_port())
- self.assertFalse(p2.is_neutron_port())
-
- def test_neutron_port(self):
- for pref in ['qvo', 'qr-', 'qg-', n_const.TAP_DEVICE_PREFIX]:
- name = pref + '03b9a237-0b'
- p1 = ports.Port(port_name=name, ofport=999)
- ryu_ofp_port = mock.Mock(port_no=999)
- ryu_ofp_port.name = name
- p2 = ports.Port.from_ofp_port(ofp_port=ryu_ofp_port)
- self.assertEqual(p1.port_name, p2.port_name)
- self.assertEqual(p1.ofport, p2.ofport)
- self.assertTrue(p1.is_neutron_port())
- self.assertTrue(p2.is_neutron_port())
- self.assertTrue('tap03b9a237-0b', p1.normalized_port_name())
- self.assertTrue('tap03b9a237-0b', p2.normalized_port_name())
-
- def test_get_normalized_port_name(self):
- self.assertEqual('tap03b9a237-0b',
- ports.get_normalized_port_name(
- '03b9a237-0b1b-11e4-b537-08606e7f74e7'))
+++ /dev/null
-# Copyright (C) 2014 VA Linux Systems Japan K.K.
-# Copyright (C) 2014 YAMAMOTO Takashi <yamamoto at valinux co jp>
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-
-import mock
-from oslo_utils import importutils
-
-from neutron.tests.unit.ofagent import ofa_test_base
-
-
-class TestOFAgentFlows(ofa_test_base.OFATestBase):
-
- _MOD = 'neutron.plugins.ofagent.agent.ofswitch'
-
- def setUp(self):
- super(TestOFAgentFlows, self).setUp()
- self.mod = importutils.import_module(self._MOD)
- self.br = self.mod.OpenFlowSwitch()
- self.br.set_dp(self._mk_test_dp("dp"))
-
- def test_delete_flows(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.delete_flows()
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, command=ofp.OFPFC_DELETE,
- match=ofpp.OFPMatch(), out_group=ofp.OFPG_ANY,
- out_port=ofp.OFPP_ANY, priority=0, table_id=ofp.OFPTT_ALL)),
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_install_default_drop(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.install_default_drop(table_id=98)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, priority=0, table_id=98)),
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_install_default_goto(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.install_default_goto(table_id=98, dest_table_id=150)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=150)],
- priority=0, table_id=98)),
- ]
- sendmsg.assert_has_calls(expected_calls)
-
- def test_install_default_goto_next(self):
- br = self.br
- with mock.patch.object(br, '_send_msg') as sendmsg:
- br.install_default_goto_next(table_id=100)
- (dp, ofp, ofpp) = br._get_dp()
- call = mock.call
- expected_calls = [
- call(ofpp.OFPFlowMod(dp, instructions=[
- ofpp.OFPInstructionGotoTable(table_id=101)],
- priority=0, table_id=100)),
- ]
- sendmsg.assert_has_calls(expected_calls)
etc/neutron/rootwrap.d/l3.filters
etc/neutron/rootwrap.d/linuxbridge-plugin.filters
etc/neutron/rootwrap.d/nec-plugin.filters
- etc/neutron/rootwrap.d/ofagent.filters
etc/neutron/rootwrap.d/openvswitch-plugin.filters
etc/init.d = etc/init.d/neutron-server
etc/neutron/plugins/bigswitch =
neutron-rootwrap = oslo_rootwrap.cmd:main
neutron-usage-audit = neutron.cmd.usage_audit:main
neutron-metering-agent = neutron.cmd.eventlet.services.metering_agent:main
- neutron-ofagent-agent = neutron.plugins.ofagent.agent.main:main
neutron-sriov-nic-agent = neutron.plugins.sriovnicagent.sriov_nic_agent:main
neutron-sanity-check = neutron.cmd.sanity_check:main
neutron.core_plugins =
cisco_apic = neutron.plugins.ml2.drivers.cisco.apic.mechanism_apic:APICMechanismDriver
l2population = neutron.plugins.ml2.drivers.l2pop.mech_driver:L2populationMechanismDriver
bigswitch = neutron.plugins.ml2.drivers.mech_bigswitch.driver:BigSwitchMechanismDriver
- ofagent = neutron.plugins.ml2.drivers.mech_ofagent:OfagentMechanismDriver
+ ofagent = networking_ofagent.plugins.ml2.drivers.mech_ofagent:OfagentMechanismDriver
mlnx = neutron.plugins.ml2.drivers.mlnx.mech_mlnx:MlnxMechanismDriver
brocade = neutron.plugins.ml2.drivers.brocade.mechanism_brocade:BrocadeMechanism
fslsdn = neutron.plugins.ml2.drivers.freescale.mechanism_fslsdn:FslsdnMechanismDriver