blob: 37443075e52ed9461d090a56ac72952b12dd7147 [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. 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)
Jonathan Hart828908c2020-04-15 14:23:45 -070084 logger.Debugw("packet-in received", log.Fields{"packet-in": js})
David K. Bainbridge157bdab2020-01-16 14:38:05 -080085 }
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()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -080096 var fields []goloxi.IOxm
David K. Bainbridge157bdab2020-01-16 14:38:05 -080097 for _, oxmField := range inMatch.GetOxmFields() {
David K. Bainbridge157bdab2020-01-16 14:38:05 -080098 field := oxmField.GetField()
99 ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800100 switch ofbField.Type {
101 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT:
102 ofpInPort := ofp.NewOxmInPort()
103 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port)
104 ofpInPort.Value = ofp.Port(val.Port)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800105 fields = append(fields, ofpInPort)
106 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE:
107 ofpEthType := ofp.NewOxmEthType()
108 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType)
109 ofpEthType.Value = ofp.EthernetType(val.EthType)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800110 fields = append(fields, ofpEthType)
111 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT:
112 ofpInPhyPort := ofp.NewOxmInPhyPort()
113 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort)
114 ofpInPhyPort.Value = ofp.Port(val.PhysicalPort)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800115 fields = append(fields, ofpInPhyPort)
116 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO:
117 ofpIpProto := ofp.NewOxmIpProto()
118 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto)
119 ofpIpProto.Value = ofp.IpPrototype(val.IpProto)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800120 fields = append(fields, ofpIpProto)
121 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC:
122 ofpUdpSrc := ofp.NewOxmUdpSrc()
123 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc)
124 ofpUdpSrc.Value = uint16(val.UdpSrc)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800125 fields = append(fields, ofpUdpSrc)
126 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST:
127 ofpUdpDst := ofp.NewOxmUdpDst()
128 val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst)
129 ofpUdpDst.Value = uint16(val.UdpDst)
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800130 fields = append(fields, ofpUdpDst)
131 case voltha.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
132 ofpVlanVid := ofp.NewOxmVlanVid()
133 val := ofbField.GetValue()
134 if val != nil {
135 vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid)
136 ofpVlanVid.Value = uint16(vlanId.VlanVid) + 0x1000
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800137 } else {
138 ofpVlanVid.Value = uint16(0)
139 }
140
141 fields = append(fields, ofpVlanVid)
142 default:
143 logger.Warnw("receive-packet-in:unhandled-oxm-field",
144 log.Fields{"field": ofbField.Type})
145 }
146 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800147
148 match.SetOxmList(fields)
149
150 ofPacketIn.SetMatch(*match)
151 ofPacketIn.SetReason(uint8(packetIn.GetReason()))
152 ofPacketIn.SetTableId(uint8(packetIn.GetTableId()))
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800153 ofc := ofa.getOFClient(deviceID)
David K. Bainbridgecac73ac2020-02-19 07:00:12 -0800154 if err := ofc.SendMessage(ofPacketIn); err != nil {
155 logger.Errorw("send-message-failed", log.Fields{
156 "device-id": deviceID,
157 "error": err})
158 }
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800159
160 }
161 }
David K. Bainbridge9cb404e2020-01-28 14:32:29 -0800162 logger.Debug("handle-packets-in-finished")
David K. Bainbridge157bdab2020-01-16 14:38:05 -0800163}