5e6991387126399618805d4bbf457d3413d65dc9
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / flow / PortSecurity.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
10
11 import java.util.Collection;
12 import java.util.Set;
13
14 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
15 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
16 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
17 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Manage the table that enforces port security
41  *
42  */
43 public class PortSecurity extends FlowTable {
44     protected static final Logger LOG =
45             LoggerFactory.getLogger(PortSecurity.class);
46
47     public static short TABLE_ID;
48
49     public PortSecurity(OfContext ctx, short tableId) {
50         super(ctx);
51         this.TABLE_ID=tableId;
52     }
53
54     @Override
55     public short getTableId() {
56         return TABLE_ID;
57     }
58
59     @Override
60     public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) {
61
62         // Allow traffic from tunnel ports
63         NodeConnectorId tunnelIf = ctx.getSwitchManager().getTunnelPort(nodeId, TunnelTypeVxlan.class);
64         if (tunnelIf != null)
65             flowMap.writeFlow(nodeId, TABLE_ID, allowFromPort(tunnelIf));
66
67         // Allow traffic from tunnel ports
68         //TODO Bug 3546 - Difficult: External port is unrelated to Tenant, L3C, L2BD..
69
70         Set<NodeConnectorId> external =
71                 ctx.getSwitchManager().getExternalPorts(nodeId);
72         for (NodeConnectorId extIf : external) {
73             flowMap.writeFlow(nodeId, TABLE_ID, allowFromExternalPort(extIf));
74         }
75
76         // Default drop all
77         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
78
79         // Drop IP traffic that doesn't match a source IP rule
80         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(110), FlowUtils.ARP, TABLE_ID));
81         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(111), FlowUtils.IPv4, TABLE_ID));
82         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(112), FlowUtils.IPv6, TABLE_ID));
83
84         for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
85             OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
86
87             if (ofc != null && ofc.getNodeConnectorId() != null
88                     && (ofc.getLocationType() == null || LocationType.Internal.equals(ofc.getLocationType()))) {
89                 // Allow layer 3 traffic (ARP and IP) with the correct
90                 // source IP, MAC, and source port
91                 l3flow(flowMap, nodeId, ep, ofc, 120, false);
92                 l3flow(flowMap, nodeId, ep, ofc, 121, true);
93                 flowMap.writeFlow(nodeId, TABLE_ID, l3DhcpDoraFlow(ep, ofc, 115));
94
95                 // Allow layer 2 traffic with the correct source MAC and
96                 // source port (note lower priority than drop IP rules)
97                 flowMap.writeFlow(nodeId, TABLE_ID, l2flow(ep, ofc, 100));
98             }
99         }
100     }
101
102     private Flow allowFromPort(NodeConnectorId port) {
103         Match match = new MatchBuilder()
104                 .setInPort(port)
105                 .build();
106         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "allow", match);
107         FlowBuilder flowb = base()
108                 .setId(flowid)
109                 .setPriority(Integer.valueOf(200))
110                 .setMatch(match)
111                 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()));
112         return flowb.build();
113     }
114
115     private Flow allowFromExternalPort(NodeConnectorId port) {
116         Match match = new MatchBuilder()
117                 .setInPort(port)
118                 .build();
119         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "allowExternal", match);
120         FlowBuilder flowb = base()
121                 .setId(flowid)
122                 .setPriority(Integer.valueOf(200))
123                 .setMatch(match)
124                 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_INGRESS_NAT()));
125         return flowb.build();
126     }
127
128     private Flow l2flow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
129         Match match = new MatchBuilder()
130                 .setEthernetMatch(
131                         FlowUtils.ethernetMatch(ep.getMacAddress(), null, null))
132                 .setInPort(ofc.getNodeConnectorId())
133                 .build();
134         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "L2", match);
135         FlowBuilder flowb = base()
136                 .setPriority(priority)
137                 .setId(flowid)
138                 .setMatch(match)
139                 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()));
140
141         return flowb.build();
142     }
143
144     private Flow l3DhcpDoraFlow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
145
146         //TODO: Handle IPv6 DORA
147         Long etherType = FlowUtils.IPv4;
148         // DHCP DORA destination is broadcast
149         String ikey = "255.255.255.255/32";
150         Layer3Match m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
151
152         Match match = new MatchBuilder()
153                 .setEthernetMatch(
154                         FlowUtils.ethernetMatch(ep.getMacAddress(),
155                         null,
156                         etherType))
157                 .setLayer3Match(m)
158                 .setInPort(ofc.getNodeConnectorId())
159                 .build();
160         FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "dhcp", match);
161         Flow flow = base()
162                 .setPriority(priority)
163                 .setId(flowid)
164                 .setMatch(match)
165                 .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()))
166                 .build();
167
168         return flow;
169     }
170
171     private void l3flow(FlowMap flowMap, NodeId nodeId,
172                         Endpoint ep, OfOverlayContext ofc,
173                         Integer priority, boolean arp) {
174         if (ep.getL3Address() == null)
175             return;
176         for (L3Address l3 : ep.getL3Address()) {
177             if (l3.getIpAddress() == null)
178                 continue;
179             Layer3Match m = null;
180             Long etherType = null;
181             String ikey = null;
182             if (l3.getIpAddress().getIpv4Address() != null) {
183                 ikey = l3.getIpAddress().getIpv4Address().getValue() + "/32";
184                 if (arp) {
185                     m = new ArpMatchBuilder()
186                             .setArpSourceTransportAddress(new Ipv4Prefix(ikey))
187                             .build();
188                     etherType = FlowUtils.ARP;
189                 } else {
190                     m = new Ipv4MatchBuilder()
191                             .setIpv4Source(new Ipv4Prefix(ikey))
192                             .build();
193                     etherType = FlowUtils.IPv4;
194                 }
195             } else if (l3.getIpAddress().getIpv6Address() != null) {
196                 if (arp)
197                     continue;
198                 ikey = l3.getIpAddress().getIpv6Address().getValue() + "/128";
199                 m = new Ipv6MatchBuilder()
200                         .setIpv6Source(new Ipv6Prefix(ikey))
201                         .build();
202                 etherType = FlowUtils.IPv6;
203             } else {
204                 continue;
205             }
206             Match match = new MatchBuilder()
207                     .setEthernetMatch(
208                             FlowUtils.ethernetMatch(ep.getMacAddress(),
209                             null,
210                             etherType))
211                     .setLayer3Match(m)
212                     .setInPort(ofc.getNodeConnectorId())
213                     .build();
214             FlowId flowid = FlowIdUtils.newFlowId(TABLE_ID, "L3", match);
215             Flow flow = base()
216                     .setPriority(priority)
217                     .setId(flowid)
218                     .setMatch(match)
219                     .setInstructions(FlowUtils.gotoTableInstructions(ctx.getPolicyManager().getTABLEID_SOURCE_MAPPER()))
220                     .build();
221
222             flowMap.writeFlow(nodeId, TABLE_ID,flow);
223         }
224     }
225 }