/* * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.source; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.Sets; import org.opendaylight.groupbasedpolicy.dto.EgKey; import org.opendaylight.groupbasedpolicy.dto.IndexedTenant; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.EndpointManager; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable; import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint; import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5; import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; /** * <h1>Manage the table that assigns source endpoint group, bridge domain, and * router domain to registers to be used by other tables</h1> * * <i>Remote tunnel flow:</i><br> * Priority = 150<br> * Matches:<br> * - in_port (should be tunnel port), {@link NodeConnectorId} * - tunnel ID match {@link org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxTunId}<br> * Actions:<br> * - loadReg1 fixed value 0xffffff {@link NxmNxReg1}<br> * - loadReg4 {@link NxmNxReg4}<br> * - loadReg5 {@link NxmNxReg5}<br> * - loadReg6 {@link NxmNxReg6}<br> * - {@link GoToTable} DESTINATION MAPPER table * <p> * <i>Remote broadcast flow:</i><br> * Priority = 150<br> * Matches:<br> * - in_port (should be tunnel port), {@link NodeConnectorId} * - tunnel ID match {@link org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxTunId}<br> * Actions:<br> * - loadReg5 {@link NxmNxReg5}<br> * - {@link GoToTable} DESTINATION MAPPER table * <p> * <i>Local EP flow:</i><br> * Priority = 100<br> * Matches:<br> * - dl_src (source mac address) {@link org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress}<br> * - in_port (node connector ID) {@link NodeConnectorId}<br> * Actions:<br> * - loadReg0 {@link NxmNxReg0}<br> * - loadReg1 {@link NxmNxReg1}<br> * - loadReg4 {@link NxmNxReg4}<br> * - loadReg5 {@link NxmNxReg5}<br> * - loadReg6 {@link NxmNxReg6}<br> * - loadTunnelId<br> * - {@link GoToTable} DESTINATION MAPPER table */ public class SourceMapper extends FlowTable { // Priorities private static final int DROP_ALL = 1; private static final int SYNCHRONIZE_EP = 100; private static final int TUNNEL_FLOW = 151; private static final int BROADCAST_FLOW = 152; private final short tableId; public SourceMapper(OfContext ctx, short tableId) { super(ctx); this.tableId = tableId; } @Override public short getTableId() { return tableId; } @Override public void sync(Endpoint endpoint, OfWriter ofWriter) throws Exception { NodeId endpointNodeId = ctx.getEndpointManager().getEndpointNodeId(endpoint); if (endpointNodeId == null) { LOG.warn("Endpoint {} has no location specified, skipped", endpoint); return; } SourceMapperFlows flows = new SourceMapperFlows(endpointNodeId, tableId); syncFlows(flows, endpoint, endpointNodeId, ofWriter); } @VisibleForTesting void syncFlows(SourceMapperFlows flows, Endpoint endpoint, NodeId nodeId, OfWriter ofWriter) { // Basic drop all flow flows.dropFlow(DROP_ALL, null, ofWriter); // Create remote tunnel/broadcast flows short destinationMapperId = ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER(); NodeConnectorId tunnelPort = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class); if (tunnelPort != null) { // Get all original endpoint groups Set<EgKey> endpointGroups = getEndpointGroups(endpoint); for (EgKey endpointGroup : endpointGroups) { // Get all original endpoint peers Set<EgKey> peers = Sets.union(Collections.singleton(endpointGroup), ctx.getCurrentPolicy().getPeers(endpointGroup)); for (EgKey peer : peers) { Collection<Endpoint> peerEgEndpoints = ctx.getEndpointManager().getEndpointsForGroup(peer); for (Endpoint peerEgEndpoint : peerEgEndpoints) { OrdinalFactory.EndpointFwdCtxOrdinals ordinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, peerEgEndpoint); flows.createTunnelFlow(destinationMapperId, TUNNEL_FLOW, tunnelPort, ordinals, ofWriter); flows.createBroadcastFlow(destinationMapperId, BROADCAST_FLOW, tunnelPort, ordinals, ofWriter); } } } } if (endpoint.getEndpointGroup() == null && endpoint.getEndpointGroups() == null || endpoint.getTenant() == null) { return; } IndexedTenant tenant = ctx.getTenant(endpoint.getTenant()); // Sync the local EP information OrdinalFactory.EndpointFwdCtxOrdinals endpointFwdCtxOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint); MacAddress macAddress = endpoint.getMacAddress(); if (endpointFwdCtxOrdinals != null) { OfOverlayContext ofOverlayContext = endpoint.getAugmentation(OfOverlayContext.class); if (ofOverlayContext != null && ofOverlayContext.getNodeConnectorId() != null && (EndpointManager.isInternal(endpoint, tenant.getExternalImplicitGroups()))) { flows.synchronizeEp(destinationMapperId, SYNCHRONIZE_EP, endpointFwdCtxOrdinals, macAddress, ofOverlayContext.getNodeConnectorId(), ofWriter); } } } private Set<EgKey> getEndpointGroups(Endpoint endpoint) { Set<EgKey> endpointGroups = new HashSet<>(); if (endpoint.getEndpointGroup() != null) { endpointGroups.add(new EgKey(endpoint.getTenant(), endpoint.getEndpointGroup())); } if (endpoint.getEndpointGroups() != null) { for (EndpointGroupId epgId : endpoint.getEndpointGroups()) { endpointGroups.add(new EgKey(endpoint.getTenant(), epgId)); } } return endpointGroups; } }