-
Notifications
You must be signed in to change notification settings - Fork 10
/
zouppp.go
138 lines (126 loc) · 3.9 KB
/
zouppp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
zouppp is a set of GO modules implements PPPoE and related protocols:
- zouppp/pppoe: PPPoE RFC2516
- zouppp/lcp: PPP/LCP RFC1661; IPCP RFC1332; IPv6CP RFC5072;
- zouppp/pap: PAP RFC1334
- zouppp/chap: CHAP RFC1994
- zouppp/datapath: linux datapath
- zouppp/client: PPPoE Client
The main module implements a simple PPPoE test client with load testing capability. Could also be used as a starting point to implement your own PPPoE client;
*/
package main
import (
"context"
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"log"
"net/http"
_ "net/http/pprof"
"runtime"
"time"
"github.com/hujun-open/etherconn"
"github.com/hujun-open/shouchan"
"github.com/hujun-open/zouppp/client"
"github.com/hujun-open/zouppp/pppoe"
)
func main() {
setup := client.DefaultSetup()
cnf, err := shouchan.NewSConf(setup, "zouppp", "a pppoe testing tool", shouchan.WithDefaultConfigFilePath[*client.Setup]("zouppp.conf"))
if err != nil {
log.Fatalf("failed to create configuration, %v", err)
}
cnf.ReadwithCMDLine()
setup = cnf.GetConf()
err = setup.Init()
if err != nil {
log.Fatalf("invalid setup, %v", err)
}
// create a list of client.Config based on the setup
cfglist, err := client.GenClientConfigurations(setup)
if err != nil {
log.Fatalf("failed to generate client config, %v", err)
}
// profiling is for dev use only
if setup.Profiling {
runtime.SetBlockProfileRate(1000000000)
go func() {
log.Println(http.ListenAndServe("0.0.0.0:6060", nil))
}()
}
// create a context
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// create a etherconn.RawSoketRelay
var relay etherconn.PacketRelay
if !setup.XDP {
relay, err = etherconn.NewRawSocketRelay(ctx, setup.Ifname,
etherconn.WithDebug(setup.LogLevel == client.LogLvlDebug),
etherconn.WithBPFFilter(`(ether proto 0x8863 or 0x8864) or (vlan and ether proto 0x8863 or 0x8864)`),
etherconn.WithRecvTimeout(setup.Timeout))
if err != nil {
setup.Logger().Sugar().Errorf("failed to create raw packet relay, %v", err)
return
}
} else {
relay, err = etherconn.NewXDPRelay(ctx, setup.Ifname,
etherconn.WithXDPDebug(setup.LogLevel == client.LogLvlDebug),
etherconn.WithXDPEtherTypes([]uint16{0x8863, 0x8864}),
etherconn.WithXDPDefaultReceival(false),
etherconn.WithXDPSendChanDepth(10240),
etherconn.WithXDPUMEMNumOfTrunk(65536),
)
if err != nil {
setup.Logger().Sugar().Errorf("failed to create xdp packet relay, %v", err)
return
}
}
// create a ResultSummary channel to get a ResultSummary upon dial finishes
summaryCh := make(chan *client.ResultSummary)
go client.CollectResults(setup, summaryCh)
// creates dialwg to get dialing results
dialwg := new(sync.WaitGroup)
dialwg.Add(len(cfglist))
// sessionwg.Wait to wait for all opened sessions
sessionwg := new(sync.WaitGroup)
// start dialing
var clntList []*client.ZouPPP
for _, cfg := range cfglist {
econn := etherconn.NewEtherConn(cfg.Mac, relay,
etherconn.WithEtherTypes([]uint16{pppoe.EtherTypePPPoEDiscovery, pppoe.EtherTypePPPoESession}),
etherconn.WithVLANs(cfg.VLANs), etherconn.WithRecvMulticast(true))
z, err := client.NewZouPPP(econn, cfg, client.WithDialWG(dialwg), client.WithSessionWG(sessionwg))
if err != nil {
setup.Logger().Sugar().Errorf("failed to create zouppp,%v", err)
return
}
go z.Dial(ctx)
clntList = append(clntList, z)
// sleep for dialing interval
time.Sleep(setup.Interval)
}
// wait for all sessions dialing finish
dialwg.Wait()
setup.Logger().Sugar().Info("all sessions dialing finished")
// get the dailing result summary
summary := <-summaryCh
fmt.Println(summary)
setup.Close()
// handle ctrl+c
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
fmt.Println("stopping...")
for _, z := range clntList {
z.Close()
}
}()
// wait for all opened sessions to close
if summary.Success > 0 {
sessionwg.Wait()
}
fmt.Println("done")
}