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