83cb7e86a2e677fe85c1e817a08d0b27c5bfaebe
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.onosproject.segmentrouting;
18
19 import org.onlab.packet.Ethernet;
20 import org.onlab.packet.IpPrefix;
21 import org.onlab.packet.TpPort;
22 import org.onosproject.cli.net.IpProtocol;
23 import org.onosproject.core.ApplicationId;
24 import org.onosproject.net.DeviceId;
25 import org.onosproject.net.flow.DefaultTrafficSelector;
26 import org.onosproject.net.flow.TrafficSelector;
27 import org.onosproject.net.flowobjective.DefaultForwardingObjective;
28 import org.onosproject.net.flowobjective.FlowObjectiveService;
29 import org.onosproject.net.flowobjective.ForwardingObjective;
30 import org.onosproject.store.service.EventuallyConsistentMap;
31 import org.slf4j.Logger;
32
33 import java.util.List;
34 import java.util.stream.Collectors;
35
36 import static org.slf4j.LoggerFactory.getLogger;
37
38 /**
39  * Segment Routing Policy Handler.
40  */
41 public class PolicyHandler {
42
43     protected final Logger log = getLogger(getClass());
44
45     private ApplicationId appId;
46     private DeviceConfiguration deviceConfiguration;
47     private FlowObjectiveService flowObjectiveService;
48     private TunnelHandler tunnelHandler;
49     private final EventuallyConsistentMap<String, Policy> policyStore;
50
51     public enum Result {
52         SUCCESS,
53         POLICY_EXISTS,
54         ID_EXISTS,
55         TUNNEL_NOT_FOUND,
56         POLICY_NOT_FOUND,
57         UNSUPPORTED_TYPE
58     }
59
60     /**
61      * Creates a reference.
62      *
63      * @param appId                segment routing application ID
64      * @param deviceConfiguration  DeviceConfiguration reference
65      * @param flowObjectiveService FlowObjectiveService reference
66      * @param tunnelHandler        tunnel handler reference
67      * @param policyStore          policy store
68      */
69     public PolicyHandler(ApplicationId appId,
70                          DeviceConfiguration deviceConfiguration,
71                          FlowObjectiveService flowObjectiveService,
72                          TunnelHandler tunnelHandler,
73                          EventuallyConsistentMap<String, Policy> policyStore) {
74         this.appId = appId;
75         this.deviceConfiguration = deviceConfiguration;
76         this.flowObjectiveService = flowObjectiveService;
77         this.tunnelHandler = tunnelHandler;
78         this.policyStore = policyStore;
79     }
80
81     /**
82      * Returns the policies.
83      *
84      * @return policy list
85      */
86     public List<Policy> getPolicies() {
87         return policyStore.values()
88                 .stream()
89                 .filter(policy -> policy instanceof TunnelPolicy)
90                 .map(policy -> new TunnelPolicy((TunnelPolicy) policy))
91                 .collect(Collectors.toList());
92     }
93
94     /**
95      * Creates a policy using the policy information given.
96      *  @param policy policy reference to create
97      *  @return ID_EXISTS if the same policy ID exists,
98      *  POLICY_EXISTS if the same policy exists, TUNNEL_NOT_FOUND if the tunnel
99      *  does not exists, UNSUPPORTED_TYPE if the policy type is not supported,
100      *  SUCCESS if the policy is created successfully
101      */
102     public Result createPolicy(Policy policy) {
103
104         if (policyStore.containsKey(policy.id())) {
105             log.warn("The policy id {} exists already", policy.id());
106             return Result.ID_EXISTS;
107         }
108
109         if (policyStore.containsValue(policy)) {
110             log.warn("The same policy exists already");
111             return Result.POLICY_EXISTS;
112         }
113
114         if (policy.type() == Policy.Type.TUNNEL_FLOW) {
115
116             TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
117             Tunnel tunnel = tunnelHandler.getTunnel(tunnelPolicy.tunnelId());
118             if (tunnel == null) {
119                 return Result.TUNNEL_NOT_FOUND;
120             }
121
122             ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
123                     .builder()
124                     .fromApp(appId)
125                     .makePermanent()
126                     .nextStep(tunnel.groupId())
127                     .withPriority(tunnelPolicy.priority())
128                     .withSelector(buildSelector(policy))
129                     .withFlag(ForwardingObjective.Flag.VERSATILE);
130
131             DeviceId source = deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
132             flowObjectiveService.forward(source, fwdBuilder.add());
133
134         } else {
135             log.warn("Policy type {} is not supported yet.", policy.type());
136             return Result.UNSUPPORTED_TYPE;
137         }
138
139         policyStore.put(policy.id(), policy);
140
141         return Result.SUCCESS;
142     }
143
144     /**
145      * Removes the policy given.
146      *
147      * @param policyInfo policy information to remove
148      * @return POLICY_NOT_FOUND if the policy to remove does not exists,
149      * SUCCESS if it is removed successfully
150      */
151     public Result removePolicy(Policy policyInfo) {
152
153         if (policyStore.get(policyInfo.id()) != null) {
154             Policy policy = policyStore.get(policyInfo.id());
155             if (policy.type() == Policy.Type.TUNNEL_FLOW) {
156                 TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
157                 Tunnel tunnel = tunnelHandler.getTunnel(tunnelPolicy.tunnelId());
158
159                 ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
160                         .builder()
161                         .fromApp(appId)
162                         .makePermanent()
163                         .withSelector(buildSelector(policy))
164                         .withPriority(tunnelPolicy.priority())
165                         .nextStep(tunnel.groupId())
166                         .withFlag(ForwardingObjective.Flag.VERSATILE);
167
168                 DeviceId source = deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
169                 flowObjectiveService.forward(source, fwdBuilder.remove());
170
171                 policyStore.remove(policyInfo.id());
172             }
173         } else {
174             log.warn("Policy {} was not found", policyInfo.id());
175             return Result.POLICY_NOT_FOUND;
176         }
177
178         return Result.SUCCESS;
179     }
180
181
182     private TrafficSelector buildSelector(Policy policy) {
183
184         TrafficSelector.Builder tsb = DefaultTrafficSelector.builder();
185         tsb.matchEthType(Ethernet.TYPE_IPV4);
186         if (policy.dstIp() != null && !policy.dstIp().isEmpty()) {
187             tsb.matchIPDst(IpPrefix.valueOf(policy.dstIp()));
188         }
189         if (policy.srcIp() != null && !policy.srcIp().isEmpty()) {
190             tsb.matchIPSrc(IpPrefix.valueOf(policy.srcIp()));
191         }
192         if (policy.ipProto() != null && !policy.ipProto().isEmpty()) {
193             Short ipProto = IpProtocol.valueOf(policy.ipProto()).value();
194             tsb.matchIPProtocol(ipProto.byteValue());
195             if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.TCP)) {
196                 if (policy.srcPort() != 0) {
197                     tsb.matchTcpSrc(TpPort.tpPort(policy.srcPort()));
198                 }
199                 if (policy.dstPort() != 0) {
200                     tsb.matchTcpDst(TpPort.tpPort(policy.dstPort()));
201                 }
202             } else if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.UDP)) {
203                 if (policy.srcPort() != 0) {
204                     tsb.matchUdpSrc(TpPort.tpPort(policy.srcPort()));
205                 }
206                 if (policy.dstPort() != 0) {
207                     tsb.matchUdpDst(TpPort.tpPort(policy.dstPort()));
208                 }
209             }
210         }
211
212         return tsb.build();
213     }
214
215 }