blob: 375e84f2f2a72e8c7eec921ccbe0c337b78b0441 [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"
David K. Bainbridgee05cf0c2021-08-19 03:16:50 +000027 "github.com/opencord/voltha-lib-go/v7/pkg/log"
28 "github.com/opencord/voltha-protos/v5/go/openflow_13"
29 "github.com/opencord/voltha-protos/v5/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 K. Bainbridgee05cf0c2021-08-19 03:16:50 +000050 vc := ofa.volthaClient.Get()
51 if vc == nil {
52 logger.Error(ctx, "No client found to establish Receive PacketIn Stream")
53 return
54 }
55 stream, err := vc.ReceivePacketsIn(streamCtx, &empty.Empty{}, opt)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080056 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000057 logger.Errorw(ctx, "Unable to establish Receive PacketIn Stream",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080058 log.Fields{"error": err})
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080059 return
David K. Bainbridge157bdab2020-01-16 14:38:05 -080060 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080061
62top:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080063
64 for {
65 select {
66 case <-ctx.Done():
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080067 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080068 default:
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080069 pkt, err := stream.Recv()
70 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000071 logger.Errorw(ctx, "error receiving packet",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080072 log.Fields{"error": err})
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080073 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080074 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080075 ofa.packetInChannel <- pkt
David K. Bainbridge157bdab2020-01-16 14:38:05 -080076 }
77 }
78}
79
80func (ofa *OFAgent) handlePacketsIn(ctx context.Context) {
Girish Kumar01e0c632020-08-10 16:48:56 +000081 span, ctx := log.CreateChildSpan(ctx, "handle-packets-in")
82 defer span.Finish()
83
Rohan Agrawalc32d9932020-06-15 11:01:47 +000084 logger.Debug(ctx, "handle-packets-in-started")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080085top:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080086 for {
87 select {
88 case <-ctx.Done():
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080089 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080090 case packet := <-ofa.packetInChannel:
91 packetIn := packet.GetPacketIn()
92
93 if logger.V(log.DebugLevel) {
94 js, _ := json.Marshal(packetIn)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000095 logger.Debugw(ctx, "packet-in received", log.Fields{"packet-in": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -080096 }
97 deviceID := packet.GetId()
98 ofPacketIn := ofp.NewPacketIn()
99 ofPacketIn.SetVersion(uint8(4))
100 ofPacketIn.SetXid(openflow.GetXid())
101 ofPacketIn.SetBufferId(packetIn.GetBufferId())
102 ofPacketIn.SetCookie(packetIn.GetCookie())
103 ofPacketIn.SetData(packetIn.GetData())
104 match := ofp.NewMatchV3()
105 inMatch := packetIn.GetMatch()
106 match.SetType(uint16(inMatch.GetType()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800107 var fields []goloxi.IOxm
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800108 for _, oxmField := range inMatch.GetOxmFields() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800109 field := oxmField.GetField()
110 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800111 switch ofbField.Type {
112 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
113 ofpInPort := ofp.NewOxmInPort()
114 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
115 ofpInPort.Value = ofp.Port(val.Port)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800116 fields = append(fields, ofpInPort)
117 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
118 ofpEthType := ofp.NewOxmEthType()
119 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
120 ofpEthType.Value = ofp.EthernetType(val.EthType)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800121 fields = append(fields, ofpEthType)
122 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
123 ofpInPhyPort := ofp.NewOxmInPhyPort()
124 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
125 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800126 fields = append(fields, ofpInPhyPort)
127 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
128 ofpIpProto := ofp.NewOxmIpProto()
129 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
130 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800131 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)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800136 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)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800141 fields = append(fields, ofpUdpDst)
142 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
143 ofpVlanVid := ofp.NewOxmVlanVid()
144 val := ofbField.GetValue()
145 if val != nil {
146 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
147 ofpVlanVid.Value = uint16(vlanId.VlanVid) + 0x1000
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800148 } else {
149 ofpVlanVid.Value = uint16(0)
150 }
151
152 fields = append(fields, ofpVlanVid)
153 default:
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000154 logger.Warnw(ctx, "receive-packet-in:unhandled-oxm-field",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800155 log.Fields{"field": ofbField.Type})
156 }
157 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800158
159 match.SetOxmList(fields)
160
161 ofPacketIn.SetMatch(*match)
162 ofPacketIn.SetReason(uint8(packetIn.GetReason()))
163 ofPacketIn.SetTableId(uint8(packetIn.GetTableId()))
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000164 ofc := ofa.getOFClient(ctx, deviceID)
165 if err := ofc.SendMessage(ctx, ofPacketIn); err != nil {
166 logger.Errorw(ctx, "send-message-failed", log.Fields{
David K. Bainbridgecac73ac2020-02-19 07:00:12 -0800167 "device-id": deviceID,
168 "error": err})
169 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800170
171 }
172 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000173 logger.Debug(ctx, "handle-packets-in-finished")
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800174}