2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
13 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
14 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
15 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
16 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
39 * Manage the table that enforces port security
42 public class PortSecurity extends FlowTable {
43 protected static final Logger LOG =
44 LoggerFactory.getLogger(PortSecurity.class);
46 public static short TABLE_ID;
48 public PortSecurity(OfContext ctx, short tableId) {
50 this.TABLE_ID=tableId;
54 public short getTableId() {
59 public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) {
61 // Allow traffic from tunnel ports
62 NodeConnectorId tunnelIf = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
64 flowMap.writeFlow(nodeId, TABLE_ID, allowFromPort(tunnelIf));
66 // Allow traffic from tunnel ports
67 //TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
69 Set<NodeConnectorId> external =
70 ctx.getSwitchManager().getExternalPorts(nodeId);
71 for (NodeConnectorId extIf : external) {
72 flowMap.writeFlow(nodeId, TABLE_ID, allowFromExternalPort(extIf));
76 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
78 // Drop IP traffic that doesn't match a source IP rule
79 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(110), FlowUtils.ARP, TABLE_ID));
80 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(111), FlowUtils.IPv4, TABLE_ID));
81 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(112), FlowUtils.IPv6, TABLE_ID));
83 for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
84 OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
86 if (ofc != null && ofc.getNodeConnectorId() != null
87 && (ofc.getLocationType() == null || LocationType.Internal.equals(ofc.getLocationType()))) {
88 // Allow layer 3 traffic (ARP and IP) with the correct
89 // source IP, MAC, and source port
90 l3flow(flowMap, nodeId, ep, ofc, 120, false);
91 l3flow(flowMap, nodeId, ep, ofc, 121, true);
92 flowMap.writeFlow(nodeId, TABLE_ID, l3DhcpDoraFlow(ep, ofc, 115));
94 // Allow layer 2 traffic with the correct source MAC and
95 // source port (note lower priority than drop IP rules)
96 flowMap.writeFlow(nodeId, TABLE_ID, l2flow(ep, ofc, 100));
101 private Flow allowFromPort(NodeConnectorId port) {
102 Match match = new MatchBuilder()
105 FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "allow", match);
106 FlowBuilder flowb = base()
108 .setPriority(Integer.valueOf(200))
110 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()));
111 return flowb.build();
114 private Flow allowFromExternalPort(NodeConnectorId port) {
115 Match match = new MatchBuilder()
118 FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "allowExternal", match);
119 FlowBuilder flowb = base()
121 .setPriority(Integer.valueOf(200))
123 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_INGRESS_NAT()));
124 return flowb.build();
127 private Flow l2flow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
128 Match match = new MatchBuilder()
130 FlowUtils.ethernetMatch(ep.getMacAddress(), null, null))
131 .setInPort(ofc.getNodeConnectorId())
133 FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "L2", match);
134 FlowBuilder flowb = base()
135 .setPriority(priority)
138 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()));
140 return flowb.build();
143 private Flow l3DhcpDoraFlow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
145 //TODO: Handle IPv6 DORA
146 Long etherType = FlowUtils.IPv4;
147 // DHCP DORA destination is broadcast
148 String ikey = "255.255.255.255/32";
149 Layer3Match m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
151 Match match = new MatchBuilder()
153 FlowUtils.ethernetMatch(ep.getMacAddress(),
157 .setInPort(ofc.getNodeConnectorId())
159 FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "dhcp", match);
161 .setPriority(priority)
164 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()))
170 private void l3flow(FlowMap flowMap, NodeId nodeId,
171 Endpoint ep, OfOverlayContext ofc,
172 Integer priority, boolean arp) {
173 if (ep.getL3Address() == null)
175 for (L3Address l3 : ep.getL3Address()) {
176 if (l3.getIpAddress() == null)
178 Layer3Match m = null;
179 Long etherType = null;
181 if (l3.getIpAddress().getIpv4Address() != null) {
182 ikey = l3.getIpAddress().getIpv4Address().getValue() + "/32";
184 m = new ArpMatchBuilder()
185 .setArpSourceTransportAddress(new Ipv4Prefix(ikey))
187 etherType = FlowUtils.ARP;
189 m = new Ipv4MatchBuilder()
190 .setIpv4Source(new Ipv4Prefix(ikey))
192 etherType = FlowUtils.IPv4;
194 } else if (l3.getIpAddress().getIpv6Address() != null) {
197 ikey = l3.getIpAddress().getIpv6Address().getValue() + "/128";
198 m = new Ipv6MatchBuilder()
199 .setIpv6Source(new Ipv6Prefix(ikey))
201 etherType = FlowUtils.IPv6;
205 Match match = new MatchBuilder()
207 FlowUtils.ethernetMatch(ep.getMacAddress(),
211 .setInPort(ofc.getNodeConnectorId())
213 FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "L3", match);
215 .setPriority(priority)
218 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()))
221 flowMap.writeFlow(nodeId, TABLE_ID,flow);