blob: f3555aefaff10406e56f2b2ca925d78ade32d5bc [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/golang/protobuf/ptypes/empty"
Jonathan Hart828908c2020-04-15 14:23:45 -070024 "github.com/opencord/goloxi"
25 ofp "github.com/opencord/goloxi/of13"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080026 "github.com/opencord/ofagent-go/internal/pkg/openflow"
Maninder12b909f2020-10-23 14:23:36 +053027 "github.com/opencord/voltha-lib-go/v4/pkg/log"
28 "github.com/opencord/voltha-protos/v4/go/openflow_13"
29 "github.com/opencord/voltha-protos/v4/go/voltha"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080030 "google.golang.org/grpc"
31)
32
33func (ofa *OFAgent) receivePacketsIn(ctx context.Context) {
Girish Kumar01e0c632020-08-10 16:48:56 +000034 span, ctx := log.CreateChildSpan(ctx, "receive-packets-in")
35 defer span.Finish()
36
Rohan Agrawalc32d9932020-06-15 11:01:47 +000037 logger.Debug(ctx, "receive-packets-in-started")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080038 // If we exit, assume disconnected
39 defer func() {
40 ofa.events <- ofaEventVolthaDisconnected
Rohan Agrawalc32d9932020-06-15 11:01:47 +000041 logger.Debug(ctx, "receive-packets-in-finished")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080042 }()
43 if ofa.volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000044 logger.Error(ctx, "no-voltha-connection")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080045 return
46 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -080047 opt := grpc.EmptyCallOption{}
Girish Kumar01e0c632020-08-10 16:48:56 +000048 streamCtx, streamDone := context.WithCancel(log.WithSpanFromContext(context.Background(), ctx))
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080049 defer streamDone()
David Bainbridgef8ce7d22020-04-08 12:49:41 -070050 stream, err := ofa.volthaClient.Get().ReceivePacketsIn(streamCtx, &empty.Empty{}, opt)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080051 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000052 logger.Errorw(ctx, "Unable to establish Receive PacketIn Stream",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080053 log.Fields{"error": err})
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080054 return
David K. Bainbridge157bdab2020-01-16 14:38:05 -080055 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080056
57top:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080058
59 for {
60 select {
61 case <-ctx.Done():
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080062 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080063 default:
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080064 pkt, err := stream.Recv()
65 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000066 logger.Errorw(ctx, "error receiving packet",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080067 log.Fields{"error": err})
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080068 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080069 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080070 ofa.packetInChannel <- pkt
David K. Bainbridge157bdab2020-01-16 14:38:05 -080071 }
72 }
73}
74
75func (ofa *OFAgent) handlePacketsIn(ctx context.Context) {
Girish Kumar01e0c632020-08-10 16:48:56 +000076 span, ctx := log.CreateChildSpan(ctx, "handle-packets-in")
77 defer span.Finish()
78
Rohan Agrawalc32d9932020-06-15 11:01:47 +000079 logger.Debug(ctx, "handle-packets-in-started")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080080top:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080081 for {
82 select {
83 case <-ctx.Done():
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080084 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080085 case packet := <-ofa.packetInChannel:
86 packetIn := packet.GetPacketIn()
87
88 if logger.V(log.DebugLevel) {
89 js, _ := json.Marshal(packetIn)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000090 logger.Debugw(ctx, "packet-in received", log.Fields{"packet-in": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -080091 }
92 deviceID := packet.GetId()
93 ofPacketIn := ofp.NewPacketIn()
94 ofPacketIn.SetVersion(uint8(4))
95 ofPacketIn.SetXid(openflow.GetXid())
96 ofPacketIn.SetBufferId(packetIn.GetBufferId())
97 ofPacketIn.SetCookie(packetIn.GetCookie())
98 ofPacketIn.SetData(packetIn.GetData())
99 match := ofp.NewMatchV3()
100 inMatch := packetIn.GetMatch()
101 match.SetType(uint16(inMatch.GetType()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800102 var fields []goloxi.IOxm
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800103 for _, oxmField := range inMatch.GetOxmFields() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800104 field := oxmField.GetField()
105 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800106 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)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800111 fields = append(fields, ofpInPort)
112 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
113 ofpEthType := ofp.NewOxmEthType()
114 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
115 ofpEthType.Value = ofp.EthernetType(val.EthType)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800116 fields = append(fields, ofpEthType)
117 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
118 ofpInPhyPort := ofp.NewOxmInPhyPort()
119 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
120 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800121 fields = append(fields, ofpInPhyPort)
122 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
123 ofpIpProto := ofp.NewOxmIpProto()
124 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
125 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800126 fields = append(fields, ofpIpProto)
127 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
128 ofpUdpSrc := ofp.NewOxmUdpSrc()
129 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
130 ofpUdpSrc.Value = uint16(val.UdpSrc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800131 fields = append(fields, ofpUdpSrc)
132 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
133 ofpUdpDst := ofp.NewOxmUdpDst()
134 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
135 ofpUdpDst.Value = uint16(val.UdpDst)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800136 fields = append(fields, ofpUdpDst)
137 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
138 ofpVlanVid := ofp.NewOxmVlanVid()
139 val := ofbField.GetValue()
140 if val != nil {
141 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
142 ofpVlanVid.Value = uint16(vlanId.VlanVid) + 0x1000
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800143 } else {
144 ofpVlanVid.Value = uint16(0)
145 }
146
147 fields = append(fields, ofpVlanVid)
148 default:
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000149 logger.Warnw(ctx, "receive-packet-in:unhandled-oxm-field",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800150 log.Fields{"field": ofbField.Type})
151 }
152 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800153
154 match.SetOxmList(fields)
155
156 ofPacketIn.SetMatch(*match)
157 ofPacketIn.SetReason(uint8(packetIn.GetReason()))
158 ofPacketIn.SetTableId(uint8(packetIn.GetTableId()))
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000159 ofc := ofa.getOFClient(ctx, deviceID)
160 if err := ofc.SendMessage(ctx, ofPacketIn); err != nil {
161 logger.Errorw(ctx, "send-message-failed", log.Fields{
David K. Bainbridgecac73ac2020-02-19 07:00:12 -0800162 "device-id": deviceID,
163 "error": err})
164 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800165
166 }
167 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000168 logger.Debug(ctx, "handle-packets-in-finished")
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800169}