blob: 7b396fc2f5de74bd6259ce580fe6496a2cc60bfb [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"
David K. Bainbridge157bdab2020-01-16 14:38:05 -080029 "google.golang.org/grpc"
30)
31
32func (ofa *OFAgent) receivePacketsIn(ctx context.Context) {
Girish Kumar01e0c632020-08-10 16:48:56 +000033 span, ctx := log.CreateChildSpan(ctx, "receive-packets-in")
34 defer span.Finish()
35
Rohan Agrawalc32d9932020-06-15 11:01:47 +000036 logger.Debug(ctx, "receive-packets-in-started")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080037 // If we exit, assume disconnected
38 defer func() {
39 ofa.events <- ofaEventVolthaDisconnected
Rohan Agrawalc32d9932020-06-15 11:01:47 +000040 logger.Debug(ctx, "receive-packets-in-finished")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080041 }()
42 if ofa.volthaClient == nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000043 logger.Error(ctx, "no-voltha-connection")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080044 return
45 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -080046 opt := grpc.EmptyCallOption{}
Girish Kumar01e0c632020-08-10 16:48:56 +000047 streamCtx, streamDone := context.WithCancel(log.WithSpanFromContext(context.Background(), ctx))
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080048 defer streamDone()
David K. Bainbridgee05cf0c2021-08-19 03:16:50 +000049 vc := ofa.volthaClient.Get()
50 if vc == nil {
51 logger.Error(ctx, "No client found to establish Receive PacketIn Stream")
52 return
53 }
54 stream, err := vc.ReceivePacketsIn(streamCtx, &empty.Empty{}, opt)
David K. Bainbridge157bdab2020-01-16 14:38:05 -080055 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000056 logger.Errorw(ctx, "Unable to establish Receive PacketIn Stream",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080057 log.Fields{"error": err})
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080058 return
David K. Bainbridge157bdab2020-01-16 14:38:05 -080059 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080060
61top:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080062
63 for {
64 select {
65 case <-ctx.Done():
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080066 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080067 default:
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080068 pkt, err := stream.Recv()
69 if err != nil {
Rohan Agrawalc32d9932020-06-15 11:01:47 +000070 logger.Errorw(ctx, "error receiving packet",
David K. Bainbridge157bdab2020-01-16 14:38:05 -080071 log.Fields{"error": err})
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080072 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080073 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080074 ofa.packetInChannel <- pkt
David K. Bainbridge157bdab2020-01-16 14:38:05 -080075 }
76 }
77}
78
79func (ofa *OFAgent) handlePacketsIn(ctx context.Context) {
Girish Kumar01e0c632020-08-10 16:48:56 +000080 span, ctx := log.CreateChildSpan(ctx, "handle-packets-in")
81 defer span.Finish()
82
Rohan Agrawalc32d9932020-06-15 11:01:47 +000083 logger.Debug(ctx, "handle-packets-in-started")
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080084top:
David K. Bainbridge157bdab2020-01-16 14:38:05 -080085 for {
86 select {
87 case <-ctx.Done():
David K. Bainbridge9cb404e2020-01-28 14:32:29 -080088 break top
David K. Bainbridge157bdab2020-01-16 14:38:05 -080089 case packet := <-ofa.packetInChannel:
90 packetIn := packet.GetPacketIn()
91
92 if logger.V(log.DebugLevel) {
93 js, _ := json.Marshal(packetIn)
Rohan Agrawalc32d9932020-06-15 11:01:47 +000094 logger.Debugw(ctx, "packet-in received", log.Fields{"packet-in": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -080095 }
96 deviceID := packet.GetId()
97 ofPacketIn := ofp.NewPacketIn()
98 ofPacketIn.SetVersion(uint8(4))
99 ofPacketIn.SetXid(openflow.GetXid())
100 ofPacketIn.SetBufferId(packetIn.GetBufferId())
101 ofPacketIn.SetCookie(packetIn.GetCookie())
102 ofPacketIn.SetData(packetIn.GetData())
103 match := ofp.NewMatchV3()
104 inMatch := packetIn.GetMatch()
105 match.SetType(uint16(inMatch.GetType()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800106 var fields []goloxi.IOxm
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800107 for _, oxmField := range inMatch.GetOxmFields() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800108 field := oxmField.GetField()
109 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800110 switch ofbField.Type {
khenaidoofcf0b8d2021-10-19 17:57:30 -0400111 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800112 ofpInPort := ofp.NewOxmInPort()
113 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
114 ofpInPort.Value = ofp.Port(val.Port)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800115 fields = append(fields, ofpInPort)
khenaidoofcf0b8d2021-10-19 17:57:30 -0400116 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800117 ofpEthType := ofp.NewOxmEthType()
118 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
119 ofpEthType.Value = ofp.EthernetType(val.EthType)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800120 fields = append(fields, ofpEthType)
khenaidoofcf0b8d2021-10-19 17:57:30 -0400121 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800122 ofpInPhyPort := ofp.NewOxmInPhyPort()
123 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
124 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800125 fields = append(fields, ofpInPhyPort)
khenaidoofcf0b8d2021-10-19 17:57:30 -0400126 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800127 ofpIpProto := ofp.NewOxmIpProto()
128 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
129 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800130 fields = append(fields, ofpIpProto)
khenaidoofcf0b8d2021-10-19 17:57:30 -0400131 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800132 ofpUdpSrc := ofp.NewOxmUdpSrc()
133 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
134 ofpUdpSrc.Value = uint16(val.UdpSrc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800135 fields = append(fields, ofpUdpSrc)
khenaidoofcf0b8d2021-10-19 17:57:30 -0400136 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800137 ofpUdpDst := ofp.NewOxmUdpDst()
138 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
139 ofpUdpDst.Value = uint16(val.UdpDst)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800140 fields = append(fields, ofpUdpDst)
khenaidoofcf0b8d2021-10-19 17:57:30 -0400141 case openflow_13.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800142 ofpVlanVid := ofp.NewOxmVlanVid()
143 val := ofbField.GetValue()
144 if val != nil {
145 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
146 ofpVlanVid.Value = uint16(vlanId.VlanVid) + 0x1000
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800147 } else {
148 ofpVlanVid.Value = uint16(0)
149 }
150
151 fields = append(fields, ofpVlanVid)
152 default:
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000153 logger.Warnw(ctx, "receive-packet-in:unhandled-oxm-field",
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800154 log.Fields{"field": ofbField.Type})
155 }
156 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800157
158 match.SetOxmList(fields)
159
160 ofPacketIn.SetMatch(*match)
161 ofPacketIn.SetReason(uint8(packetIn.GetReason()))
162 ofPacketIn.SetTableId(uint8(packetIn.GetTableId()))
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000163 ofc := ofa.getOFClient(ctx, deviceID)
164 if err := ofc.SendMessage(ctx, ofPacketIn); err != nil {
165 logger.Errorw(ctx, "send-message-failed", log.Fields{
David K. Bainbridgecac73ac2020-02-19 07:00:12 -0800166 "device-id": deviceID,
167 "error": err})
168 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800169
170 }
171 }
Rohan Agrawalc32d9932020-06-15 11:01:47 +0000172 logger.Debug(ctx, "handle-packets-in-finished")
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800173}