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