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 | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame^] | 26 | pb "github.com/opencord/voltha-protos/v2/go/voltha" |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 27 | |
| 28 | "log" |
| 29 | "net" |
| 30 | ) |
| 31 | |
| 32 | var conn net.Conn |
| 33 | var volthaClient *pb.VolthaServiceClient |
| 34 | var packetOutChannel chan pb.PacketOut |
| 35 | |
| 36 | type Client struct { |
| 37 | OfServerAddress string |
| 38 | Port uint16 |
| 39 | DeviceId string |
| 40 | KeepRunning bool |
| 41 | } |
| 42 | |
| 43 | func 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 | |
| 49 | func (client *Client) End() { |
| 50 | client.KeepRunning = false |
| 51 | } |
| 52 | func (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) |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame^] | 58 | return |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 59 | } |
| 60 | for { |
| 61 | if client.KeepRunning { |
| 62 | connection, e := net.DialTCP("tcp", nil, raddr) |
| 63 | conn = connection |
| 64 | if e != nil { |
| 65 | log.Fatalf("unable to connect to %v", raddr) |
| 66 | } |
| 67 | defer conn.Close() |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame^] | 68 | client.sayHello() |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 69 | for { |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame^] | 70 | if !client.KeepRunning { |
| 71 | return |
| 72 | } |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 73 | buf := make([]byte, 1500) |
| 74 | read, e := conn.Read(buf) |
| 75 | if e != nil { |
| 76 | log.Printf("Connection has died %v", e) |
| 77 | break |
| 78 | } |
| 79 | decoder := goloxi.NewDecoder(buf) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 80 | header, e := ofp.DecodeHeader(decoder) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 81 | |
| 82 | if e != nil { |
| 83 | log.Printf("decodeheader threw error %v", e) |
| 84 | } |
| 85 | message, _ := json.Marshal(header) |
| 86 | log.Printf("message %s\n", message) |
| 87 | client.parseHeader(header, buf) //first one is ready |
| 88 | len := header.GetLength() |
| 89 | if len < uint16(read) { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 90 | for { |
| 91 | read = read - int(len) |
| 92 | newBuf := buf[len:] |
| 93 | decoder = goloxi.NewDecoder(newBuf) |
| 94 | newHeader, e := ofp.DecodeHeader(decoder) |
| 95 | message, _ := json.Marshal(newHeader) |
| 96 | log.Printf("message %s\n", message) |
| 97 | if e != nil { |
| 98 | |
| 99 | } |
| 100 | len = newHeader.GetLength() |
| 101 | client.parseHeader(newHeader, newBuf) |
| 102 | if read == int(len) { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 103 | break |
| 104 | } else { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 105 | } |
| 106 | buf = newBuf |
| 107 | } |
| 108 | } |
| 109 | if e != nil { |
| 110 | log.Println("Decode Header error ", e) |
| 111 | } |
| 112 | } |
| 113 | } |
| 114 | break |
| 115 | } |
| 116 | } |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame^] | 117 | func (client *Client) sayHello() { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 118 | |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame^] | 119 | hello := ofp.NewHello() |
| 120 | hello.Xid = uint32(GetXid()) |
| 121 | var elements []ofp.IHelloElem |
| 122 | |
| 123 | elem := ofp.NewHelloElemVersionbitmap() |
| 124 | elem.SetType(ofp.OFPHETVersionbitmap) |
| 125 | elem.SetLength(8) |
| 126 | var bitmap = ofp.Uint32{Value: 16} |
| 127 | bitmaps := []*ofp.Uint32{&bitmap} |
| 128 | |
| 129 | elem.SetBitmaps(bitmaps) |
| 130 | |
| 131 | elements = append(elements, elem) |
| 132 | |
| 133 | hello.SetElements(elements) |
| 134 | e := client.SendMessage(hello) |
| 135 | if e != nil { |
| 136 | log.Fatal(e) |
| 137 | } |
| 138 | } |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 139 | func (client *Client) parseHeader(header ofp.IHeader, buf []byte) { |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 140 | switch header.GetType() { |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 141 | case ofp.OFPTHello: |
Don Newton | b437c6f | 2019-12-18 11:51:57 -0500 | [diff] [blame^] | 142 | //x := header.(*ofp.Hello) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 143 | case ofp.OFPTError: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 144 | errMsg := header.(*ofp.ErrorMsg) |
| 145 | go handleErrMsg(errMsg) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 146 | case ofp.OFPTEchoRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 147 | echoReq := header.(*ofp.EchoRequest) |
| 148 | go handleEchoRequest(echoReq, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 149 | case ofp.OFPTEchoReply: |
| 150 | case ofp.OFPTExperimenter: |
| 151 | case ofp.OFPTFeaturesRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 152 | featReq := header.(*ofp.FeaturesRequest) |
| 153 | go handleFeatureRequest(featReq, client.DeviceId, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 154 | case ofp.OFPTFeaturesReply: |
| 155 | case ofp.OFPTGetConfigRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 156 | configReq := header.(*ofp.GetConfigRequest) |
| 157 | go handleGetConfigRequest(configReq, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 158 | case ofp.OFPTGetConfigReply: |
| 159 | case ofp.OFPTSetConfig: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 160 | setConf := header.(*ofp.SetConfig) |
| 161 | go handleSetConfig(setConf) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 162 | case ofp.OFPTPacketIn: |
| 163 | case ofp.OFPTFlowRemoved: |
| 164 | case ofp.OFPTPortStatus: |
| 165 | case ofp.OFPTPacketOut: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 166 | packetOut := header.(*ofp.PacketOut) |
| 167 | go handlePacketOut(packetOut, client.DeviceId) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 168 | case ofp.OFPTFlowMod: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 169 | flowModType := uint8(buf[25]) |
| 170 | switch flowModType { |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 171 | case ofp.OFPFCAdd: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 172 | flowAdd := header.(*ofp.FlowAdd) |
| 173 | go handleFlowAdd(flowAdd, client.DeviceId) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 174 | case ofp.OFPFCModify: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 175 | flowMod := header.(*ofp.FlowMod) |
| 176 | go handleFlowMod(flowMod, client.DeviceId) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 177 | case ofp.OFPFCModifyStrict: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 178 | flowModStrict := header.(*ofp.FlowModifyStrict) |
| 179 | go handleFlowModStrict(flowModStrict, client.DeviceId) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 180 | case ofp.OFPFCDelete: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 181 | flowDelete := header.(*ofp.FlowDelete) |
| 182 | go handleFlowDelete(flowDelete, client.DeviceId) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 183 | case ofp.OFPFCDeleteStrict: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 184 | flowDeleteStrict := header.(*ofp.FlowDeleteStrict) |
| 185 | go handleFlowDeleteStrict(flowDeleteStrict, client.DeviceId) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 186 | } |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 187 | case ofp.OFPTStatsRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 188 | var statType = uint16(buf[8])<<8 + uint16(buf[9]) |
| 189 | log.Println("statsType", statType) |
| 190 | go handleStatsRequest(header, statType, client.DeviceId, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 191 | case ofp.OFPTBarrierRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 192 | barRequest := header.(*ofp.BarrierRequest) |
| 193 | go handleBarrierRequest(barRequest, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 194 | case ofp.OFPTRoleRequest: |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 195 | roleReq := header.(*ofp.RoleRequest) |
| 196 | go handleRoleRequest(roleReq, client) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 197 | case ofp.OFPTMeterMod: |
| 198 | meterMod := header.(*ofp.MeterMod) |
| 199 | go handleMeterModRequest(meterMod, client) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 200 | |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | //openFlowMessage created to allow for a single SendMessage |
| 205 | type OpenFlowMessage interface { |
| 206 | Serialize(encoder *goloxi.Encoder) error |
| 207 | } |
| 208 | |
| 209 | func (client *Client) SendMessage(message OpenFlowMessage) error { |
| 210 | jsonMessage, _ := json.Marshal(message) |
| 211 | log.Printf("send message called %s\n", jsonMessage) |
| 212 | enc := goloxi.NewEncoder() |
| 213 | message.Serialize(enc) |
| 214 | jMessage, _ := json.Marshal(message) |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 215 | bytes := enc.Bytes() |
| 216 | log.Printf("message after serialize %d for message %s", bytes, jMessage) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 217 | |
| 218 | for { |
| 219 | if conn == nil { |
| 220 | log.Println("CONN IS NIL") |
| 221 | time.Sleep(10 * time.Millisecond) |
| 222 | } else { |
| 223 | break |
| 224 | } |
| 225 | } |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 226 | _, err := conn.Write(bytes) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 227 | if err != nil { |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 228 | log.Printf("SendMessage had error %v \n %s\n********", err, jMessage) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 229 | return err |
Don Newton | e0d34a8 | 2019-11-14 10:58:06 -0500 | [diff] [blame] | 230 | } else { |
| 231 | log.Printf("message after send %s", jMessage) |
Don Newton | 98fd881 | 2019-09-23 15:15:02 -0400 | [diff] [blame] | 232 | } |
| 233 | return nil |
| 234 | } |
| 235 | func SetGrpcClient(client *pb.VolthaServiceClient) { |
| 236 | volthaClient = client |
| 237 | } |
| 238 | func getGrpcClient() *pb.VolthaServiceClient { |
| 239 | return volthaClient |
| 240 | } |
| 241 | func test(hello ofp.IHello) { |
| 242 | fmt.Println("works") |
| 243 | } |
| 244 | func SetPacketOutChannel(pktOutChan chan pb.PacketOut) { |
| 245 | packetOutChannel = pktOutChan |
| 246 | } |