Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 1 | /* |
| 2 | Copyright 2017 the original author or authors. |
| 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 | |
| 17 | package openflow |
| 18 | |
| 19 | import ( |
| 20 | "encoding/json" |
| 21 | "fmt" |
| 22 | "time" |
| 23 | |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 24 | "github.com/donNewtonAlpha/goloxi" |
| 25 | ofp "github.com/donNewtonAlpha/goloxi/of13" |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 26 | "github.com/opencord/ofagent-go/settings" |
| 27 | l "github.com/opencord/voltha-lib-go/v2/pkg/log" |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 28 | pb "github.com/opencord/voltha-protos/v2/go/voltha" |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 29 | |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 30 | "net" |
| 31 | ) |
| 32 | |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 33 | var volthaClient *pb.VolthaServiceClient |
| 34 | var packetOutChannel chan pb.PacketOut |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 35 | var logger, _ = l.AddPackage(l.JSON, l.DebugLevel, nil) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 36 | |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 37 | //Client structure to hold fields of Openflow Client |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 38 | type Client struct { |
| 39 | OfServerAddress string |
| 40 | Port uint16 |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 41 | DeviceID string |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 42 | KeepRunning bool |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 43 | conn net.Conn |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 44 | } |
| 45 | |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 46 | //NewClient contstructs a new Openflow Client and then starts up |
| 47 | func NewClient(ofServerAddress string, port uint16, deviceID string, keepRunning bool) *Client { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 48 | |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 49 | client := Client{OfServerAddress: ofServerAddress, Port: port, DeviceID: deviceID, KeepRunning: keepRunning} |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 50 | addressLine := fmt.Sprintf("%s:%d", client.OfServerAddress, client.Port) |
| 51 | raddr, e := net.ResolveTCPAddr("tcp", addressLine) |
| 52 | if e != nil { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 53 | logger.Fatalw("openflowClient Start unable to resolve address", l.Fields{"Address": addressLine}) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 54 | } |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 55 | connection, e := net.DialTCP("tcp", nil, raddr) |
| 56 | client.conn = connection |
| 57 | if e != nil { |
| 58 | logger.Fatalf("openflowClient Unable to connect to voltha @ %v exiting", raddr) |
| 59 | } |
| 60 | client.sayHello() |
| 61 | return &client |
| 62 | } |
| 63 | |
| 64 | //End - set keepRunning to false so start loop exits |
| 65 | func (client *Client) End() { |
| 66 | client.KeepRunning = false |
| 67 | } |
| 68 | |
| 69 | //Start run loop for the openflow client |
| 70 | func (client *Client) Start() { |
| 71 | |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 72 | for { |
| 73 | if client.KeepRunning { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 74 | defer client.conn.Close() |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 75 | for { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 76 | defer func() { |
| 77 | |
| 78 | if r := recover(); r != nil { |
| 79 | err := r.(error) |
| 80 | fmt.Printf("Caught error in client.Start() %v \n ", err) |
| 81 | } |
| 82 | }() |
| 83 | |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 84 | if !client.KeepRunning { |
| 85 | return |
| 86 | } |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 87 | buf := make([]byte, 1500) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 88 | read, e := client.conn.Read(buf) |
| 89 | if settings.GetDebug(client.DeviceID) { |
| 90 | fmt.Printf("conn.Read read %d bytes\n", read) |
| 91 | } |
| 92 | if read < 8 { |
| 93 | continue |
| 94 | } |
| 95 | |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 96 | if e != nil { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 97 | logger.Errorw("Voltha connection has died", l.Fields{"DeviceID": client.DeviceID, "Error": e}) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 98 | break |
| 99 | } |
| 100 | decoder := goloxi.NewDecoder(buf) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 101 | header, e := ofp.DecodeHeader(decoder) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 102 | |
| 103 | if e != nil { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 104 | js, _ := json.Marshal(decoder) |
| 105 | logger.Errorw("DecodeHeader threw error", l.Fields{"DeviceID": client.DeviceID, "Decoder": js, "Error": e}) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 106 | } |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 107 | if settings.GetDebug(client.DeviceID) { |
| 108 | js, _ := json.Marshal(header) |
| 109 | logger.Debugw("Header Decode", l.Fields{"DeviceID": client.DeviceID, "Header": js}) |
| 110 | } |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 111 | client.parseHeader(header, buf) //first one is ready |
| 112 | len := header.GetLength() |
| 113 | if len < uint16(read) { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 114 | for { |
| 115 | read = read - int(len) |
| 116 | newBuf := buf[len:] |
| 117 | decoder = goloxi.NewDecoder(newBuf) |
| 118 | newHeader, e := ofp.DecodeHeader(decoder) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 119 | if e != nil { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 120 | js, _ := json.Marshal(decoder) |
| 121 | logger.Errorw("DecodeHeader threw error", l.Fields{"DeviceID": client.DeviceID, "Decoder": js, "Error": e}) |
| 122 | } |
| 123 | if e != nil { |
| 124 | js, _ := json.Marshal(decoder) |
| 125 | logger.Errorw("DecodeHeader threw error", l.Fields{"DeviceID": client.DeviceID, "Decoder": js, "Error": e}) |
| 126 | } |
| 127 | if settings.GetDebug(client.DeviceID) { |
| 128 | js, _ := json.Marshal(header) |
| 129 | logger.Debugw("Header Decode", l.Fields{"DeviceID": client.DeviceID, "Header": js}) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 130 | } |
| 131 | len = newHeader.GetLength() |
| 132 | client.parseHeader(newHeader, newBuf) |
| 133 | if read == int(len) { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 134 | break |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 135 | } |
| 136 | buf = newBuf |
| 137 | } |
| 138 | } |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 139 | } |
| 140 | } |
| 141 | break |
| 142 | } |
| 143 | } |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 144 | func (client *Client) sayHello() { |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 145 | hello := ofp.NewHello() |
| 146 | hello.Xid = uint32(GetXid()) |
| 147 | var elements []ofp.IHelloElem |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 148 | elem := ofp.NewHelloElemVersionbitmap() |
| 149 | elem.SetType(ofp.OFPHETVersionbitmap) |
| 150 | elem.SetLength(8) |
| 151 | var bitmap = ofp.Uint32{Value: 16} |
| 152 | bitmaps := []*ofp.Uint32{&bitmap} |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 153 | elem.SetBitmaps(bitmaps) |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 154 | elements = append(elements, elem) |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 155 | hello.SetElements(elements) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 156 | if settings.GetDebug(client.DeviceID) { |
| 157 | js, _ := json.Marshal(hello) |
| 158 | logger.Debugw("sayHello Called", l.Fields{"DeviceID": client.DeviceID, "HelloMessage": js}) |
| 159 | } |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 160 | e := client.SendMessage(hello) |
| 161 | if e != nil { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 162 | logger.Fatalw("Failed saying hello to Openflow Server, unable to proceed", |
| 163 | l.Fields{"DeviceID": client.DeviceID, "Error": e}) |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 164 | } |
| 165 | } |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 166 | func (client *Client) parseHeader(header ofp.IHeader, buf []byte) { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 167 | switch header.GetType() { |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 168 | case ofp.OFPTHello: |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame] | 169 | //x := header.(*ofp.Hello) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 170 | case ofp.OFPTError: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 171 | errMsg := header.(*ofp.ErrorMsg) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 172 | go handleErrMsg(errMsg, client.DeviceID) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 173 | case ofp.OFPTEchoRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 174 | echoReq := header.(*ofp.EchoRequest) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 175 | go handleEchoRequest(echoReq, client.DeviceID, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 176 | case ofp.OFPTEchoReply: |
| 177 | case ofp.OFPTExperimenter: |
| 178 | case ofp.OFPTFeaturesRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 179 | featReq := header.(*ofp.FeaturesRequest) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 180 | go handleFeatureRequest(featReq, client.DeviceID, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 181 | case ofp.OFPTFeaturesReply: |
| 182 | case ofp.OFPTGetConfigRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 183 | configReq := header.(*ofp.GetConfigRequest) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 184 | go handleGetConfigRequest(configReq, client.DeviceID, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 185 | case ofp.OFPTGetConfigReply: |
| 186 | case ofp.OFPTSetConfig: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 187 | setConf := header.(*ofp.SetConfig) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 188 | go handleSetConfig(setConf, client.DeviceID) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 189 | case ofp.OFPTPacketIn: |
| 190 | case ofp.OFPTFlowRemoved: |
| 191 | case ofp.OFPTPortStatus: |
| 192 | case ofp.OFPTPacketOut: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 193 | packetOut := header.(*ofp.PacketOut) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 194 | go handlePacketOut(packetOut, client.DeviceID) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 195 | case ofp.OFPTFlowMod: |
Don Newton | 6f6c866 | 2020-01-15 14:44:49 -0500 | [diff] [blame^] | 196 | /* Not using go routine to handle flow* messages or barrier requests |
| 197 | onos typically issues barrier requests just before a flow* message. |
| 198 | by handling in this thread I ensure all flow* are handled when barrier |
| 199 | request is issued. |
| 200 | */ |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 201 | flowModType := uint8(buf[25]) |
| 202 | switch flowModType { |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 203 | case ofp.OFPFCAdd: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 204 | flowAdd := header.(*ofp.FlowAdd) |
Don Newton | 6f6c866 | 2020-01-15 14:44:49 -0500 | [diff] [blame^] | 205 | handleFlowAdd(flowAdd, client.DeviceID) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 206 | case ofp.OFPFCModify: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 207 | flowMod := header.(*ofp.FlowMod) |
Don Newton | 6f6c866 | 2020-01-15 14:44:49 -0500 | [diff] [blame^] | 208 | handleFlowMod(flowMod, client.DeviceID) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 209 | case ofp.OFPFCModifyStrict: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 210 | flowModStrict := header.(*ofp.FlowModifyStrict) |
Don Newton | 6f6c866 | 2020-01-15 14:44:49 -0500 | [diff] [blame^] | 211 | handleFlowModStrict(flowModStrict, client.DeviceID) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 212 | case ofp.OFPFCDelete: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 213 | flowDelete := header.(*ofp.FlowDelete) |
Don Newton | 6f6c866 | 2020-01-15 14:44:49 -0500 | [diff] [blame^] | 214 | handleFlowDelete(flowDelete, client.DeviceID) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 215 | case ofp.OFPFCDeleteStrict: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 216 | flowDeleteStrict := header.(*ofp.FlowDeleteStrict) |
Don Newton | 6f6c866 | 2020-01-15 14:44:49 -0500 | [diff] [blame^] | 217 | handleFlowDeleteStrict(flowDeleteStrict, client.DeviceID) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 218 | } |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 219 | case ofp.OFPTStatsRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 220 | var statType = uint16(buf[8])<<8 + uint16(buf[9]) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 221 | go handleStatsRequest(header, statType, client.DeviceID, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 222 | case ofp.OFPTBarrierRequest: |
Don Newton | 6f6c866 | 2020-01-15 14:44:49 -0500 | [diff] [blame^] | 223 | /* See note above at case ofp.OFPTFlowMod:*/ |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 224 | barRequest := header.(*ofp.BarrierRequest) |
Don Newton | 6f6c866 | 2020-01-15 14:44:49 -0500 | [diff] [blame^] | 225 | handleBarrierRequest(barRequest, client.DeviceID, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 226 | case ofp.OFPTRoleRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 227 | roleReq := header.(*ofp.RoleRequest) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 228 | go handleRoleRequest(roleReq, client.DeviceID, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 229 | case ofp.OFPTMeterMod: |
| 230 | meterMod := header.(*ofp.MeterMod) |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 231 | go handleMeterModRequest(meterMod, client.DeviceID, client) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 232 | |
| 233 | } |
| 234 | } |
| 235 | |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 236 | //Message created to allow for a single SendMessage |
| 237 | type Message interface { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 238 | Serialize(encoder *goloxi.Encoder) error |
| 239 | } |
| 240 | |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 241 | //SendMessage sends message to openflow server |
| 242 | func (client *Client) SendMessage(message Message) error { |
| 243 | if settings.GetDebug(client.DeviceID) { |
| 244 | js, _ := json.Marshal(message) |
| 245 | logger.Debugw("SendMessage called", l.Fields{"DeviceID": client.DeviceID, "Message": js}) |
| 246 | } |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 247 | enc := goloxi.NewEncoder() |
| 248 | message.Serialize(enc) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 249 | for { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 250 | if client.conn == nil { |
| 251 | logger.Warnln("SendMessage Connection is Nil sleeping for 10 milliseconds") |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 252 | time.Sleep(10 * time.Millisecond) |
| 253 | } else { |
| 254 | break |
| 255 | } |
| 256 | } |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 257 | bytes := enc.Bytes() |
| 258 | _, err := client.conn.Write(bytes) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 259 | if err != nil { |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 260 | jMessage, _ := json.Marshal(message) |
| 261 | logger.Errorw("SendMessage failed sending message", l.Fields{"DeviceID": client.DeviceID, "Error": err, "Message": jMessage}) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 262 | return err |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 263 | } |
| 264 | return nil |
| 265 | } |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 266 | |
| 267 | //SetGrpcClient store a reference to the grpc client connection |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 268 | func SetGrpcClient(client *pb.VolthaServiceClient) { |
| 269 | volthaClient = client |
| 270 | } |
| 271 | func getGrpcClient() *pb.VolthaServiceClient { |
| 272 | return volthaClient |
| 273 | } |
Don Newton | 7577f07 | 2020-01-06 12:41:11 -0500 | [diff] [blame] | 274 | |
| 275 | //SetPacketOutChannel - store the channel to send packet outs to grpc connection |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 276 | func SetPacketOutChannel(pktOutChan chan pb.PacketOut) { |
| 277 | packetOutChannel = pktOutChan |
| 278 | } |