blob: 685ab430f7370dfb037fa118e35ef5a44615ef1f [file] [log] [blame]
David K. Bainbridge157bdab2020-01-16 14:38:05 -08001/*
2 Copyright 2020 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 ofagent
18
19import (
20 "context"
21 "encoding/json"
David Bainbridgef8ce7d22020-04-08 12:49:41 -070022
David K. Bainbridge157bdab2020-01-16 14:38:05 -080023 "github.com/donNewtonAlpha/goloxi"
24 ofp "github.com/donNewtonAlpha/goloxi/of13"
25 "github.com/golang/protobuf/ptypes/empty"
26 "github.com/opencord/ofagent-go/internal/pkg/openflow"
David K. Bainbridgeaea73cd2020-01-27 10:44:50 -080027 "github.com/opencord/voltha-lib-go/v3/pkg/log"
28 "github.com/opencord/voltha-protos/v3/go/openflow_13"
29 "github.com/opencord/voltha-protos/v3/go/voltha"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080030 "google.golang.org/grpc"
31)
32
33func (ofa *OFAgent) receivePacketsIn(ctx context.Context) {
34 logger.Debug("receive-packets-in-started")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080035 // If we exit, assume disconnected
36 defer func() {
37 ofa.events <- ofaEventVolthaDisconnected
38 logger.Debug("receive-packets-in-finished")
39 }()
40 if ofa.volthaClient == nil {
41 logger.Error("no-voltha-connection")
42 return
43 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -080044 opt := grpc.EmptyCallOption{}
45 streamCtx, streamDone := context.WithCancel(context.Background())
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080046 defer streamDone()
David Bainbridgef8ce7d22020-04-08 12:49:41 -070047 stream, err := ofa.volthaClient.Get().ReceivePacketsIn(streamCtx, &empty.Empty{}, opt)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080048 if err != nil {
49 logger.Errorw("Unable to establish Receive PacketIn Stream",
50 log.Fields{"error": err})
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080051 return
David K. Bainbridge157bdab2020-01-16 14:38:05 -080052 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080053
54top:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080055
56 for {
57 select {
58 case <-ctx.Done():
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080059 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080060 default:
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080061 pkt, err := stream.Recv()
62 if err != nil {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080063 logger.Errorw("error receiving packet",
64 log.Fields{"error": err})
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080065 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080066 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080067 ofa.packetInChannel <- pkt
David K. Bainbridge157bdab2020-01-16 14:38:05 -080068 }
69 }
70}
71
72func (ofa *OFAgent) handlePacketsIn(ctx context.Context) {
73 logger.Debug("handle-packets-in-started")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080074top:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080075 for {
76 select {
77 case <-ctx.Done():
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080078 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080079 case packet := <-ofa.packetInChannel:
80 packetIn := packet.GetPacketIn()
81
82 if logger.V(log.DebugLevel) {
83 js, _ := json.Marshal(packetIn)
84 logger.Debugw("packet-in recieved", log.Fields{"packet-in": js})
85 }
86 deviceID := packet.GetId()
87 ofPacketIn := ofp.NewPacketIn()
88 ofPacketIn.SetVersion(uint8(4))
89 ofPacketIn.SetXid(openflow.GetXid())
90 ofPacketIn.SetBufferId(packetIn.GetBufferId())
91 ofPacketIn.SetCookie(packetIn.GetCookie())
92 ofPacketIn.SetData(packetIn.GetData())
93 match := ofp.NewMatchV3()
94 inMatch := packetIn.GetMatch()
95 match.SetType(uint16(inMatch.GetType()))
96 //oxFields := inMatch.GetOxmFields()
97 var fields []goloxi.IOxm
98 size := uint16(4)
99 for _, oxmField := range inMatch.GetOxmFields() {
100 /*
101 for i := 0; i < len(oxFields); i++ {
102 oxmField := oxFields[i]
103 */
104 field := oxmField.GetField()
105 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
106 size += 4 //header for oxm
107 switch ofbField.Type {
108 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
109 ofpInPort := ofp.NewOxmInPort()
110 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
111 ofpInPort.Value = ofp.Port(val.Port)
112 size += 4
113 fields = append(fields, ofpInPort)
114 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
115 ofpEthType := ofp.NewOxmEthType()
116 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
117 ofpEthType.Value = ofp.EthernetType(val.EthType)
118 size += 2
119 fields = append(fields, ofpEthType)
120 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
121 ofpInPhyPort := ofp.NewOxmInPhyPort()
122 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
123 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
124 size += 4
125 fields = append(fields, ofpInPhyPort)
126 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
127 ofpIpProto := ofp.NewOxmIpProto()
128 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
129 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
130 size += 1
131 fields = append(fields, ofpIpProto)
132 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
133 ofpUdpSrc := ofp.NewOxmUdpSrc()
134 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
135 ofpUdpSrc.Value = uint16(val.UdpSrc)
136 size += 2
137 fields = append(fields, ofpUdpSrc)
138 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
139 ofpUdpDst := ofp.NewOxmUdpDst()
140 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
141 ofpUdpDst.Value = uint16(val.UdpDst)
142 size += 2
143 fields = append(fields, ofpUdpDst)
144 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
145 ofpVlanVid := ofp.NewOxmVlanVid()
146 val := ofbField.GetValue()
147 if val != nil {
148 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
149 ofpVlanVid.Value = uint16(vlanId.VlanVid) + 0x1000
150 size += 2
151 } else {
152 ofpVlanVid.Value = uint16(0)
153 }
154
155 fields = append(fields, ofpVlanVid)
156 default:
157 logger.Warnw("receive-packet-in:unhandled-oxm-field",
158 log.Fields{"field": ofbField.Type})
159 }
160 }
161 match.SetLength(size)
162
163 match.SetOxmList(fields)
164
165 ofPacketIn.SetMatch(*match)
166 ofPacketIn.SetReason(uint8(packetIn.GetReason()))
167 ofPacketIn.SetTableId(uint8(packetIn.GetTableId()))
168 ofPacketIn.SetTotalLen(uint16(len(ofPacketIn.GetData())))
169 ofc := ofa.getOFClient(deviceID)
David K. Bainbridgecac73ac2020-02-19 07:00:12 -0800170 if err := ofc.SendMessage(ofPacketIn); err != nil {
171 logger.Errorw("send-message-failed", log.Fields{
172 "device-id": deviceID,
173 "error": err})
174 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800175
176 }
177 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800178 logger.Debug("handle-packets-in-finished")
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800179}