9d2e06f52297999f148d56f68a17ef897cc2d918
[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 package org.onosproject.net.newresource.impl;
17
18 import com.google.common.collect.Lists;
19 import org.onlab.packet.MplsLabel;
20 import org.onlab.packet.VlanId;
21 import org.onlab.util.ItemNotFoundException;
22 import org.onosproject.net.ConnectPoint;
23 import org.onosproject.net.Link;
24 import org.onosproject.net.LinkKey;
25 import org.onosproject.net.behaviour.MplsQuery;
26 import org.onosproject.net.behaviour.VlanQuery;
27 import org.onosproject.net.driver.DriverHandler;
28 import org.onosproject.net.driver.DriverService;
29 import org.onosproject.net.link.LinkEvent;
30 import org.onosproject.net.link.LinkListener;
31 import org.onosproject.net.newresource.ResourceAdminService;
32 import org.onosproject.net.newresource.ResourcePath;
33
34 import java.util.List;
35 import java.util.concurrent.ExecutorService;
36 import java.util.function.Predicate;
37 import java.util.stream.Collectors;
38 import java.util.stream.IntStream;
39
40 import static com.google.common.base.Preconditions.checkNotNull;
41
42 /**
43  * An implementation of LinkListener registering links as resources.
44  */
45 final class ResourceLinkListener implements LinkListener {
46
47     private static final int TOTAL_VLANS = 1024;
48     private static final List<VlanId> ENTIRE_VLAN_IDS = getEntireVlans();
49
50     private static final int TOTAL_MPLS_LABELS = 1048576;
51     private static final List<MplsLabel> ENTIRE_MPLS_LABELS = getEntireMplsLabels();
52
53     private final ResourceAdminService adminService;
54     private final DriverService driverService;
55     private final ExecutorService executor;
56
57     /**
58      * Creates an instance with the specified ResourceAdminService and ExecutorService.
59      *
60      * @param adminService instance invoked to register resources
61      * @param driverService driver service instance
62      * @param executor executor used for processing resource registration
63      */
64     ResourceLinkListener(ResourceAdminService adminService, DriverService driverService, ExecutorService executor) {
65         this.adminService = checkNotNull(adminService);
66         this.driverService = checkNotNull(driverService);
67         this.executor = checkNotNull(executor);
68     }
69
70     @Override
71     public void event(LinkEvent event) {
72         Link link = event.subject();
73         switch (event.type()) {
74             case LINK_ADDED:
75                 registerLinkResource(link);
76                 break;
77             case LINK_REMOVED:
78                 unregisterLinkResource(link);
79                 break;
80             default:
81                 break;
82         }
83     }
84
85     private void registerLinkResource(Link link) {
86         executor.submit(() -> {
87             // register the link
88             LinkKey linkKey = LinkKey.linkKey(link);
89             adminService.registerResources(ResourcePath.discrete(linkKey));
90
91             ResourcePath linkPath = ResourcePath.discrete(linkKey);
92             // register VLAN IDs against the link
93             if (isEnabled(link, this::isVlanEnabled)) {
94                 adminService.registerResources(Lists.transform(ENTIRE_VLAN_IDS, linkPath::child));
95             }
96
97             // register MPLS labels against the link
98             if (isEnabled(link, this::isMplsEnabled)) {
99                 adminService.registerResources(Lists.transform(ENTIRE_MPLS_LABELS, linkPath::child));
100             }
101         });
102     }
103
104     private void unregisterLinkResource(Link link) {
105         LinkKey linkKey = LinkKey.linkKey(link);
106         executor.submit(() -> adminService.unregisterResources(ResourcePath.discrete(linkKey)));
107     }
108
109     private boolean isEnabled(Link link, Predicate<ConnectPoint> predicate) {
110         return predicate.test(link.src()) && predicate.test(link.dst());
111     }
112
113     private boolean isVlanEnabled(ConnectPoint cp) {
114         try {
115             DriverHandler handler = driverService.createHandler(cp.deviceId());
116             if (handler == null) {
117                 return false;
118             }
119
120             VlanQuery query = handler.behaviour(VlanQuery.class);
121             return query != null && query.isEnabled(cp.port());
122         } catch (ItemNotFoundException e) {
123             return false;
124         }
125     }
126
127     private boolean isMplsEnabled(ConnectPoint cp) {
128         try {
129             DriverHandler handler = driverService.createHandler(cp.deviceId());
130             if (handler == null) {
131                 return false;
132             }
133
134             MplsQuery query = handler.behaviour(MplsQuery.class);
135             return query != null && query.isEnabled(cp.port());
136         } catch (ItemNotFoundException e) {
137             return false;
138         }
139     }
140
141     private static List<VlanId> getEntireVlans() {
142         return IntStream.range(0, TOTAL_VLANS)
143                 .mapToObj(x -> VlanId.vlanId((short) x))
144                 .collect(Collectors.toList());
145     }
146
147     private static List<MplsLabel> getEntireMplsLabels() {
148         // potentially many objects are created
149         return IntStream.range(0, TOTAL_MPLS_LABELS)
150                 .mapToObj(MplsLabel::mplsLabel)
151                 .collect(Collectors.toList());
152     }
153 }