aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
blob: 8e1b6a8fbaa5e52ea340fd17963403e51222ed00 (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
/*
 * 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.segmentrouting.grouphandler;

import java.util.HashSet;
import java.util.Set;

import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.link.LinkService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceProperties;
import org.onosproject.store.service.EventuallyConsistentMap;

/**
 * Default ECMP group handler creation module for a transit device.
 * This component creates a set of ECMP groups for every neighbor
 * that this device is connected to.
 * For example, consider a network of 4 devices: D0 (Segment ID: 100),
 * D1 (Segment ID: 101), D2 (Segment ID: 102) and D3 (Segment ID: 103),
 * where D0 and D3 are edge devices and D1 and D2 are transit devices.
 * Assume transit device D1 is connected to 2 neighbors (D0 and D3 ).
 * The following groups will be created in D1:
 * 1) all ports to D0 + with no label push,
 * 2) all ports to D3 + with no label push,
 */
public class DefaultTransitGroupHandler extends DefaultGroupHandler {

    protected DefaultTransitGroupHandler(DeviceId deviceId,
                                  ApplicationId appId,
                                  DeviceProperties config,
                                  LinkService linkService,
                                  FlowObjectiveService flowObjService,
                                  EventuallyConsistentMap<
                                        NeighborSetNextObjectiveStoreKey,
                                        Integer> nsNextObjStore,
                                  EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
                                        Integer> subnetNextObjStore) {
        super(deviceId, appId, config, linkService, flowObjService,
              nsNextObjStore, subnetNextObjStore);
    }

    @Override
    public void createGroups() {
        Set<DeviceId> neighbors = devicePortMap.keySet();
        if (neighbors == null || neighbors.isEmpty()) {
            return;
        }

        // Create all possible Neighbor sets from this router
        // NOTE: Avoid any pairings of edge routers only
        Set<Set<DeviceId>> sets = getPowerSetOfNeighbors(neighbors);
        sets = filterEdgeRouterOnlyPairings(sets);
        log.debug("createGroupsAtTransitRouter: The size of neighbor powerset "
                + "for sw {} is {}", deviceId, sets.size());
        Set<NeighborSet> nsSet = new HashSet<>();
        for (Set<DeviceId> combo : sets) {
            if (combo.isEmpty()) {
                continue;
            }
            NeighborSet ns = new NeighborSet(combo);
            log.debug("createGroupsAtTransitRouter: sw {} combo {} ns {}",
                      deviceId, combo, ns);
            nsSet.add(ns);
        }
        log.debug("createGroupsAtTransitRouter: The neighborset with label "
                + "for sw {} is {}", deviceId, nsSet);

        createGroupsFromNeighborsets(nsSet);
    }

    @Override
    protected void newNeighbor(Link newNeighborLink) {
        log.debug("New Neighbor: Updating groups for "
                + "transit device {}", deviceId);
        // Recompute neighbor power set
        addNeighborAtPort(newNeighborLink.dst().deviceId(),
                          newNeighborLink.src().port());
        // Compute new neighbor sets due to the addition of new neighbor
        Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
                                             newNeighborLink.dst().deviceId(),
                                             devicePortMap.keySet());
        createGroupsFromNeighborsets(nsSet);
    }

    @Override
    protected void newPortToExistingNeighbor(Link newNeighborLink) {
        /*log.debug("New port to existing neighbor: Updating "
                + "groups for transit device {}", deviceId);
        addNeighborAtPort(newNeighborLink.dst().deviceId(),
                          newNeighborLink.src().port());
        Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
                                              newNeighborLink.dst().deviceId(),
                                              devicePortMap.keySet());
        for (NeighborSet ns : nsSet) {
            // Create the new bucket to be updated
            TrafficTreatment.Builder tBuilder =
                    DefaultTrafficTreatment.builder();
            tBuilder.setOutput(newNeighborLink.src().port())
                    .setEthDst(deviceConfig.getDeviceMac(
                          newNeighborLink.dst().deviceId()))
                    .setEthSrc(nodeMacAddr);
            if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
                tBuilder.pushMpls()
                        .setMpls(MplsLabel.
                                 mplsLabel(ns.getEdgeLabel()));
            }


            Integer nextId = deviceNextObjectiveIds.get(ns);
            if (nextId != null) {
                NextObjective.Builder nextObjBuilder = DefaultNextObjective
                        .builder().withId(nextId)
                        .withType(NextObjective.Type.HASHED).fromApp(appId);

                nextObjBuilder.addTreatment(tBuilder.build());

                NextObjective nextObjective = nextObjBuilder.add();
                flowObjectiveService.next(deviceId, nextObjective);
            }
        }*/
    }

    @Override
    protected Set<NeighborSet> computeImpactedNeighborsetForPortEvent(
                                            DeviceId impactedNeighbor,
                                            Set<DeviceId> updatedNeighbors) {
        Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(updatedNeighbors);

        Set<DeviceId> tmp = new HashSet<>();
        tmp.addAll(updatedNeighbors);
        tmp.remove(impactedNeighbor);
        Set<Set<DeviceId>> tmpPowerSet = getPowerSetOfNeighbors(tmp);

        // Compute the impacted neighbor sets
        powerSet.removeAll(tmpPowerSet);

        powerSet = filterEdgeRouterOnlyPairings(powerSet);
        Set<NeighborSet> nsSet = new HashSet<>();
        for (Set<DeviceId> combo : powerSet) {
            if (combo.isEmpty()) {
                continue;
            }
            NeighborSet ns = new NeighborSet(combo);
            log.debug("createGroupsAtTransitRouter: sw {} combo {} ns {}",
                      deviceId, combo, ns);
            nsSet.add(ns);
        }
        log.debug("computeImpactedNeighborsetForPortEvent: The neighborset with label "
                + "for sw {} is {}", deviceId, nsSet);

        return nsSet;
    }

    private Set<Set<DeviceId>> filterEdgeRouterOnlyPairings(Set<Set<DeviceId>> sets) {
        Set<Set<DeviceId>> fiteredSets = new HashSet<>();
        for (Set<DeviceId> deviceSubSet : sets) {
            if (deviceSubSet.size() > 1) {
                boolean avoidEdgeRouterPairing = true;
                for (DeviceId device : deviceSubSet) {
                    boolean isEdge;
                    try {
                        isEdge = deviceConfig.isEdgeDevice(device);
                    } catch (DeviceConfigNotFoundException e) {
                        log.warn(e.getMessage() + " Skipping filterEdgeRouterOnlyPairings on this device.");
                        continue;
                    }

                    if (!isEdge) {
                        avoidEdgeRouterPairing = false;
                        break;
                    }
                }
                if (!avoidEdgeRouterPairing) {
                    fiteredSets.add(deviceSubSet);
                }
            } else {
                fiteredSets.add(deviceSubSet);
            }
        }
        return fiteredSets;
    }
}