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.MatchBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 * Manage the table that enforces port security
40 public class PortSecurity extends FlowTable {
41 protected static final Logger LOG =
42 LoggerFactory.getLogger(PortSecurity.class);
44 public static final short TABLE_ID = 0;
46 public PortSecurity(OfContext ctx) {
51 public short getTableId() {
56 public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) {
58 // Allow traffic from tunnel and external ports
59 NodeConnectorId tunnelIf = ctx.getSwitchManager().getTunnelPort(nodeId);
61 flowMap.writeFlow(nodeId, TABLE_ID, allowFromPort(tunnelIf));
62 Set<NodeConnectorId> external =
63 ctx.getSwitchManager().getExternalPorts(nodeId);
64 for (NodeConnectorId extIf : external) {
65 flowMap.writeFlow(nodeId, TABLE_ID, allowFromPort(extIf));
69 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null));
71 // Drop IP traffic that doesn't match a source IP rule
72 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(110), FlowUtils.ARP));
73 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(111), FlowUtils.IPv4));
74 flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(112), FlowUtils.IPv6));
76 for (EgKey sepg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
77 for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId, sepg)) {
78 OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
80 if (ofc != null && ofc.getNodeConnectorId() != null &&
81 (ofc.getLocationType() == null ||
82 LocationType.Internal.equals(ofc.getLocationType()))) {
83 // Allow layer 3 traffic (ARP and IP) with the correct
84 // source IP, MAC, and source port
85 l3flow(flowMap, nodeId, ep, ofc, 120, false);
86 l3flow(flowMap, nodeId, ep, ofc, 121, true);
87 flowMap.writeFlow(nodeId, TABLE_ID, l3DhcpDoraFlow(ep, ofc, 115));
89 // Allow layer 2 traffic with the correct source MAC and
90 // source port (note lower priority than drop IP rules)
91 flowMap.writeFlow(nodeId, TABLE_ID, l2flow(ep, ofc, 100));
97 private Flow allowFromPort(
98 NodeConnectorId port) {
99 FlowId flowid = new FlowId(new StringBuilder()
101 .append(port.getValue())
103 FlowBuilder flowb = base()
105 .setPriority(Integer.valueOf(200))
106 .setMatch(new MatchBuilder()
109 .setInstructions(FlowUtils.gotoTableInstructions((short) (getTableId() + 1)));
110 return flowb.build();
114 private Flow l2flow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
115 FlowId flowid = new FlowId(new StringBuilder()
116 .append(ofc.getNodeConnectorId().getValue())
118 .append(ep.getMacAddress().getValue())
120 FlowBuilder flowb = base()
121 .setPriority(priority)
123 .setMatch(new MatchBuilder()
124 .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
126 .setInPort(ofc.getNodeConnectorId())
128 .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)));
130 return flowb.build();
133 private Flow l3DhcpDoraFlow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
135 //TODO: Handle IPv6 DORA
136 Long etherType = FlowUtils.IPv4;
137 // DHCP DORA destination is broadcast
138 String ikey = "255.255.255.255/32";
139 Layer3Match m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
141 FlowId flowid = new FlowId(new StringBuilder()
142 .append(ofc.getNodeConnectorId().getValue())
144 .append(ep.getMacAddress().getValue())
149 .setPriority(priority)
151 .setMatch(new MatchBuilder()
152 .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
156 .setInPort(ofc.getNodeConnectorId())
158 .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)))
164 private void l3flow(FlowMap flowMap, NodeId nodeId,
165 Endpoint ep, OfOverlayContext ofc,
166 Integer priority, boolean arp) {
167 if (ep.getL3Address() == null)
169 for (L3Address l3 : ep.getL3Address()) {
170 if (l3.getIpAddress() == null)
172 Layer3Match m = null;
173 Long etherType = null;
175 if (l3.getIpAddress().getIpv4Address() != null) {
176 ikey = l3.getIpAddress().getIpv4Address().getValue() + "/32";
178 m = new ArpMatchBuilder()
179 .setArpSourceTransportAddress(new Ipv4Prefix(ikey))
181 etherType = FlowUtils.ARP;
183 m = new Ipv4MatchBuilder()
184 .setIpv4Source(new Ipv4Prefix(ikey))
186 etherType = FlowUtils.IPv4;
188 } else if (l3.getIpAddress().getIpv6Address() != null) {
191 ikey = l3.getIpAddress().getIpv6Address().getValue() + "/128";
192 m = new Ipv6MatchBuilder()
193 .setIpv6Source(new Ipv6Prefix(ikey))
195 etherType = FlowUtils.IPv6;
199 FlowId flowid = new FlowId(new StringBuilder()
200 .append(ofc.getNodeConnectorId().getValue())
202 .append(ep.getMacAddress().getValue())
209 .setPriority(priority)
211 .setMatch(new MatchBuilder()
212 .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
216 .setInPort(ofc.getNodeConnectorId())
218 .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)))
221 flowMap.writeFlow(nodeId, TABLE_ID,flow);