aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java
blob: 91f2679cdfd02e1236d36b4b82a272d4f2eb535d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.driver.pipeline;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupKey;

/**
 * Spring-open driver implementation for Dell hardware switches.
 */
public class SpringOpenTTPDell extends SpringOpenTTP {

    /* Table IDs to be used for Dell Open Segment Routers*/
    private static final int DELL_TABLE_VLAN = 17;
    private static final int DELL_TABLE_TMAC = 18;
    private static final int DELL_TABLE_IPV4_UNICAST = 30;
    private static final int DELL_TABLE_MPLS = 25;
    private static final int DELL_TABLE_ACL = 40;

    //TODO: Store this info in the distributed store.
    private MacAddress deviceTMac = null;

    public SpringOpenTTPDell() {
        super();
        vlanTableId = DELL_TABLE_VLAN;
        tmacTableId = DELL_TABLE_TMAC;
        ipv4UnicastTableId = DELL_TABLE_IPV4_UNICAST;
        mplsTableId = DELL_TABLE_MPLS;
        aclTableId = DELL_TABLE_ACL;
    }

    @Override
    protected void setTableMissEntries() {
        // No need to set table-miss-entries in Dell switches
        return;
    }

    @Override
    //Dell switches need ETH_DST based match condition in all IP table entries.
    //So this method overrides the default spring-open behavior and adds
    //ETH_DST match condition while pushing IP table flow rules
    protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
        log.debug("Processing specific");
        TrafficSelector selector = fwd.selector();
        EthTypeCriterion ethType = (EthTypeCriterion) selector
                .getCriterion(Criterion.Type.ETH_TYPE);
        if ((ethType == null) ||
                (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
                (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
            log.debug("processSpecific: Unsupported "
                    + "forwarding objective criteraia");
            fail(fwd, ObjectiveError.UNSUPPORTED);
            return Collections.emptySet();
        }

        TrafficSelector.Builder filteredSelectorBuilder =
                DefaultTrafficSelector.builder();
        int forTableId = -1;
        if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
            if (deviceTMac == null) {
                log.debug("processSpecific: ETH_DST filtering "
                        + "objective is not set which is required "
                        + "before sending a IPv4 forwarding objective");
                //TODO: Map the error to more appropriate error code.
                fail(fwd, ObjectiveError.DEVICEMISSING);
                return Collections.emptySet();
            }
            filteredSelectorBuilder = filteredSelectorBuilder
                .matchEthType(Ethernet.TYPE_IPV4)
                .matchEthDst(deviceTMac)
                .matchIPDst(((IPCriterion) selector
                        .getCriterion(Criterion.Type.IPV4_DST))
                        .ip());
            forTableId = ipv4UnicastTableId;
            log.debug("processing IPv4 specific forwarding objective");
        } else {
            filteredSelectorBuilder = filteredSelectorBuilder
                .matchEthType(Ethernet.MPLS_UNICAST)
                .matchMplsLabel(((MplsCriterion)
                   selector.getCriterion(Criterion.Type.MPLS_LABEL)).label());
            //TODO: Add Match for BoS
            //if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) {
            //}
            forTableId = mplsTableId;
            log.debug("processing MPLS specific forwarding objective");
        }

        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment
                .builder();
        if (fwd.treatment() != null) {
            for (Instruction i : fwd.treatment().allInstructions()) {
                treatmentBuilder.add(i);
            }
        }

        if (fwd.nextId() != null) {
            NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());

            if (next != null) {
                GroupKey key = appKryo.deserialize(next.data());

                Group group = groupService.getGroup(deviceId, key);

                if (group == null) {
                    log.warn("The group left!");
                    fail(fwd, ObjectiveError.GROUPMISSING);
                    return Collections.emptySet();
                }
                treatmentBuilder.group(group.id());
                log.debug("Adding OUTGROUP action");
            } else {
                log.warn("processSpecific: No associated next objective object");
                fail(fwd, ObjectiveError.GROUPMISSING);
                return Collections.emptySet();
            }
        }

        TrafficSelector filteredSelector = filteredSelectorBuilder.build();
        TrafficTreatment treatment = treatmentBuilder.transition(aclTableId)
                .build();

        FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
                .fromApp(fwd.appId()).withPriority(fwd.priority())
                .forDevice(deviceId).withSelector(filteredSelector)
                .withTreatment(treatment);

        if (fwd.permanent()) {
            ruleBuilder.makePermanent();
        } else {
            ruleBuilder.makeTemporary(fwd.timeout());
        }

        ruleBuilder.forTable(forTableId);
        return Collections.singletonList(ruleBuilder.build());

    }

    @Override
    //Dell switches need ETH_DST based match condition in all IP table entries.
    //So while processing the ETH_DST based filtering objective, store
    //the device MAC to be used locally to use it while pushing the IP rules.
    protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion,
                                                 VlanIdCriterion vlanIdCriterion,
                                                 FilteringObjective filt,
                                                 VlanId assignedVlan,
                                                 ApplicationId applicationId) {
        // Store device termination Mac to be used in IP flow entries
        deviceTMac = ethCriterion.mac();

        log.debug("For now not adding any TMAC rules "
                + "into Dell switches as it is ignoring");

        return Collections.emptyList();
    }

    @Override
    protected List<FlowRule> processVlanIdFilter(VlanIdCriterion vlanIdCriterion,
                                                 FilteringObjective filt,
                                                 VlanId assignedVlan,
                                                 ApplicationId applicationId) {
        log.debug("For now not adding any VLAN rules "
                + "into Dell switches as it is ignoring");

        return Collections.emptyList();
    }
}