blob: 9f8b035624547153aadeb1a4cd28d0a158cff70b [file] [log] [blame]
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001/*
2 * Copyright 2018-present Open Networking Foundation
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 dhcp
18
19import (
Matteo Scandolo40e067f2019-10-16 16:59:41 -070020 "context"
Matteo Scandolo8d281372020-09-03 16:23:37 -070021 "encoding/hex"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070022 "errors"
23 "fmt"
Shrey Baid688b4242020-07-10 20:40:10 +053024 "net"
25 "reflect"
26 "strconv"
27
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070028 "github.com/google/gopacket"
29 "github.com/google/gopacket/layers"
30 "github.com/looplab/fsm"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070031 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070032 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080033 "github.com/opencord/voltha-protos/v2/go/openolt"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070034 log "github.com/sirupsen/logrus"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070035)
36
37var dhcpLogger = log.WithFields(log.Fields{
38 "module": "DHCP",
39})
40
41var defaultParamsRequestList = []layers.DHCPOpt{
42 layers.DHCPOptSubnetMask,
43 layers.DHCPOptBroadcastAddr,
44 layers.DHCPOptTimeOffset,
45 layers.DHCPOptRouter,
46 layers.DHCPOptDomainName,
47 layers.DHCPOptDNS,
48 layers.DHCPOptDomainSearch,
49 layers.DHCPOptHostname,
50 layers.DHCPOptNetBIOSTCPNS,
51 layers.DHCPOptNetBIOSTCPScope,
52 layers.DHCPOptInterfaceMTU,
53 layers.DHCPOptClasslessStaticRoute,
54 layers.DHCPOptNTPServers,
55}
56
Matteo Scandolo378b8c92020-04-16 14:34:22 -070057func createDefaultDHCPReq(oltId int, intfId uint32, onuId uint32, mac net.HardwareAddr) layers.DHCPv4 {
Matteo Scandolofe9ac252019-10-25 11:40:17 -070058 // NOTE we want to generate a unique XID, the easiest way is to concat the PON ID and the ONU ID
59 // we increment them by one otherwise:
Matteo Scandolo378b8c92020-04-16 14:34:22 -070060 // - OLT: 0 PON: 0 ONU: 62 = 062 -> 62
61 // - OLT: 0 PON: 6 ONU: 2 = 62 -> 62
62 xid, err := strconv.Atoi(fmt.Sprintf("%d%d%d", oltId+1, intfId+1, onuId+1))
Matteo Scandolofe9ac252019-10-25 11:40:17 -070063 if err != nil {
64 log.Fatal("Can't generate unique XID for ONU")
65 }
66
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070067 return layers.DHCPv4{
68 Operation: layers.DHCPOpRequest,
69 HardwareType: layers.LinkTypeEthernet,
70 HardwareLen: 6,
71 HardwareOpts: 0,
Matteo Scandolofe9ac252019-10-25 11:40:17 -070072 Xid: uint32(xid),
Matteo Scandolo40e067f2019-10-16 16:59:41 -070073 ClientHWAddr: mac,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070074 }
75}
76
Matteo Scandolofe9ac252019-10-25 11:40:17 -070077func createDefaultOpts(intfId uint32, onuId uint32) []layers.DHCPOption {
78 hostname := []byte(fmt.Sprintf("%d.%d.bbsim.onf.org", intfId, onuId))
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070079 opts := []layers.DHCPOption{}
80 opts = append(opts, layers.DHCPOption{
81 Type: layers.DHCPOptHostname,
82 Data: hostname,
83 Length: uint8(len(hostname)),
84 })
85
86 bytes := []byte{}
87 for _, option := range defaultParamsRequestList {
88 bytes = append(bytes, byte(option))
89 }
90
91 opts = append(opts, layers.DHCPOption{
92 Type: layers.DHCPOptParamsRequest,
93 Data: bytes,
94 Length: uint8(len(bytes)),
95 })
96 return opts
97}
98
Matteo Scandolo4a036262020-08-17 15:56:13 -070099func createDHCPDisc(oltId int, intfId uint32, onuId uint32, gemPort uint32, macAddress net.HardwareAddr) *layers.DHCPv4 {
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700100 dhcpLayer := createDefaultDHCPReq(oltId, intfId, onuId, macAddress)
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700101 defaultOpts := createDefaultOpts(intfId, onuId)
Shrey Baid688b4242020-07-10 20:40:10 +0530102 dhcpLayer.Options = append([]layers.DHCPOption{{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700103 Type: layers.DHCPOptMessageType,
104 Data: []byte{byte(layers.DHCPMsgTypeDiscover)},
105 Length: 1,
106 }}, defaultOpts...)
107
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700108 data := []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700109 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, byte(intfId), byte(onuId), byte(gemPort)} //FIXME use the OLT-ID in here
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700110 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
111 Type: layers.DHCPOptClientID,
112 Data: data,
113 Length: uint8(len(data)),
114 })
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700115
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700116 return &dhcpLayer
117}
118
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700119func createDHCPReq(oltId int, intfId uint32, onuId uint32, macAddress net.HardwareAddr, offeredIp net.IP) *layers.DHCPv4 {
120 dhcpLayer := createDefaultDHCPReq(oltId, intfId, onuId, macAddress)
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700121 defaultOpts := createDefaultOpts(intfId, onuId)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700122
123 dhcpLayer.Options = append(defaultOpts, layers.DHCPOption{
124 Type: layers.DHCPOptMessageType,
125 Data: []byte{byte(layers.DHCPMsgTypeRequest)},
126 Length: 1,
127 })
128
129 data := []byte{182, 21, 0, 128}
130 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
131 Type: layers.DHCPOptServerID,
132 Data: data,
133 Length: uint8(len(data)),
134 })
135
136 data = []byte{0xcd, 0x28, 0xcb, 0xcc, 0x00, 0x01, 0x00, 0x01,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700137 0x23, 0xed, 0x11, 0xec, 0x4e, 0xfc, 0xcd, 0x28, byte(intfId), byte(onuId)}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700138 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
139 Type: layers.DHCPOptClientID,
140 Data: data,
141 Length: uint8(len(data)),
142 })
143
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700144 // NOTE we should not request a specific IP, or we should request the one that has been offered
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700145 dhcpLayer.Options = append(dhcpLayer.Options, layers.DHCPOption{
146 Type: layers.DHCPOptRequestIP,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700147 Data: offeredIp,
148 Length: uint8(len(offeredIp)),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700149 })
150 return &dhcpLayer
151}
152
Matteo Scandolo8d281372020-09-03 16:23:37 -0700153func serializeDHCPPacket(intfId uint32, onuId uint32, cTag int, srcMac net.HardwareAddr, dhcp *layers.DHCPv4, pbit uint8) ([]byte, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700154 buffer := gopacket.NewSerializeBuffer()
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800155
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700156 options := gopacket.SerializeOptions{
157 ComputeChecksums: true,
158 FixLengths: true,
159 }
160
161 ethernetLayer := &layers.Ethernet{
162 SrcMAC: srcMac,
163 DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
164 EthernetType: layers.EthernetTypeIPv4,
165 }
166
167 ipLayer := &layers.IPv4{
168 Version: 4,
169 TOS: 0x10,
170 TTL: 128,
171 SrcIP: []byte{0, 0, 0, 0},
172 DstIP: []byte{255, 255, 255, 255},
173 Protocol: layers.IPProtocolUDP,
174 }
175
176 udpLayer := &layers.UDP{
177 SrcPort: 68,
178 DstPort: 67,
179 }
180
Shrey Baid688b4242020-07-10 20:40:10 +0530181 _ = udpLayer.SetNetworkLayerForChecksum(ipLayer)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700182 if err := gopacket.SerializeLayers(buffer, options, ethernetLayer, ipLayer, udpLayer, dhcp); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800183 dhcpLogger.Error("SerializeLayers")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700184 return nil, err
185 }
186
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800187 untaggedPkt := gopacket.NewPacket(buffer.Bytes(), layers.LayerTypeEthernet, gopacket.Default)
188
Matteo Scandolo8d281372020-09-03 16:23:37 -0700189 taggedPkt, err := packetHandlers.PushSingleTag(cTag, untaggedPkt, pbit)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800190 if err != nil {
191 dhcpLogger.Error("TagPacket")
192 return nil, err
193 }
194
195 return gopacket.Payload(taggedPkt.Data()), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700196}
197
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700198func GetDhcpLayer(pkt gopacket.Packet) (*layers.DHCPv4, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700199 layerDHCP := pkt.Layer(layers.LayerTypeDHCPv4)
200 dhcp, _ := layerDHCP.(*layers.DHCPv4)
201 if dhcp == nil {
202 return nil, errors.New("Failed-to-extract-DHCP-layer")
203 }
204 return dhcp, nil
205}
206
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700207func GetDhcpMessageType(dhcp *layers.DHCPv4) (layers.DHCPMsgType, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700208 for _, option := range dhcp.Options {
209 if option.Type == layers.DHCPOptMessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700210 if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeDiscover)}) {
211 return layers.DHCPMsgTypeDiscover, nil
212 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeOffer)}) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700213 return layers.DHCPMsgTypeOffer, nil
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700214 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRequest)}) {
215 return layers.DHCPMsgTypeRequest, nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700216 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeAck)}) {
217 return layers.DHCPMsgTypeAck, nil
218 } else if reflect.DeepEqual(option.Data, []byte{byte(layers.DHCPMsgTypeRelease)}) {
219 return layers.DHCPMsgTypeRelease, nil
220 } else {
221 msg := fmt.Sprintf("This type %x is not supported", option.Data)
222 return 0, errors.New(msg)
223 }
224 }
225 }
226 return 0, errors.New("Failed to extract MsgType from dhcp")
227}
228
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700229// returns the DHCP Layer type or error if it's not a DHCP Packet
230func GetDhcpPacketType(pkt gopacket.Packet) (string, error) {
231 dhcpLayer, err := GetDhcpLayer(pkt)
232 if err != nil {
233 return "", err
234 }
235 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
236 if err != nil {
237 return "", err
238 }
239
240 return dhcpMessageType.String(), nil
241}
242
Matteo Scandolo4a036262020-08-17 15:56:13 -0700243func sendDHCPPktIn(msg bbsim.ByteMsg, portNo uint32, gemPortId uint32, stream bbsim.Stream) error {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700244
Matteo Scandolo8d281372020-09-03 16:23:37 -0700245 dhcpLogger.WithFields(log.Fields{
Shrey Baid688b4242020-07-10 20:40:10 +0530246 "OnuId": msg.OnuId,
247 "IntfId": msg.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700248 "GemPort": gemPortId,
Shrey Baid688b4242020-07-10 20:40:10 +0530249 "Type": "DHCP",
Matteo Scandolo8d281372020-09-03 16:23:37 -0700250 "Pkt": hex.EncodeToString(msg.Bytes),
251 }).Trace("Sending DHCP packet in")
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700252
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700253 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
Matteo Scandolo27428702019-10-11 16:21:16 -0700254 IntfType: "pon",
255 IntfId: msg.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700256 GemportId: gemPortId,
Matteo Scandolo27428702019-10-11 16:21:16 -0700257 Pkt: msg.Bytes,
258 PortNo: portNo,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700259 }}
260
261 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
262 dhcpLogger.Errorf("Fail to send DHCP PktInd indication. %v", err)
263 return err
264 }
265 return nil
266}
267
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700268func sendDHCPRequest(oltId int, ponPortId uint32, onuId uint32, serviceName string, serialNumber string, portNo uint32,
Matteo Scandolo8d281372020-09-03 16:23:37 -0700269 cTag int, gemPortId uint32, onuStateMachine *fsm.FSM, onuHwAddress net.HardwareAddr,
270 offeredIp net.IP, pbit uint8, stream bbsim.Stream) error {
Matteo Scandolo378b8c92020-04-16 14:34:22 -0700271 dhcp := createDHCPReq(oltId, ponPortId, onuId, onuHwAddress, offeredIp)
Matteo Scandolo8d281372020-09-03 16:23:37 -0700272 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp, pbit)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700273
274 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700275 dhcpLogger.WithFields(log.Fields{
276 "OnuId": onuId,
277 "IntfId": ponPortId,
278 "OnuSn": serialNumber,
279 "OfferedIp": offeredIp.String(),
280 }).Errorf("Cannot serializeDHCPPacket: %s", err)
281 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
282 return err
283 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700284 return err
285 }
286 // NOTE I don't think we need to tag the packet
287 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
288
289 msg := bbsim.ByteMsg{
290 IntfId: ponPortId,
291 OnuId: onuId,
292 Bytes: pkt,
293 }
294
Matteo Scandolo4a036262020-08-17 15:56:13 -0700295 if err := sendDHCPPktIn(msg, portNo, gemPortId, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700296 dhcpLogger.WithFields(log.Fields{
297 "OnuId": onuId,
298 "IntfId": ponPortId,
299 "OnuSn": serialNumber,
300 }).Errorf("Cannot sendDHCPPktIn: %s", err)
301 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
302 return err
303 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700304 return err
305 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700306
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700307 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700308 "OnuId": onuId,
309 "IntfId": ponPortId,
310 "OnuSn": serialNumber,
311 "OfferedIp": offeredIp.String(),
312 "ServiceName": serviceName,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700313 }).Infof("DHCPRequest Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700314 return nil
315}
316
Matteo Scandolo075b1892019-10-07 12:11:07 -0700317func updateDhcpFailed(onuId uint32, ponPortId uint32, serialNumber string, onuStateMachine *fsm.FSM) error {
318 if err := onuStateMachine.Event("dhcp_failed"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700319 dhcpLogger.WithFields(log.Fields{
320 "OnuId": onuId,
321 "IntfId": ponPortId,
322 "OnuSn": serialNumber,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700323 }).Errorf("Error while transitioning ONU State %v", err)
324 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700325 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700326 return nil
327}
328
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700329func SendDHCPDiscovery(oltId int, ponPortId uint32, onuId uint32, serviceName string, cTag int, gemPortId uint32,
Matteo Scandolo8d281372020-09-03 16:23:37 -0700330 serialNumber string, portNo uint32, stateMachine *fsm.FSM, onuHwAddress net.HardwareAddr,
331 pbit uint8, stream bbsim.Stream) error {
332
Matteo Scandolo4a036262020-08-17 15:56:13 -0700333 dhcp := createDHCPDisc(oltId, ponPortId, onuId, gemPortId, onuHwAddress)
Matteo Scandolo8d281372020-09-03 16:23:37 -0700334 pkt, err := serializeDHCPPacket(ponPortId, onuId, cTag, onuHwAddress, dhcp, pbit)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800335
Matteo Scandolo075b1892019-10-07 12:11:07 -0700336 if err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700337 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700338 "OnuId": onuId,
339 "IntfId": ponPortId,
340 "OnuSn": serialNumber,
341 "ServiceName": serviceName,
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700342 }).Errorf("Cannot serializeDHCPPacket: %s", err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700343 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, stateMachine); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700344 return err
345 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700346 return err
347 }
348 // NOTE I don't think we need to tag the packet
349 //taggedPkt, err := packetHandlers.PushSingleTag(cTag, pkt)
350
351 msg := bbsim.ByteMsg{
352 IntfId: ponPortId,
353 OnuId: onuId,
354 Bytes: pkt,
355 }
356
Matteo Scandolo4a036262020-08-17 15:56:13 -0700357 if err := sendDHCPPktIn(msg, portNo, gemPortId, stream); err != nil {
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700358 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700359 "OnuId": onuId,
360 "IntfId": ponPortId,
361 "OnuSn": serialNumber,
362 "ServiceName": serviceName,
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700363 }).Errorf("Cannot sendDHCPPktIn: %s", err)
Matteo Scandolo4a036262020-08-17 15:56:13 -0700364 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, stateMachine); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -0700365 return err
366 }
367 return err
368 }
369 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700370 "OnuId": onuId,
371 "IntfId": ponPortId,
372 "OnuSn": serialNumber,
373 "ServiceName": serviceName,
374 }).Info("DHCPDiscovery Sent")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700375
Matteo Scandolo4a036262020-08-17 15:56:13 -0700376 if err := stateMachine.Event("dhcp_discovery_sent"); err != nil {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700377 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700378 "OnuId": onuId,
379 "IntfId": ponPortId,
380 "OnuSn": serialNumber,
381 "ServiceName": serviceName,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700382 }).Errorf("Error while transitioning ONU State %v", err)
383 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700384 return nil
385}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700386
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700387func HandleNextPacket(oltId int, onuId uint32, ponPortId uint32, serviceName string, serialNumber string, portNo uint32,
Matteo Scandolo8d281372020-09-03 16:23:37 -0700388 cTag int, gemPortId uint32, onuHwAddress net.HardwareAddr, onuStateMachine *fsm.FSM,
389 pkt gopacket.Packet, pbit uint8, stream bbsim.Stream) error {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700390
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700391 dhcpLayer, err := GetDhcpLayer(pkt)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700392 if err != nil {
393 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700394 "OnuId": onuId,
395 "IntfId": ponPortId,
396 "OnuSn": serialNumber,
397 "ServiceName": serviceName,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700398 }).Errorf("Can't get DHCP Layer from Packet: %v", err)
399 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
400 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700401 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700402 return err
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700403 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700404 dhcpMessageType, err := GetDhcpMessageType(dhcpLayer)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700405 if err != nil {
406 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700407 "OnuId": onuId,
408 "IntfId": ponPortId,
409 "OnuSn": serialNumber,
410 "ServiceName": serviceName,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700411 }).Errorf("Can't get DHCP Message Type from DHCP Layer: %v", err)
412 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
413 return err
414 }
415 return err
416 }
417
418 if dhcpLayer.Operation == layers.DHCPOpReply {
419 if dhcpMessageType == layers.DHCPMsgTypeOffer {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700420 offeredIp := dhcpLayer.YourClientIP
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700421 if err := sendDHCPRequest(oltId, ponPortId, onuId, serviceName, serialNumber, portNo, cTag, gemPortId, onuStateMachine, onuHwAddress, offeredIp, pbit, stream); err != nil {
Matteo Scandolo075b1892019-10-07 12:11:07 -0700422 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700423 "OnuId": onuId,
424 "IntfId": ponPortId,
425 "OnuSn": serialNumber,
426 "ServiceName": serviceName,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700427 }).Errorf("Can't send DHCP Request: %s", err)
428 if err := updateDhcpFailed(onuId, ponPortId, serialNumber, onuStateMachine); err != nil {
429 return err
430 }
431 return err
432 }
433 if err := onuStateMachine.Event("dhcp_request_sent"); err != nil {
434 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700435 "OnuId": onuId,
436 "IntfId": ponPortId,
437 "OnuSn": serialNumber,
438 "ServiceName": serviceName,
439 }).Errorf("Error while transitioning State %v", err)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700440 }
441
442 } else if dhcpMessageType == layers.DHCPMsgTypeAck {
443 // NOTE once the ack is received we don't need to do anything but change the state
444 if err := onuStateMachine.Event("dhcp_ack_received"); err != nil {
445 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700446 "OnuId": onuId,
447 "IntfId": ponPortId,
448 "OnuSn": serialNumber,
449 "ServiceName": serviceName,
450 }).Errorf("Error while transitioning State %v", err)
Matteo Scandolo075b1892019-10-07 12:11:07 -0700451 }
452 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700453 "OnuId": onuId,
454 "IntfId": ponPortId,
455 "OnuSn": serialNumber,
456 "ServiceName": serviceName,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700457 }).Infof("DHCP State machine completed")
458 }
459 // NOTE do we need to care about DHCPMsgTypeRelease??
460 } else {
461 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700462 "OnuId": onuId,
463 "IntfId": ponPortId,
464 "OnuSn": serialNumber,
465 "ServiceName": serviceName,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700466 }).Warnf("Unsupported DHCP Operation: %s", dhcpLayer.Operation.String())
467 }
Matteo Scandolofe9ac252019-10-25 11:40:17 -0700468
Matteo Scandolo075b1892019-10-07 12:11:07 -0700469 return nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700470}
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700471
472// This method handle the BBR DHCP Packets
473// BBR does not need to do anything but forward the packets in the correct direction
Matteo Scandolo4a036262020-08-17 15:56:13 -0700474func HandleNextBbrPacket(onuId uint32, ponPortId uint32, serialNumber string, doneChannel chan bool, pkt gopacket.Packet, client openolt.OpenoltClient) error {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700475
476 // check if the packet is going:
477 // - outgouing: toward the DHCP
478 // - incoming: toward the ONU
479 isIncoming := packetHandlers.IsIncomingPacket(pkt)
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800480 dhcpLogger.Tracef("Is Incoming: %t", isIncoming)
481
482 pkt, err := packetHandlers.PopSingleTag(pkt)
483 if err != nil {
484 dhcpLogger.WithFields(log.Fields{
485 "OnuId": onuId,
486 "IntfId": ponPortId,
487 "OnuSn": serialNumber,
488 "error": err,
489 }).Fatalf("Can't untag packet")
490 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700491
492 dhcpType, err := GetDhcpPacketType(pkt)
493 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800494 dhcpLogger.WithFields(log.Fields{
495 "OnuId": onuId,
496 "IntfId": ponPortId,
497 "OnuSn": serialNumber,
498 "error": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700499 }).Fatalf("Can't find DHCP type for packet")
500 }
501
502 srcMac, _ := packetHandlers.GetSrcMacAddressFromPacket(pkt)
503 dstMac, _ := packetHandlers.GetDstMacAddressFromPacket(pkt)
504
Shrey Baid688b4242020-07-10 20:40:10 +0530505 if isIncoming {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700506
507 onuPacket := openolt.OnuPacket{
508 IntfId: ponPortId,
509 OnuId: onuId,
510 PortNo: onuId,
511 GemportId: 1,
512 Pkt: pkt.Data(),
513 }
514
515 if _, err := client.OnuPacketOut(context.Background(), &onuPacket); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800516 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700517 "OnuId": onuId,
518 "IntfId": ponPortId,
519 "OnuSn": serialNumber,
520 "Type": dhcpType,
521 "error": err,
522 }).Error("Failed to send DHCP packet to the ONU")
523 }
524
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800525 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700526 "OnuId": onuId,
527 "IntfId": ponPortId,
528 "OnuSn": serialNumber,
529 "Type": dhcpType,
530 "DstMac": dstMac,
531 "SrcMac": srcMac,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700532 }).Infof("Sent DHCP packet to the ONU")
533
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700534 dhcpLayer, _ := GetDhcpLayer(pkt)
535 dhcpMessageType, _ := GetDhcpMessageType(dhcpLayer)
536 if dhcpMessageType == layers.DHCPMsgTypeAck {
537 doneChannel <- true
538 }
539
540 } else {
541 // double tag the packet and send it to the NNI
Matteo Scandolo4a036262020-08-17 15:56:13 -0700542 // we don't really care about the tags as they are stripped before
543 // the packet is sent to the DHCP server
Matteo Scandolo8d281372020-09-03 16:23:37 -0700544 // in BBR we don't care about the pBit
545 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(900, 900, pkt, 0)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700546 if err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800547 dhcpLogger.WithFields(log.Fields{
548 "OnuId": onuId,
549 "IntfId": ponPortId,
550 "OnuSn": serialNumber,
551 "Type": dhcpType,
552 "error": err,
553 }).Error("Failed to add double tag to packet")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700554 }
555
556 pkt := openolt.UplinkPacket{
557 IntfId: 0, // BBSim does not care about which NNI, it has only one
558 Pkt: doubleTaggedPkt.Data(),
559 }
560 if _, err := client.UplinkPacketOut(context.Background(), &pkt); err != nil {
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800561 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700562 "OnuId": onuId,
563 "IntfId": ponPortId,
564 "OnuSn": serialNumber,
565 "Type": dhcpType,
566 "error": err,
567 }).Error("Failed to send DHCP packet out of the NNI Port")
568 }
Matteo Scandoloe0e9b772020-02-03 14:23:43 -0800569 dhcpLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700570 "OnuId": onuId,
571 "IntfId": ponPortId,
572 "OnuSn": serialNumber,
573 "Type": dhcpType,
574 "DstMac": dstMac,
575 "SrcMac": srcMac,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700576 }).Infof("Sent DHCP packet out of the NNI Port")
577 }
578 return nil
579}