Adding multiple EPG capability to EPs and IntraEPG policy
[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.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 final short TABLE_ID = 0;
45
46     public PortSecurity(OfContext ctx) {
47         super(ctx);
48     }
49
50     @Override
51     public short getTableId() {
52         return TABLE_ID;
53     }
54
55     @Override
56     public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) {
57
58         // Allow traffic from tunnel and external ports
59         NodeConnectorId tunnelIf = ctx.getSwitchManager().getTunnelPort(nodeId);
60         if (tunnelIf != null)
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));
66         }
67
68         // Default drop all
69         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null));
70
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));
75
76         for (EgKey sepg : ctx.getEndpointManager().getGroupsForNode(nodeId)) {
77             for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId, sepg)) {
78                 OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
79
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));
88
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));
92                 }
93             }
94         }
95     }
96
97     private Flow allowFromPort(
98             NodeConnectorId port) {
99         FlowId flowid = new FlowId(new StringBuilder()
100                 .append("allow|")
101                 .append(port.getValue())
102                 .toString());
103         FlowBuilder flowb = base()
104                 .setId(flowid)
105                 .setPriority(Integer.valueOf(200))
106                 .setMatch(new MatchBuilder()
107                         .setInPort(port)
108                         .build())
109                 .setInstructions(FlowUtils.gotoTableInstructions((short) (getTableId() + 1)));
110         return flowb.build();
111
112     }
113
114     private Flow l2flow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
115         FlowId flowid = new FlowId(new StringBuilder()
116                 .append(ofc.getNodeConnectorId().getValue())
117                 .append("|")
118                 .append(ep.getMacAddress().getValue())
119                 .toString());
120         FlowBuilder flowb = base()
121                 .setPriority(priority)
122                 .setId(flowid)
123                 .setMatch(new MatchBuilder()
124                         .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
125                                 null, null))
126                         .setInPort(ofc.getNodeConnectorId())
127                         .build())
128                 .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)));
129
130         return flowb.build();
131     }
132
133     private Flow l3DhcpDoraFlow(Endpoint ep, OfOverlayContext ofc, Integer priority) {
134
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();
140
141         FlowId flowid = new FlowId(new StringBuilder()
142                 .append(ofc.getNodeConnectorId().getValue())
143                 .append("|")
144                 .append(ep.getMacAddress().getValue())
145                 .append("|dhcp|")
146                 .append(etherType)
147                 .toString());
148         Flow flow = base()
149                 .setPriority(priority)
150                 .setId(flowid)
151                 .setMatch(new MatchBuilder()
152                         .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
153                                 null,
154                                 etherType))
155                         .setLayer3Match(m)
156                         .setInPort(ofc.getNodeConnectorId())
157                         .build())
158                 .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)))
159                 .build();
160
161         return flow;
162     }
163
164     private void l3flow(FlowMap flowMap, NodeId nodeId,
165                         Endpoint ep, OfOverlayContext ofc,
166                         Integer priority, boolean arp) {
167         if (ep.getL3Address() == null)
168             return;
169         for (L3Address l3 : ep.getL3Address()) {
170             if (l3.getIpAddress() == null)
171                 continue;
172             Layer3Match m = null;
173             Long etherType = null;
174             String ikey = null;
175             if (l3.getIpAddress().getIpv4Address() != null) {
176                 ikey = l3.getIpAddress().getIpv4Address().getValue() + "/32";
177                 if (arp) {
178                     m = new ArpMatchBuilder()
179                             .setArpSourceTransportAddress(new Ipv4Prefix(ikey))
180                             .build();
181                     etherType = FlowUtils.ARP;
182                 } else {
183                     m = new Ipv4MatchBuilder()
184                             .setIpv4Source(new Ipv4Prefix(ikey))
185                             .build();
186                     etherType = FlowUtils.IPv4;
187                 }
188             } else if (l3.getIpAddress().getIpv6Address() != null) {
189                 if (arp)
190                     continue;
191                 ikey = l3.getIpAddress().getIpv6Address().getValue() + "/128";
192                 m = new Ipv6MatchBuilder()
193                         .setIpv6Source(new Ipv6Prefix(ikey))
194                         .build();
195                 etherType = FlowUtils.IPv6;
196             } else {
197                 continue;
198             }
199             FlowId flowid = new FlowId(new StringBuilder()
200                     .append(ofc.getNodeConnectorId().getValue())
201                     .append("|")
202                     .append(ep.getMacAddress().getValue())
203                     .append("|")
204                     .append(ikey)
205                     .append("|")
206                     .append(etherType)
207                     .toString());
208             Flow flow = base()
209                     .setPriority(priority)
210                     .setId(flowid)
211                     .setMatch(new MatchBuilder()
212                             .setEthernetMatch(FlowUtils.ethernetMatch(ep.getMacAddress(),
213                                     null,
214                                     etherType))
215                             .setLayer3Match(m)
216                             .setInPort(ofc.getNodeConnectorId())
217                             .build())
218                     .setInstructions(FlowUtils.gotoTableInstructions((short) (TABLE_ID + 1)))
219                     .build();
220
221             flowMap.writeFlow(nodeId, TABLE_ID,flow);
222         }
223     }
224 }