blob: a8515e54d000488ee3b7b8794d9c11037c14fa43 [file] [log] [blame]
Yi Tseng0b809722017-11-03 10:23:26 -07001/*
2 * Copyright 2017-present Open Networking Foundation
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
17package org.onosproject.pipelines.fabric.pipeliner;
18
Yi Tseng27b9bc02018-04-12 14:52:40 +080019import com.google.common.collect.Lists;
Yi Tseng0b809722017-11-03 10:23:26 -070020import org.onlab.packet.Ethernet;
21import org.onlab.packet.MacAddress;
22import org.onlab.packet.VlanId;
23import org.onlab.util.ImmutableByteSequence;
24import org.onosproject.net.DeviceId;
25import org.onosproject.net.PortNumber;
26import org.onosproject.net.flow.DefaultFlowRule;
27import org.onosproject.net.flow.DefaultTrafficSelector;
28import org.onosproject.net.flow.DefaultTrafficTreatment;
29import org.onosproject.net.flow.FlowRule;
30import org.onosproject.net.flow.TrafficSelector;
31import org.onosproject.net.flow.TrafficTreatment;
32import org.onosproject.net.flow.criteria.Criterion;
33import org.onosproject.net.flow.criteria.EthCriterion;
34import org.onosproject.net.flow.criteria.PiCriterion;
35import org.onosproject.net.flow.criteria.PortCriterion;
36import org.onosproject.net.flow.criteria.VlanIdCriterion;
37import org.onosproject.net.flowobjective.FilteringObjective;
38import org.onosproject.net.flowobjective.ObjectiveError;
39import org.onosproject.net.pi.runtime.PiAction;
40import org.onosproject.net.pi.runtime.PiActionParam;
41import org.onosproject.pipelines.fabric.FabricConstants;
42import org.slf4j.Logger;
43
44import java.util.Collection;
45
46import static org.slf4j.LoggerFactory.getLogger;
47
48/**
49 * Handling filtering objective for fabric pipeliner.
50 */
51public class FabricFilteringPipeliner {
52 private static final Logger log = getLogger(FabricFilteringPipeliner.class);
53 // Forwarding types
54 private static final byte FWD_BRIDGING = 0;
55 private static final byte FWD_MPLS = 1;
56 private static final byte FWD_IPV4_UNICAST = 2;
57 private static final byte FWD_IPV4_MULTICAST = 3;
58 private static final byte FWD_IPV6_UNICAST = 4;
59 private static final byte FWD_IPV6_MULTICAST = 5;
60 private static final PiCriterion VLAN_VALID = PiCriterion.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +080061 .matchExact(FabricConstants.HDR_VLAN_TAG_IS_VALID, new byte[]{1})
Yi Tseng0b809722017-11-03 10:23:26 -070062 .build();
63 private static final PiCriterion VLAN_INVALID = PiCriterion.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +080064 .matchExact(FabricConstants.HDR_VLAN_TAG_IS_VALID, new byte[]{0})
Yi Tseng0b809722017-11-03 10:23:26 -070065 .build();
66
67 protected DeviceId deviceId;
68
69 public FabricFilteringPipeliner(DeviceId deviceId) {
70 this.deviceId = deviceId;
71 }
72
73 /**
74 * Translates filtering objective to flows and groups.
75 *
76 * @param filterObjective the filtering objective
77 * @return translation result, contains flows, groups or error it generated
78 */
79 public PipelinerTranslationResult filter(FilteringObjective filterObjective) {
80 PipelinerTranslationResult.Builder resultBuilder = PipelinerTranslationResult.builder();
81 // maps selector and treatment from filtering objective to filtering
82 // control block.
83
84 if (filterObjective.type() == FilteringObjective.Type.DENY) {
85 log.warn("Unsupported filtering objective type {}", filterObjective.type());
86 resultBuilder.setError(ObjectiveError.UNSUPPORTED);
87 return resultBuilder.build();
88 }
89
90 if (filterObjective.key() == null ||
91 filterObjective.key().type() != Criterion.Type.IN_PORT) {
92 log.warn("Unsupported filter key {}", filterObjective.key());
93 resultBuilder.setError(ObjectiveError.BADPARAMS);
94 return resultBuilder.build();
95 }
96 PortCriterion inPortCriterion = (PortCriterion) filterObjective.key();
97 VlanIdCriterion vlanCriterion = filterObjective.conditions().stream()
98 .filter(criterion -> criterion.type() == Criterion.Type.VLAN_VID)
99 .map(criterion -> (VlanIdCriterion) criterion)
100 .findFirst()
101 .orElse(null);
102 EthCriterion ethDstCriterion = filterObjective.conditions().stream()
103 .filter(criterion -> criterion.type() == Criterion.Type.ETH_DST)
104 .map(criterion -> (EthCriterion) criterion)
105 .findFirst()
106 .orElse(null);
107
108 FlowRule inPortVlanTableRule = createInPortVlanTable(inPortCriterion, vlanCriterion,
109 filterObjective);
110 Collection<FlowRule> fwdClassifierRules = createFwdClassifierRules(inPortCriterion, ethDstCriterion,
111 filterObjective);
112
113 resultBuilder.addFlowRule(inPortVlanTableRule);
114 fwdClassifierRules.forEach(resultBuilder::addFlowRule);
115 return resultBuilder.build();
116 }
117
118 private FlowRule createInPortVlanTable(Criterion inPortCriterion,
119 VlanIdCriterion vlanCriterion,
120 FilteringObjective filterObjective) {
121 Criterion vlanIsVlalidCriterion;
122 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
123 .add(inPortCriterion);
124
125 VlanId vlanId = null;
126 if (vlanCriterion != null) {
127 vlanId = vlanCriterion.vlanId();
128 }
129
130 vlanIsVlalidCriterion = VLAN_VALID;
131 if (vlanId == null || vlanId.equals(VlanId.NONE)) {
132 // untag vlan, match in port only
133 vlanIsVlalidCriterion = VLAN_INVALID;
134 }
135
136 selector.add(vlanIsVlalidCriterion);
137
138 // TODO: check if this treatment is valid or not
139 TrafficTreatment treatment = filterObjective.meta();
140 if (treatment == null) {
141 treatment = DefaultTrafficTreatment.emptyTreatment();
142 }
143
144 return DefaultFlowRule.builder()
145 .fromApp(filterObjective.appId())
146 .withPriority(filterObjective.priority())
147 .withSelector(selector.build())
148 .withTreatment(treatment)
149 .withPriority(filterObjective.priority())
Yi Tseng43ee7e82018-04-12 16:37:34 +0800150 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)
Yi Tseng0b809722017-11-03 10:23:26 -0700151 .forDevice(deviceId)
152 .makePermanent()
153 .build();
154 }
155
156 private Collection<FlowRule> createFwdClassifierRules(PortCriterion inPortCriterion,
157 EthCriterion ethDstCriterion,
158 FilteringObjective filterObjective) {
Yi Tseng27b9bc02018-04-12 14:52:40 +0800159 Collection<FlowRule> flowRules = Lists.newArrayList();
Yi Tseng0b809722017-11-03 10:23:26 -0700160 if (ethDstCriterion == null) {
161 // Bridging table, do nothing
162 return flowRules;
163 }
164 PortNumber port = inPortCriterion.port();
165 MacAddress dstMac = ethDstCriterion.mac();
166 if (dstMac.isMulticast()) {
167 flowRules.add(createMulticastFwdClassifierRule(port, dstMac, filterObjective));
168 return flowRules;
169 }
170
171 flowRules.addAll(createIpFwdClassifierRules(port, dstMac, filterObjective));
172 flowRules.add(createMplsFwdClassifierRule(port, dstMac, filterObjective));
173 return flowRules;
174 }
175
176 private FlowRule createMulticastFwdClassifierRule(PortNumber inPort, MacAddress dstMac,
177 FilteringObjective filterObjective) {
178 TrafficTreatment treatment;
179 short ethType;
180 if (dstMac.equals(MacAddress.IPV4_MULTICAST)) {
181 // Ipv4 multicast
182 treatment = createFwdClassifierTreatment(FWD_IPV4_MULTICAST);
183 ethType = Ethernet.TYPE_IPV4;
184 } else {
185 // IPv6 multicast
186 treatment = createFwdClassifierTreatment(FWD_IPV6_MULTICAST);
187 ethType = Ethernet.TYPE_IPV6;
188 }
189 return createFwdClassifierRule(inPort, ethType, dstMac, treatment, filterObjective);
190 }
191
192 private Collection<FlowRule> createIpFwdClassifierRules(PortNumber inPort,
193 MacAddress dstMac,
194 FilteringObjective filterObjective) {
Yi Tseng27b9bc02018-04-12 14:52:40 +0800195 Collection<FlowRule> flowRules = Lists.newArrayList();
Yi Tseng0b809722017-11-03 10:23:26 -0700196 TrafficTreatment treatment;
197 treatment = createFwdClassifierTreatment(FWD_IPV4_UNICAST);
198 flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV4, dstMac, treatment, filterObjective));
199 treatment = createFwdClassifierTreatment(FWD_IPV6_UNICAST);
200 flowRules.add(createFwdClassifierRule(inPort, Ethernet.TYPE_IPV6, dstMac, treatment, filterObjective));
201 return flowRules;
202 }
203
204 private FlowRule createMplsFwdClassifierRule(PortNumber inPort,
205 MacAddress dstMac,
206 FilteringObjective filterObjective) {
207 TrafficTreatment treatment = createFwdClassifierTreatment(FWD_MPLS);
208 return createFwdClassifierRule(inPort, Ethernet.MPLS_UNICAST, dstMac, treatment, filterObjective);
209 }
210
211 private FlowRule createFwdClassifierRule(PortNumber inPort,
212 short ethType,
213 MacAddress dstMac,
214 TrafficTreatment treatment,
215 FilteringObjective filterObjective) {
216 TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
217 .matchInPort(inPort)
218 .matchEthDst(dstMac)
219 .matchEthType(ethType);
220
221 return DefaultFlowRule.builder()
222 .withSelector(selector.build())
223 .withTreatment(treatment)
224 .fromApp(filterObjective.appId())
225 .withPriority(filterObjective.priority())
226 .forDevice(deviceId)
227 .makePermanent()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800228 .forTable(FabricConstants.FABRIC_INGRESS_FILTERING_FWD_CLASSIFIER)
Yi Tseng0b809722017-11-03 10:23:26 -0700229 .build();
230 }
231
232 private TrafficTreatment createFwdClassifierTreatment(byte fwdType) {
Yi Tseng43ee7e82018-04-12 16:37:34 +0800233 PiActionParam param = new PiActionParam(FabricConstants.FWD_TYPE,
Yi Tseng0b809722017-11-03 10:23:26 -0700234 ImmutableByteSequence.copyFrom(fwdType));
235 PiAction action = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800236 .withId(FabricConstants.FABRIC_INGRESS_FILTERING_SET_FORWARDING_TYPE)
Yi Tseng0b809722017-11-03 10:23:26 -0700237 .withParameter(param)
238 .build();
239 return DefaultTrafficTreatment.builder()
240 .piTableAction(action)
241 .build();
242
243 }
244}