blob: fa96caf0c6e8fbffa9482f4479f3baa9b2e30f7b [file] [log] [blame]
Kent Hagerman3136fbd2020-05-14 10:30:45 -04001/*
2 * Copyright 2018-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 device
18
19import (
20 "context"
Kent Hagerman3136fbd2020-05-14 10:30:45 -040021 "fmt"
Kent Hagerman3136fbd2020-05-14 10:30:45 -040022 "github.com/opencord/voltha-go/rw_core/route"
23 "github.com/opencord/voltha-lib-go/v3/pkg/log"
24 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
25 "github.com/opencord/voltha-protos/v3/go/voltha"
Kent Hagerman3136fbd2020-05-14 10:30:45 -040026)
27
khenaidoo0db4c812020-05-27 15:27:30 -040028// GetRoute returns a route
Kent Hagerman3136fbd2020-05-14 10:30:45 -040029func (agent *LogicalAgent) GetRoute(ctx context.Context, ingressPortNo uint32, egressPortNo uint32) ([]route.Hop, error) {
30 logger.Debugw("getting-route", log.Fields{"ingress-port": ingressPortNo, "egress-port": egressPortNo})
31 routes := make([]route.Hop, 0)
32
33 // Note: A port value of 0 is equivalent to a nil port
34
khenaidoo0db4c812020-05-27 15:27:30 -040035 // Controller-bound flow
Kent Hagerman3136fbd2020-05-14 10:30:45 -040036 if egressPortNo != 0 && ((egressPortNo & 0x7fffffff) == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)) {
37 logger.Debugw("controller-flow", log.Fields{"ingressPortNo": ingressPortNo, "egressPortNo": egressPortNo, "logicalPortsNo": agent.logicalPortsNo})
38 if agent.isNNIPort(ingressPortNo) {
39 //This is a trap on the NNI Port
khenaidoo0db4c812020-05-27 15:27:30 -040040 if agent.deviceRoutes.IsRoutesEmpty() {
Kent Hagerman3136fbd2020-05-14 10:30:45 -040041 // If there are no routes set (usually when the logical device has only NNI port(s), then just return an
42 // route with same IngressHop and EgressHop
43 hop := route.Hop{DeviceID: agent.rootDeviceID, Ingress: ingressPortNo, Egress: ingressPortNo}
44 routes = append(routes, hop)
45 routes = append(routes, hop)
46 return routes, nil
47 }
khenaidoo0db4c812020-05-27 15:27:30 -040048
49 // Return a 'half' route to make the flow decomposer logic happy
50 routes, err := agent.deviceRoutes.GetHalfRoute(true, 0, 0)
51 if err != nil {
52 return nil, fmt.Errorf("no upstream route from:%d to:%d :%w", ingressPortNo, egressPortNo, route.ErrNoRoute)
Kent Hagerman3136fbd2020-05-14 10:30:45 -040053 }
khenaidoo0db4c812020-05-27 15:27:30 -040054 return routes, nil
Kent Hagerman3136fbd2020-05-14 10:30:45 -040055 }
khenaidoo0db4c812020-05-27 15:27:30 -040056 // Treat it as if the output port is the first NNI of the OLT
Kent Hagerman3136fbd2020-05-14 10:30:45 -040057 var err error
58 if egressPortNo, err = agent.getFirstNNIPort(); err != nil {
59 logger.Warnw("no-nni-port", log.Fields{"error": err})
60 return nil, err
61 }
62 }
khenaidoo0db4c812020-05-27 15:27:30 -040063
64 //If ingress port is not specified (nil), it may be a wildcarded route if egress port is OFPP_CONTROLLER or a nni
65 // logical port, in which case we need to create a half-route where only the egress hop is filled, the first hop is nil
Kent Hagerman3136fbd2020-05-14 10:30:45 -040066 if ingressPortNo == 0 && agent.isNNIPort(egressPortNo) {
khenaidoo0db4c812020-05-27 15:27:30 -040067 routes, err := agent.deviceRoutes.GetHalfRoute(true, ingressPortNo, egressPortNo)
68 if err != nil {
69 return nil, fmt.Errorf("no upstream route from:%d to:%d :%w", ingressPortNo, egressPortNo, route.ErrNoRoute)
Kent Hagerman3136fbd2020-05-14 10:30:45 -040070 }
khenaidoo0db4c812020-05-27 15:27:30 -040071 return routes, nil
Kent Hagerman3136fbd2020-05-14 10:30:45 -040072 }
khenaidoo0db4c812020-05-27 15:27:30 -040073
Kent Hagerman3136fbd2020-05-14 10:30:45 -040074 //If egress port is not specified (nil), we can also can return a "half" route
75 if egressPortNo == 0 {
khenaidoo0db4c812020-05-27 15:27:30 -040076 routes, err := agent.deviceRoutes.GetHalfRoute(false, ingressPortNo, egressPortNo)
77 if err != nil {
78 return nil, fmt.Errorf("no downstream route from:%d to:%d :%w", ingressPortNo, egressPortNo, route.ErrNoRoute)
Kent Hagerman3136fbd2020-05-14 10:30:45 -040079 }
khenaidoo0db4c812020-05-27 15:27:30 -040080 return routes, nil
Kent Hagerman3136fbd2020-05-14 10:30:45 -040081 }
Kent Hagerman3136fbd2020-05-14 10:30:45 -040082
khenaidoo0db4c812020-05-27 15:27:30 -040083 // Return the pre-calculated route
84 return agent.deviceRoutes.GetRoute(ctx, ingressPortNo, egressPortNo)
Kent Hagerman3136fbd2020-05-14 10:30:45 -040085}
86
87// GetDeviceRoutes returns device graph
88func (agent *LogicalAgent) GetDeviceRoutes() *route.DeviceRoutes {
89 return agent.deviceRoutes
90}
91
Kent Hagerman3136fbd2020-05-14 10:30:45 -040092//rebuildRoutes rebuilds the device routes
93func (agent *LogicalAgent) buildRoutes(ctx context.Context) error {
94 logger.Debugf("building-routes", log.Fields{"logical-device-id": agent.logicalDeviceID})
95 if err := agent.requestQueue.WaitForGreenLight(ctx); err != nil {
96 return err
97 }
98 defer agent.requestQueue.RequestComplete()
99
100 if agent.deviceRoutes == nil {
101 agent.deviceRoutes = route.NewDeviceRoutes(agent.logicalDeviceID, agent.deviceMgr.getDevice)
102 }
103 // Get all the logical ports on that logical device
104 lDevice := agent.getLogicalDeviceWithoutLock()
105
106 if err := agent.deviceRoutes.ComputeRoutes(ctx, lDevice.Ports); err != nil {
107 return err
108 }
109 if err := agent.deviceRoutes.Print(); err != nil {
110 return err
111 }
112 return nil
113}
114
115//updateRoutes updates the device routes
khenaidoo0db4c812020-05-27 15:27:30 -0400116func (agent *LogicalAgent) updateRoutes(ctx context.Context, device *voltha.Device, lp *voltha.LogicalPort, lps []*voltha.LogicalPort) error {
117 logger.Debugw("updateRoutes", log.Fields{"logical-device-id": agent.logicalDeviceID, "device-id": device.Id, "port:": lp})
118
119 if err := agent.deviceRoutes.AddPort(ctx, lp, device, lps); err != nil {
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400120 return err
121 }
khenaidoo0db4c812020-05-27 15:27:30 -0400122 if err := agent.deviceRoutes.Print(); err != nil {
123 return err
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400124 }
khenaidoo0db4c812020-05-27 15:27:30 -0400125 return nil
126}
127
128//updateAllRoutes updates the device routes using all the logical ports on that device
129func (agent *LogicalAgent) updateAllRoutes(ctx context.Context, device *voltha.Device) error {
130 logger.Debugw("updateAllRoutes", log.Fields{"logical-device-id": agent.logicalDeviceID, "device-id": device.Id, "ports-count": len(device.Ports)})
131
132 ld, err := agent.GetLogicalDevice(ctx)
133 if err != nil {
134 return err
135 }
136
137 if err := agent.deviceRoutes.AddAllPorts(ctx, device, ld.Ports); err != nil {
Kent Hagerman3136fbd2020-05-14 10:30:45 -0400138 return err
139 }
140 if err := agent.deviceRoutes.Print(); err != nil {
141 return err
142 }
143 return nil
144}