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