blob: 7067b3fba54101d856dfb8ecf80c7f39cffe515e [file] [log] [blame]
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +09001/*
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 core
18
19import (
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +090020 "errors"
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +090021 "gerrit.opencord.org/voltha-bbsim/device"
22 "gerrit.opencord.org/voltha-bbsim/protos"
23 "gerrit.opencord.org/voltha-bbsim/setup"
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +090024 "github.com/google/gopacket"
25 "github.com/google/gopacket/layers"
26 "github.com/google/gopacket/pcap"
27 "google.golang.org/grpc"
28 "log"
29 "strconv"
30 "sync"
31 "time"
32)
33
34type Mode int
35
36const MAX_ONUS_PER_PON = 64 // This value should be the same with the value in AdapterPlatrorm class
37
38const (
39 DEFAULT Mode = iota
40 AAA
41 BOTH
42)
43
44type Server struct {
45 Olt *device.Olt
46 Onumap map[uint32][]*device.Onu
47 Ioinfos []*Ioinfo
48 Endchan chan int
49 Mode Mode
50 AAAWait int
51 DhcpWait int
52 DhcpServerIP string
53 gRPCserver *grpc.Server
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +090054 VethEnv []string
55 TestFlag bool
56 Processes []string
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +090057}
58
59type Packet struct {
60 Info *Ioinfo
61 Pkt gopacket.Packet
62}
63
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +090064func (s *Server)Initialize(){
65 s.VethEnv = []string{}
66 s.Endchan = make(chan int)
67 s.TestFlag = false
68 s.Processes = []string{}
69 s.Ioinfos = []*Ioinfo{}
70}
71
72func Create(oltid uint32, npon uint32, nonus uint32, aaawait int, dhcpwait int, ip string, g *grpc.Server, mode Mode, e chan int) *Server {
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +090073 s := new(Server)
74 s.Olt = device.CreateOlt(oltid, npon, 1)
75 nnni := s.Olt.NumNniIntf
76 log.Printf("OLT ID: %d was retrieved.\n", s.Olt.ID)
77 s.Onumap = make(map[uint32][]*device.Onu)
78 s.AAAWait = aaawait
79 s.DhcpWait = dhcpwait
80 s.DhcpServerIP = ip
81 s.gRPCserver = g
82 s.Mode = mode
83 s.Endchan = e
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +090084 s.VethEnv = []string{}
85 s.TestFlag = false
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +090086 for intfid := nnni; intfid < npon+nnni; intfid++ {
87 s.Onumap[intfid] = device.CreateOnus(oltid, intfid, nonus, nnni)
88 }
89 return s
90}
91
92func (s *Server) activateOLT(stream openolt.Openolt_EnableIndicationServer) error {
93 // Activate OLT
94 olt := s.Olt
95 oltid := olt.ID
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +090096 wg := &sync.WaitGroup{}
97
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +090098 // DEBUG
99 log.Printf("pointer@activateOLT %p", s)
100 log.Printf("Ioinfos:%v\n", s.Ioinfos)
101 log.Printf("OLT Status:%v\n", s.Olt.OperState)
102 log.Printf("ONUmap:%v\n", s.Onumap)
103 log.Printf("VethEnv:%v\n", s.VethEnv)
104 log.Printf("Processes:%v\n", s.Processes)
105
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900106 if err := sendOltInd(stream, olt); err != nil {
107 return err
108 }
109 olt.OperState = "up"
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900110 *olt.InternalState = device.OLT_UP
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900111 log.Printf("OLT %s sent OltInd.\n", olt.Name)
112
113 // OLT sends Interface Indication to Adapter
114 if err := sendIntfInd(stream, olt); err != nil {
115 log.Printf("[ERROR] Fail to sendIntfInd: %v\n", err)
116 return err
117 }
118 log.Printf("OLT %s sent IntfInd.\n", olt.Name)
119
120 // OLT sends Operation Indication to Adapter after activating each interface
121 //time.Sleep(IF_UP_TIME * time.Second)
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900122 *olt.InternalState = device.PONIF_UP
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900123 if err := sendOperInd(stream, olt); err != nil {
124 log.Printf("[ERROR] Fail to sendOperInd: %v\n", err)
125 return err
126 }
127 log.Printf("OLT %s sent OperInd.\n", olt.Name)
128
129 // OLT sends ONU Discover Indication to Adapter after ONU discovery
130 for intfid, _ := range s.Onumap {
131 device.UpdateOnusOpStatus(intfid, s.Onumap[intfid], "up")
132 }
133
134 for intfid, _ := range s.Onumap {
135 sendOnuDiscInd(stream, s.Onumap[intfid])
136 log.Printf("OLT id:%d sent ONUDiscInd.\n", olt.ID)
137 }
138
139 // OLT Sends OnuInd after waiting all of those ONUs up
140 for {
141 if s.IsAllONUActive() {
142 break
143 }
144 }
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900145
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900146 for intfid, _ := range s.Onumap {
147 sendOnuInd(stream, s.Onumap[intfid])
148 log.Printf("OLT id:%d sent ONUInd.\n", olt.ID)
149 }
150
151 if s.Mode == DEFAULT {
152 //EnableIndication's stream should be kept even after activateOLT() is finished.
153 //Otherwise, OpenOLT adapter sends EnableIndication again.
154 <-s.Endchan
155 log.Println("core server thread receives close !")
156 } else if s.Mode == AAA || s.Mode == BOTH {
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900157 s.TestFlag = true
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900158 var err error
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900159 s.Ioinfos, s.VethEnv, err = createIoinfos(oltid, s.VethEnv, s.Onumap)
160 log.Println("s.VethEnv", s.VethEnv)
161 if err != nil {
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900162 return err
163 }
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900164
165 errchan := make(chan error)
166 go func() {
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900167 <- errchan
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900168 close(s.Endchan)
169 }()
170
171 wg.Add(1)
172 go func() {
173 defer func() {
174 log.Println("runPacketInDaemon Done")
175 wg.Done()
176 }()
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900177
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900178 err := s.runPacketInDaemon(stream)
179 if err != nil {
180 errchan <- err
181 return
182 }
183 }()
184
185 wg.Add(1)
186 go func() {
187 defer func() {
188 log.Println("exeAAATest Done")
189 wg.Done()
190 }()
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900191
192 err = s.exeAAATest()
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900193 if err != nil {
194 errchan <- err
195 return
196 }
Keita NISHIMOTOc864da22018-10-15 22:41:42 +0900197
198 if s.Mode == BOTH {
199 go func() {
200 defer func() {
201 log.Println("exeDHCPTest Done")
202 }()
Keita NISHIMOTOc864da22018-10-15 22:41:42 +0900203
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900204 err := s.exeDHCPTest()
Keita NISHIMOTOc864da22018-10-15 22:41:42 +0900205 if err != nil {
206 errchan <- err
207 return
208 }
209 }()
210 }
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900211 }()
212 wg.Wait()
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900213 cleanUpVeths(s.VethEnv) // Grace teardown
214 pnames := s.Processes
215 killProcesses(pnames)
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900216 log.Println("Grace shutdown down")
217 }
218 return nil
219}
220
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900221func createIoinfos(oltid uint32, vethenv []string, onumap map[uint32][]*device.Onu)([]*Ioinfo, []string, error){
222 ioinfos := []*Ioinfo{}
223 var err error
224 for intfid, _ := range onumap {
225 for i := 0; i < len(onumap[intfid]); i++ {
226 var handler *pcap.Handle
227 onuid := onumap[intfid][i].OnuID
228 uniup, unidw := makeUniName(oltid, intfid, onuid)
229 if handler, vethenv, err = setupVethHandler(uniup, unidw, vethenv); err != nil {
230 return ioinfos, vethenv, err
231 }
232 iinfo := Ioinfo{name: uniup, iotype: "uni", ioloc: "inside", intfid: intfid, onuid: onuid, handler: handler}
233 ioinfos = append(ioinfos, &iinfo)
234 oinfo := Ioinfo{name: unidw, iotype: "uni", ioloc: "outside", intfid: intfid, onuid: onuid, handler: nil}
235 ioinfos = append(ioinfos, &oinfo)
236 }
237 }
238
239 var handler *pcap.Handle
240 nniup, nnidw := makeNniName(oltid)
241 if handler, vethenv, err = setupVethHandler(nniup, nnidw, vethenv); err != nil {
242 return ioinfos, vethenv, err
243 }
244 //TODO: Intfid should be modified
245 iinfo := Ioinfo{name: nnidw, iotype: "nni", ioloc: "inside", intfid: 1, handler: handler}
246 ioinfos = append(ioinfos, &iinfo)
247 oinfo := Ioinfo{name: nniup, iotype: "nni", ioloc: "outside", intfid: 1, handler: nil}
248 ioinfos = append(ioinfos, &oinfo)
249 return ioinfos, vethenv, nil
250}
251
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900252func (s *Server) runPacketInDaemon(stream openolt.Openolt_EnableIndicationServer) error {
253 log.Println("runPacketInDaemon Start")
254 unichannel := make(chan Packet, 2048)
255 flag := false
256
257 for intfid, _ := range s.Onumap {
258 for _, onu := range s.Onumap[intfid] { //TODO: should be updated for multiple-Interface
259 onuid := onu.OnuID
260 ioinfo, err := s.identifyUniIoinfo("inside", intfid, onuid)
261 if err != nil {
262 log.Printf("[ERROR] Fail to identifyUniIoinfo (onuid: %d): %v\n", onuid, err)
263 return err
264 }
265 uhandler := ioinfo.handler
266 defer uhandler.Close()
267 go RecvWorker(ioinfo, uhandler, unichannel)
268 }
269 }
270
271 ioinfo, err := s.identifyNniIoinfo("inside")
272 if err != nil {
273 return err
274 }
275 nhandler := ioinfo.handler
276 defer nhandler.Close()
277 nnichannel := make(chan Packet, 32)
278 go RecvWorker(ioinfo, nhandler, nnichannel)
279
280 data := &openolt.Indication_PktInd{}
281 for {
282 select {
283 case unipkt := <-unichannel:
284 log.Println("Received packet in grpc Server from UNI.")
285 if unipkt.Info == nil || unipkt.Info.iotype != "uni" {
286 log.Println("[WARNING] This packet does not come from UNI !")
287 continue
288 }
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900289
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900290 intfid := unipkt.Info.intfid
291 onuid := unipkt.Info.onuid
292 gemid, _ := getGemPortID(intfid, onuid)
293 pkt := unipkt.Pkt
294 layerEth := pkt.Layer(layers.LayerTypeEthernet)
295 le, _ := layerEth.(*layers.Ethernet)
296 ethtype := le.EthernetType
297 if ethtype == 0x888e {
298 log.Printf("Received upstream packet is EAPOL.")
299 log.Println(unipkt.Pkt.Dump())
300 log.Println(pkt.Dump())
301 } else if layerDHCP := pkt.Layer(layers.LayerTypeDHCPv4); layerDHCP != nil {
302 log.Printf("Received upstream packet is DHCP.")
303 log.Println(unipkt.Pkt.Dump())
304 log.Println(pkt.Dump())
305 } else {
306 continue
307 }
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900308
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900309 log.Printf("sendPktInd intfid:%d (onuid: %d) gemid:%d\n", intfid, onuid, gemid)
310 data = &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{IntfType: "pon", IntfId: intfid, GemportId: gemid, Pkt: pkt.Data()}}
311 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
312 log.Printf("[ERROR] Failed to send PktInd indication. %v\n", err)
313 return err
314 }
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900315
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900316 case nnipkt := <-nnichannel:
317 if nnipkt.Info == nil || nnipkt.Info.iotype != "nni" {
318 log.Println("[WARNING] This packet does not come from NNI !")
319 continue
320 }
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900321
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900322 log.Println("Received packet in grpc Server from NNI.")
323 intfid := nnipkt.Info.intfid
324 pkt := nnipkt.Pkt
325 log.Printf("sendPktInd intfid:%d\n", intfid)
326 data = &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{IntfType: "nni", IntfId: intfid, Pkt: pkt.Data()}}
327 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
328 log.Printf("[ERROR] Failed to send PktInd indication. %v\n", err)
329 return err
330 }
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900331
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900332 case <-s.Endchan:
333 if flag == false {
334 log.Println("PacketInDaemon thread receives close !")
335 close(unichannel)
336 log.Println("Closed unichannel !")
337 close(nnichannel)
338 log.Println("Closed nnichannel !")
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900339
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900340 flag = true
341 return nil
342 }
343 }
344 }
345 return nil
346}
347
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900348func (s *Server) exeAAATest() error {
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900349 log.Println("exeAAATest Start")
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900350 infos, err := s.getUniIoinfos("outside")
351 if err != nil {
352 return err
353 }
354
355 univeths := []string{}
356 for _, info := range infos {
357 univeths = append(univeths, info.name)
358 }
359
360 for {
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900361 select {
362 case <-s.Endchan:
363 log.Println("exeAAATest thread receives close !")
364 return nil
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900365 case <- time.After(time.Second * time.Duration(s.AAAWait)):
366 log.Println("timeout")
367 err = setup.ActivateWPASups(univeths)
368 if err != nil {
369 return err
370 }
371 s.Processes = append(s.Processes, "wpa_supplicant")
372 log.Println("s.Processes:", s.Processes)
373 return nil
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900374 }
375 }
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900376 return nil
377}
378
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900379func (s *Server) exeDHCPTest() error {
Keita NISHIMOTOc864da22018-10-15 22:41:42 +0900380 log.Println("exeDHCPTest Start")
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900381 info, err := s.identifyNniIoinfo("outside")
382
383 if err != nil {
384 return err
385 }
386
387 err = setup.ActivateDHCPServer(info.name, s.DhcpServerIP)
388 if err != nil {
389 return err
390 }
391 s.Processes = append(s.Processes, "dhcpd")
392
393 infos, err := s.getUniIoinfos("outside")
394 if err != nil {
395 return err
396 }
397
398 univeths := []string{}
399 for _, info := range infos {
400 univeths = append(univeths, info.name)
401 }
402
403 for {
Keita NISHIMOTOc864da22018-10-15 22:41:42 +0900404 select {
405 case <-s.Endchan:
406 log.Println("exeDHCPTest thread receives close !")
407 return nil
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900408 case <- time.After(time.Second * time.Duration(s.DhcpWait)):
409 log.Println("timeout")
410 err = setup.ActivateDHCPClients(univeths)
411 if err != nil {
412 return err
413 }
414 s.Processes = append(s.Processes, "dhclient")
415 log.Println("s.Processes:", s.Processes)
416 return nil
Keita NISHIMOTOc864da22018-10-15 22:41:42 +0900417 }
418 }
Keita NISHIMOTOc864da22018-10-15 22:41:42 +0900419 return nil
420}
421
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900422func (s *Server) onuPacketOut(intfid uint32, onuid uint32, rawpkt gopacket.Packet) error {
423 layerEth := rawpkt.Layer(layers.LayerTypeEthernet)
424 if layerEth != nil {
425 pkt, _ := layerEth.(*layers.Ethernet)
426 ethtype := pkt.EthernetType
427 if ethtype == 0x888e {
428 log.Printf("Received downstream packet is EAPOL.")
429 log.Println(rawpkt.Dump())
430 } else if layerDHCP := rawpkt.Layer(layers.LayerTypeDHCPv4); layerDHCP != nil {
431 log.Printf("Received downstream packet is DHCP.")
432 log.Println(rawpkt.Dump())
433 rawpkt, _, _ = PopVLAN(rawpkt)
434 rawpkt, _, _ = PopVLAN(rawpkt)
435 } else {
436 return nil
437 }
438 ioinfo, err := s.identifyUniIoinfo("inside", intfid, onuid)
439 if err != nil {
440 return err
441 }
442 handle := ioinfo.handler
443 SendUni(handle, rawpkt)
444 return nil
445 }
446 log.Printf("[WARNING] Received packet is not supported")
447 return nil
448}
449
450func (s *Server) uplinkPacketOut(rawpkt gopacket.Packet) error {
451 log.Println("")
452 poppkt, _, err := PopVLAN(rawpkt)
453 poppkt, _, err = PopVLAN(poppkt)
454 if err != nil {
455 log.Println(err)
456 return err
457 }
458 ioinfo, err := s.identifyNniIoinfo("inside")
459 if err != nil {
460 return err
461 }
462 handle := ioinfo.handler
463 SendNni(handle, poppkt)
464 return nil
465}
466
467func (s *Server) IsAllONUActive() bool {
468 for _, onus := range s.Onumap {
469 for _, onu := range onus {
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900470 if *onu.InternalState != device.ONU_ACTIVATED {
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900471 return false
472 }
473 }
474 }
475 return true
476}
477
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900478func getGemPortID(intfid uint32, onuid uint32) (uint32, error) {
479 idx := uint32(0)
480 return 1024 + (((MAX_ONUS_PER_PON*intfid + onuid - 1) * 7) + idx), nil
481 //return uint32(1032 + 8 * (vid - 1)), nil
482}
483
484func (s *Server) getOnuBySN(sn *openolt.SerialNumber) (*device.Onu, error) {
485 for _, onus := range s.Onumap {
486 for _, onu := range onus {
487 if device.ValidateSN(*sn, *onu.SerialNumber) {
488 return onu, nil
489 }
490 }
491 }
492 err := errors.New("No mathced SN is found !")
493 log.Println(err)
494 return nil, err
495}
496
497func (s *Server) getOnuByID(onuid uint32) (*device.Onu, error) {
498 for _, onus := range s.Onumap {
499 for _, onu := range onus {
500 if onu.OnuID == onuid {
501 return onu, nil
502 }
503 }
504 }
505 err := errors.New("No matched OnuID is found !")
506 log.Println(err)
507 return nil, err
508}
509
510func makeUniName(oltid uint32, intfid uint32, onuid uint32) (upif string, dwif string) {
511 upif = setup.UNI_VETH_UP_PFX + strconv.Itoa(int(oltid)) + "_" + strconv.Itoa(int(intfid)) + "_" + strconv.Itoa(int(onuid))
512 dwif = setup.UNI_VETH_DW_PFX + strconv.Itoa(int(oltid)) + "_" + strconv.Itoa(int(intfid)) + "_" + strconv.Itoa(int(onuid))
513 return
514}
515
516func makeNniName(oltid uint32) (upif string, dwif string) {
517 upif = setup.NNI_VETH_UP_PFX + strconv.Itoa(int(oltid))
518 dwif = setup.NNI_VETH_DW_PFX + strconv.Itoa(int(oltid))
519 return
520}
521
Keita NISHIMOTOca4da5f2018-10-15 22:48:52 +0900522func cleanUpVeths(vethenv []string) error {
523 if len(vethenv) > 0 {
524 log.Println("cleanUp veths !")
525 setup.TearVethDown(vethenv)
526 }
527 return nil
528}
529
530func killProcesses(pnames []string) error {
531 for _, pname := range pnames {
532 setup.KillProcess(pname)
533 }
Keita NISHIMOTO3b8b9c02018-10-09 09:40:01 +0900534 return nil
535}
536
537func setupVethHandler(inveth string, outveth string, vethenv []string) (*pcap.Handle, []string, error) {
538 log.Printf("setupVethHandler: %s and %s\n", inveth, outveth)
539 err1 := setup.CreateVethPairs(inveth, outveth)
540 vethenv = append(vethenv, inveth)
541 if err1 != nil {
542 setup.RemoveVeths(vethenv)
543 return nil, vethenv, err1
544 }
545 handler, err2 := getVethHandler(inveth)
546 if err2 != nil {
547 setup.RemoveVeths(vethenv)
548 return nil, vethenv, err2
549 }
550 return handler, vethenv, nil
551}
552
553func getVethHandler(vethname string) (*pcap.Handle, error) {
554 var (
555 device string = vethname
556 snapshot_len int32 = 1518
557 promiscuous bool = false
558 err error
559 timeout time.Duration = pcap.BlockForever
560 )
561 handle, err := pcap.OpenLive(device, snapshot_len, promiscuous, timeout)
562 if err != nil {
563 return nil, err
564 }
565 log.Printf("Server handle created for %s\n", vethname)
566 return handle, nil
567}