blob: b07e36d92ab2c7bdc2fb8848b458b7853eca24ce [file] [log] [blame]
Don Newton98fd8812019-09-23 15:15:02 -04001/*
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
17package openflow
18
19import (
20 "encoding/json"
21 "fmt"
22 "time"
23
24 pb "github.com/opencord/voltha-protos/go/voltha"
25 "github.com/skydive-project/goloxi"
26 ofp "github.com/skydive-project/goloxi/of13"
27
28 "log"
29 "net"
30)
31
32var conn net.Conn
33var volthaClient *pb.VolthaServiceClient
34var packetOutChannel chan pb.PacketOut
35
36type Client struct {
37 OfServerAddress string
38 Port uint16
39 DeviceId string
40 KeepRunning bool
41}
42
43func NewClient(ofServerAddress string, port uint16, deviceId string, keepRunning bool) *Client {
44 client := Client{OfServerAddress: ofServerAddress, Port: port, DeviceId: deviceId, KeepRunning: keepRunning}
45 go client.Start()
46 return &client
47}
48
49func (client *Client) End() {
50 client.KeepRunning = false
51}
52func (client *Client) Start() {
53 addressLine := fmt.Sprintf("%s:%d", client.OfServerAddress, client.Port)
54 raddr, e := net.ResolveTCPAddr("tcp", addressLine)
55 if e != nil {
56 errMessage := fmt.Errorf("Unable to resolve %s", addressLine)
57 fmt.Println(errMessage)
58 }
59 for {
60 if client.KeepRunning {
61 connection, e := net.DialTCP("tcp", nil, raddr)
62 conn = connection
63 if e != nil {
64 log.Fatalf("unable to connect to %v", raddr)
65 }
66 defer conn.Close()
67 hello := ofp.NewHello()
68 hello.Xid = uint32(GetXid())
69 var elements []ofp.IHelloElem
70
71 elem := ofp.NewHelloElemVersionbitmap()
72 elem.SetType(ofp.OFPHETVersionbitmap)
73 elem.SetLength(8)
74 var bitmap = ofp.Uint32{Value: 16}
75 bitmaps := []*ofp.Uint32{&bitmap}
76
77 elem.SetBitmaps(bitmaps)
78
79 elements = append(elements, elem)
80
81 hello.SetElements(elements)
82 e = client.SendMessage(hello)
83 if e != nil {
84 log.Fatal(e)
85 }
86 for {
87 buf := make([]byte, 1500)
88 read, e := conn.Read(buf)
89 if e != nil {
90 log.Printf("Connection has died %v", e)
91 break
92 }
93 decoder := goloxi.NewDecoder(buf)
94 log.Printf("decoder offset %d baseOffset %d", decoder.Offset(), decoder.BaseOffset())
95 header, e := ofp.DecodeHeader(decoder)
96 log.Printf("received packet read: %d", read)
97
98 if e != nil {
99 log.Printf("decodeheader threw error %v", e)
100 }
101 message, _ := json.Marshal(header)
102 log.Printf("message %s\n", message)
103 client.parseHeader(header, buf) //first one is ready
104 len := header.GetLength()
105 if len < uint16(read) {
106 log.Printf("Len %d was less than read %d", len, read)
107 for {
108 read = read - int(len)
109 newBuf := buf[len:]
110 decoder = goloxi.NewDecoder(newBuf)
111 newHeader, e := ofp.DecodeHeader(decoder)
112 message, _ := json.Marshal(newHeader)
113 log.Printf("message %s\n", message)
114 if e != nil {
115
116 }
117 len = newHeader.GetLength()
118 client.parseHeader(newHeader, newBuf)
119 if read == int(len) {
120 log.Printf(" not continuing read %d len %d", read, len)
121 break
122 } else {
123 log.Printf("continuing read %d len %d", read, len)
124 }
125 buf = newBuf
126 }
127 }
128 if e != nil {
129 log.Println("Decode Header error ", e)
130 }
131 }
132 }
133 break
134 }
135}
136
137func (client *Client) parseHeader(header ofp.IHeader, buf []byte) {
138
139 log.Printf("parseHeader called with type %d", header.GetType())
140 switch header.GetType() {
141 case 0:
142 x := header.(*ofp.Hello)
143 log.Printf("helloMessage : %+v", x)
144 //nothing real to do
145 case 1:
146 errMsg := header.(*ofp.ErrorMsg)
147 go handleErrMsg(errMsg)
148 case 2:
149 echoReq := header.(*ofp.EchoRequest)
150 go handleEchoRequest(echoReq, client)
151 case 3:
152 //EchoReply
153 case 4:
154 //Expirementer
155 case 5:
156 featReq := header.(*ofp.FeaturesRequest)
157 go handleFeatureRequest(featReq, client.DeviceId, client)
158 case 6:
159 //feature reply
160 case 7:
161 configReq := header.(*ofp.GetConfigRequest)
162 go handleGetConfigRequest(configReq, client)
163 case 8:
164 //GetConfigReply
165 case 9:
166 setConf := header.(*ofp.SetConfig)
167 go handleSetConfig(setConf)
168 case 10:
169 //packetIn := header.(*ofp.PacketIn)
170 //go handlePacketIn(packetIn)
171 case 11:
172 //FlowRemoved
173 case 12:
174 //portStatus
175 case 13:
176 packetOut := header.(*ofp.PacketOut)
177 go handlePacketOut(packetOut, client.DeviceId)
178 case 14:
179 flowModType := uint8(buf[25])
180 switch flowModType {
181 case 0:
182 flowAdd := header.(*ofp.FlowAdd)
183 go handleFlowAdd(flowAdd, client.DeviceId)
184 //return DecodeFlowAdd(_flowmod, decoder)
185 case 1:
186 flowMod := header.(*ofp.FlowMod)
187 go handleFlowMod(flowMod, client.DeviceId)
188 //return DecodeFlowModify(_flowmod, decoder)
189 case 2:
190 flowModStrict := header.(*ofp.FlowModifyStrict)
191 go handleFlowModStrict(flowModStrict, client.DeviceId)
192 //return DecodeFlowModifyStrict(_flowmod, decoder)
193 case 3:
194 flowDelete := header.(*ofp.FlowDelete)
195 go handleFlowDelete(flowDelete, client.DeviceId)
196 //return DecodeFlowDelete(_flowmod, decoder)
197 case 4:
198 flowDeleteStrict := header.(*ofp.FlowDeleteStrict)
199 go handleFlowDeleteStrict(flowDeleteStrict, client.DeviceId)
200 //return DecodeFlowDeleteStrict(_flowmod, decoder)
201 default:
202 //return nil, fmt.Errorf("Invalid type '%d' for 'FlowMod'", _flowmod.Command)
203
204 }
205 case 18:
206 var statType = uint16(buf[8])<<8 + uint16(buf[9])
207 log.Println("statsType", statType)
208 go handleStatsRequest(header, statType, client.DeviceId, client)
209 case 20:
210 barRequest := header.(*ofp.BarrierRequest)
211 go handleBarrierRequest(barRequest, client)
212 case 24:
213 roleReq := header.(*ofp.RoleRequest)
214 go handleRoleRequest(roleReq, client)
215
216 }
217}
218
219//openFlowMessage created to allow for a single SendMessage
220type OpenFlowMessage interface {
221 Serialize(encoder *goloxi.Encoder) error
222}
223
224func (client *Client) SendMessage(message OpenFlowMessage) error {
225 jsonMessage, _ := json.Marshal(message)
226 log.Printf("send message called %s\n", jsonMessage)
227 enc := goloxi.NewEncoder()
228 message.Serialize(enc)
229 jMessage, _ := json.Marshal(message)
230 log.Printf("message after serialize %s", jMessage)
231
232 for {
233 if conn == nil {
234 log.Println("CONN IS NIL")
235 time.Sleep(10 * time.Millisecond)
236 } else {
237 break
238 }
239 }
240 _, err := conn.Write(enc.Bytes())
241 if err != nil {
242 log.Printf("SendMessage had error %s", err)
243 return err
244 }
245 return nil
246}
247func SetGrpcClient(client *pb.VolthaServiceClient) {
248 volthaClient = client
249}
250func getGrpcClient() *pb.VolthaServiceClient {
251 return volthaClient
252}
253func test(hello ofp.IHello) {
254 fmt.Println("works")
255}
256func SetPacketOutChannel(pktOutChan chan pb.PacketOut) {
257 packetOutChannel = pktOutChan
258}