| /* |
| Copyright 2017 the original author or authors. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| package grpc |
| |
| import ( |
| "context" |
| "encoding/json" |
| |
| "github.com/donNewtonAlpha/goloxi" |
| ofp "github.com/donNewtonAlpha/goloxi/of13" |
| "github.com/golang/protobuf/ptypes/empty" |
| "github.com/opencord/ofagent-go/openflow" |
| "github.com/opencord/ofagent-go/settings" |
| l "github.com/opencord/voltha-lib-go/v2/pkg/log" |
| "github.com/opencord/voltha-protos/v2/go/openflow_13" |
| pb "github.com/opencord/voltha-protos/v2/go/voltha" |
| "google.golang.org/grpc" |
| ) |
| |
| func receivePacketIn(client pb.VolthaServiceClient) { |
| if settings.GetDebug(grpcDeviceID) { |
| logger.Debugln("Starting ReceivePacketIn Stream") |
| } |
| opt := grpc.EmptyCallOption{} |
| stream, err := client.ReceivePacketsIn(context.Background(), &empty.Empty{}, opt) |
| if err != nil { |
| logger.Fatalw("Unable to establish PacketIn stream", l.Fields{"Error": err}) |
| } |
| for { |
| packet, err := stream.Recv() |
| packetIn := packet.GetPacketIn() |
| |
| if err != nil { |
| logger.Fatalw("ReceivePacketIn unable to receive packet", l.Fields{"Error": err}) |
| } |
| if settings.GetDebug(grpcDeviceID) { |
| js, _ := json.Marshal(packetIn) |
| logger.Debugw("ReceivePacketIn Recieved", l.Fields{"PacketIn": js}) |
| } |
| deviceID := packet.GetId() |
| ofPacketIn := ofp.NewPacketIn() |
| ofPacketIn.SetVersion(uint8(4)) |
| ofPacketIn.SetXid(openflow.GetXid()) |
| ofPacketIn.SetBufferId(packetIn.GetBufferId()) |
| ofPacketIn.SetCookie(packetIn.GetCookie()) |
| ofPacketIn.SetData(packetIn.GetData()) |
| match := ofp.NewMatchV3() |
| inMatch := packetIn.GetMatch() |
| match.SetType(uint16(inMatch.GetType())) |
| oxFields := inMatch.GetOxmFields() |
| var fields []goloxi.IOxm |
| var size uint16 |
| size = 4 |
| for i := 0; i < len(oxFields); i++ { |
| oxmField := oxFields[i] |
| field := oxmField.GetField() |
| ofbField := field.(*openflow_13.OfpOxmField_OfbField).OfbField |
| size += 4 //header for oxm |
| switch ofbField.Type { |
| case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PORT: |
| ofpInPort := ofp.NewOxmInPort() |
| val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_Port) |
| ofpInPort.Value = ofp.Port(val.Port) |
| size += 4 |
| fields = append(fields, ofpInPort) |
| case pb.OxmOfbFieldTypes_OFPXMT_OFB_ETH_TYPE: |
| ofpEthType := ofp.NewOxmEthType() |
| val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_EthType) |
| ofpEthType.Value = ofp.EthernetType(val.EthType) |
| size += 2 |
| fields = append(fields, ofpEthType) |
| case pb.OxmOfbFieldTypes_OFPXMT_OFB_IN_PHY_PORT: |
| ofpInPhyPort := ofp.NewOxmInPhyPort() |
| val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_PhysicalPort) |
| ofpInPhyPort.Value = ofp.Port(val.PhysicalPort) |
| size += 4 |
| fields = append(fields, ofpInPhyPort) |
| case pb.OxmOfbFieldTypes_OFPXMT_OFB_IP_PROTO: |
| ofpIpProto := ofp.NewOxmIpProto() |
| val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_IpProto) |
| ofpIpProto.Value = ofp.IpPrototype(val.IpProto) |
| size += 1 |
| fields = append(fields, ofpIpProto) |
| case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_SRC: |
| ofpUdpSrc := ofp.NewOxmUdpSrc() |
| val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpSrc) |
| ofpUdpSrc.Value = uint16(val.UdpSrc) |
| size += 2 |
| fields = append(fields, ofpUdpSrc) |
| case pb.OxmOfbFieldTypes_OFPXMT_OFB_UDP_DST: |
| ofpUdpDst := ofp.NewOxmUdpDst() |
| val := ofbField.GetValue().(*openflow_13.OfpOxmOfbField_UdpDst) |
| ofpUdpDst.Value = uint16(val.UdpDst) |
| size += 2 |
| fields = append(fields, ofpUdpDst) |
| case pb.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID: |
| ofpVlanVid := ofp.NewOxmVlanVid() |
| val := ofbField.GetValue() |
| if val != nil { |
| vlanId := val.(*openflow_13.OfpOxmOfbField_VlanVid) |
| ofpVlanVid.Value = uint16(vlanId.VlanVid) + 0x1000 |
| size += 2 |
| } else { |
| ofpVlanVid.Value = uint16(0) |
| } |
| |
| fields = append(fields, ofpVlanVid) |
| default: |
| logger.Warnw("receivePacketIn Unhandled OxmField ", l.Fields{"Field": ofbField.Type}) |
| } |
| } |
| match.SetLength(size) |
| |
| match.SetOxmList(fields) |
| |
| ofPacketIn.SetMatch(*match) |
| ofPacketIn.SetReason(uint8(packetIn.GetReason())) |
| ofPacketIn.SetTableId(uint8(packetIn.GetTableId())) |
| ofPacketIn.SetTotalLen(uint16(len(ofPacketIn.GetData()))) |
| openFlowClient := GetClient(deviceID) |
| openFlowClient.SendMessage(ofPacketIn) |
| |
| } |
| |
| } |