Bug 5617: OfOverlay Refactoring - Destination mapper
[groupbasedpolicy.git] / renderers / ofoverlay / src / main / java / org / opendaylight / groupbasedpolicy / renderer / ofoverlay / mapper / ingressnat / IngressNatMapper.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.mapper.ingressnat;
10
11 import com.google.common.collect.Sets;
12 import org.opendaylight.groupbasedpolicy.dto.EgKey;
13 import org.opendaylight.groupbasedpolicy.dto.EpKey;
14 import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
15 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
16 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
17 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable;
18 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTable;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg0;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg4;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.load.grouping.NxRegLoad;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.reg.move.grouping.NxRegMove;
34
35 import java.util.Collection;
36 import java.util.Collections;
37
38 /**
39  * <h1>Manage the table processing NAT translation (table=1)</h1>
40  *
41  * Ingress NAT translation flows, created for every L3 endpoints with NAT which also contain L2 context
42  * <p>
43  * <i>Nat flow:</i><br>
44  * Priority = 100<br>
45  * Matches:<br>
46  *      - nw_dst (destination ip address)<br>
47  * Actions:<br>
48  *      - loadReg0 {@link NxmNxReg0}<br>
49  *      - loadReg1 {@link NxmNxReg1}<br>
50  *      - loadReg4 {@link NxmNxReg4}<br>
51  *      - loadReg5 {@link NxmNxReg5}<br>
52  *      - loadReg6 {@link NxmNxReg6}<br>
53  *      - loadTunnelId<br>
54  *      - {@link GoToTable} DESTINATION MAPPER table
55  * <p>
56  * <i>Outside Arp flow:</i><br>
57  * Priority = 150<br>
58  * Matches:<br>
59  *      - arp, (ethertype)<br>
60  *      - set arp target transport address<br>
61  * Actions:<br>
62  *      - move eth_src = eth_dst {@link NxRegMove}<br>
63  *      - set dl src_mac {@link MacAddress}<br>
64  *      - load arp_op {@link NxRegLoad}<br>
65  *      - move arp_sha = arp_tha {@link NxRegMove}<br>
66  *      - load arp_sha {@link NxRegLoad}<br>
67  *      - move arp_spa = arp_tpa {@link NxRegMove}<br>
68  *      - load arp_spa {@link NxRegLoad}<br>
69  *      - output:port {@link NodeConnectorId}
70  * <p>
71  * Flows for ingress traffic. Created for every external endpoint without location<br>
72  * <p>
73  * <i>Ingress external IP flow</i><br>
74  * Priority = 90<br>
75  * Matches:<br>
76  *      - nw_src (source ip address)<br>
77  * Actions:<br>
78  *      - loadReg0 {@link NxmNxReg0}<br>
79  *      - loadReg1 {@link NxmNxReg1}<br>
80  *      - loadReg4 {@link NxmNxReg4}<br>
81  *      - loadReg5 {@link NxmNxReg5}<br>
82  *      - loadReg6 {@link NxmNxReg6}<br>
83  *      - loadTunnelId<br>
84  *      - {@link GoToTable} DESTINATION MAPPER table
85  * <p>
86  * <i>Ingress external Arp flow</i><br>
87  * Priority = 80<br>
88  * Matches:<br>
89  *      - arp_spa (source arp address)<br>
90  * Actions:<br>
91  *      - loadReg0 {@link NxmNxReg0}<br>
92  *      - loadReg1 {@link NxmNxReg1}<br>
93  *      - loadReg4 {@link NxmNxReg4}<br>
94  *      - loadReg5 {@link NxmNxReg5}<br>
95  *      - loadReg6 {@link NxmNxReg6}<br>
96  *      - loadTunnelId<br>
97  *      - {@link GoToTable} DESTINATION MAPPER table
98  *
99  */
100 public class IngressNatMapper extends FlowTable {
101
102     // Priorities
103     private static final Integer BASE = 1;
104     private static final Integer ARP_EXTERNAL = 80;
105     private static final Integer NAT_EXTERNAL = 90;
106     private static final Integer NAT = 100;
107     private static final Integer ARP = 150;
108     private final short tableId;
109
110     public IngressNatMapper(OfContext ctx, short tableId) {
111         super(ctx);
112         this.tableId = tableId;
113     }
114
115     @Override
116     public short getTableId() {
117         return tableId;
118     }
119
120     @Override
121     public void sync(Endpoint endpoint, OfWriter ofWriter) {
122         NodeId endpointNodeId = ctx.getEndpointManager().getEndpointNodeId(endpoint);
123         if (endpointNodeId == null) {
124             LOG.warn("Endpoint {} has no location specified, skipped", endpoint);
125             return;
126         }
127         IngressNatMapperFlows flows = new IngressNatMapperFlows(endpointNodeId, tableId);
128         syncFlows(flows, endpoint, ofWriter);
129     }
130
131     void syncFlows(IngressNatMapperFlows flows, Endpoint endpoint, OfWriter ofWriter) {
132
133         // To support provider networks, all external ingress traffic is currently passed here and
134         // if no match is found - no NAT is performed and processing continues in DestinationMapper.
135
136         // Base flow
137         short destinationMapperId = ctx.getPolicyManager().getTABLEID_DESTINATION_MAPPER();
138         flows.baseFlow(destinationMapperId, BASE, ofWriter);
139
140         // Flows for ingress NAT translation
141         Collection<EndpointL3> l3Endpoints = ctx.getEndpointManager().getL3EndpointsWithNat();
142         OrdinalFactory.EndpointFwdCtxOrdinals epFwdCtxOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
143         EndpointKey endpointKey = endpoint.getKey();
144         for (EndpointL3 l3Endpoint : l3Endpoints) {
145             L2BridgeDomainId l2Context = l3Endpoint.getL2Context();
146             MacAddress macAddress = l3Endpoint.getMacAddress();
147             if (l2Context != null && macAddress != null) {
148                 Endpoint l2EpFromL3Ep = ctx.getEndpointManager().getEndpoint(new EpKey(l2Context, macAddress));
149                 if(endpointKey.equals(l2EpFromL3Ep.getKey())) {
150                     if (epFwdCtxOrdinals != null) {
151                         flows.createNatFlow(destinationMapperId, l3Endpoint, epFwdCtxOrdinals, NAT, ofWriter);
152                     }
153                     IndexedTenant tenant = ctx.getTenant(endpoint.getTenant());
154                     if (tenant != null) {
155                         flows.createArpFlow(tenant, l3Endpoint, ARP, ofWriter);
156                     }
157                     // L3 Endpoint found, end of loop
158                     break;
159                 }
160             }
161         }
162         // Flows for ingress traffic that does not have to be translated.
163         for (EgKey endpointGroupKey : ctx.getEndpointManager().getEgKeysForEndpoint(endpoint)) {
164             for (EgKey peer : Sets.union(Collections.singleton(endpointGroupKey),
165                     ctx.getCurrentPolicy().getPeers(endpointGroupKey))) {
166                 for (Endpoint externalEndpoint : ctx.getEndpointManager().getExtEpsNoLocForGroup(peer)) {
167                     if (epFwdCtxOrdinals != null) {
168                         flows.createIngressExternalNatFlows(destinationMapperId, externalEndpoint, epFwdCtxOrdinals,
169                                 NAT_EXTERNAL, ofWriter);
170                         flows.createIngressExternalArpFlows(destinationMapperId, externalEndpoint, epFwdCtxOrdinals,
171                                 ARP_EXTERNAL, ofWriter);
172                     }
173                 }
174             }
175         }
176     }
177 }