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