aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
blob: 33496bd74a70514cfb5dfa692c2af0254959fadd (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
/*
 * 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.List;
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.DeviceProperties;
import org.onosproject.store.service.EventuallyConsistentMap;

/**
 * Default ECMP group handler creation module for an edge 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 device D0 is connected to 2 neighbors (D1 and D2 ).
 * The following groups will be created in D0:
 * 1) all ports to D1 + with no label push, // direct attach case, seen
 * 2) all ports to D1 + with label 102 pushed, // this is not needed
 * 3) all ports to D1 + with label 103 pushed, // maybe needed, sometimes seen
 * 4) all ports to D2 + with no label push,
 * 5) all ports to D2 + with label 101 pushed,
 * 6) all ports to D2 + with label 103 pushed,
 * 7) all ports to D1 and D2 + with label 103 pushed // ecmp case
 * 8) what about ecmp no label case
 */
public class DefaultEdgeGroupHandler extends DefaultGroupHandler {

    protected DefaultEdgeGroupHandler(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() {
        log.debug("Creating default groups "
                + "for edge device {}", deviceId);
        Set<DeviceId> neighbors = devicePortMap.keySet();
        if (neighbors == null || neighbors.isEmpty()) {
            return;
        }

        // Create all possible Neighbor sets from this router
        Set<Set<DeviceId>> powerSet = getPowerSetOfNeighbors(neighbors);
        log.trace("createGroupsAtEdgeRouter: The size of neighbor powerset "
                + "for sw {} is {}", deviceId, powerSet.size());
        Set<NeighborSet> nsSet = new HashSet<>();
        for (Set<DeviceId> combo : powerSet) {
            if (combo.isEmpty()) {
                continue;
            }
            List<Integer> groupSegmentIds =
                    getSegmentIdsTobePairedWithNeighborSet(combo);
            for (Integer sId : groupSegmentIds) {
                NeighborSet ns = new NeighborSet(combo, sId);
                log.trace("createGroupsAtEdgeRouter: sw {} "
                        + "combo {} sId {} ns {}",
                        deviceId, combo, sId, ns);
                nsSet.add(ns);
            }
        }
        log.trace("createGroupsAtEdgeRouter: The neighborset "
                + "with label for sw {} is {}",
                deviceId, nsSet);

        createGroupsFromNeighborsets(nsSet);
    }

    @Override
    protected void newNeighbor(Link newNeighborLink) {
        log.debug("New Neighbor: Updating groups "
                + "for edge 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 edge 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);

        Set<NeighborSet> nsSet = new HashSet<>();
        for (Set<DeviceId> combo : powerSet) {
            if (combo.isEmpty()) {
                continue;
            }
            List<Integer> groupSegmentIds =
                    getSegmentIdsTobePairedWithNeighborSet(combo);
            for (Integer sId : groupSegmentIds) {
                NeighborSet ns = new NeighborSet(combo, sId);
                log.trace("computeImpactedNeighborsetForPortEvent: sw {} "
                        + "combo {} sId {} ns {}",
                        deviceId, combo, sId, ns);
                nsSet.add(ns);
            }
        }
        log.trace("computeImpactedNeighborsetForPortEvent: The neighborset "
                + "with label for sw {} is {}",
                deviceId, nsSet);
        return nsSet;
    }

}