-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathutil.go
More file actions
109 lines (100 loc) · 2.4 KB
/
Copy pathutil.go
File metadata and controls
109 lines (100 loc) · 2.4 KB
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
package main
import (
"log"
"net"
"strings"
"sync"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/hkwi/gopenflow/ofp4"
"github.com/yosisa/gof"
)
func write(w *gof.Writer, m gof.Marshaler) {
b := m.Marshal()
w.WriteBytes(b)
switch v := m.(type) {
case *gof.FlowMod:
log.Printf("FlowMod: %s", ofp4.FlowMod(b))
case *gof.PacketOut:
if len(v.Actions) == 0 {
return
}
ss := make([]string, len(v.Actions))
for i, a := range v.Actions {
ss[i] = ofp4.ActionHeader(a.MarshalAction()).String()
}
log.Printf("PacketOut: %v", strings.Join(ss, ","))
case *gof.MultipartRequest:
log.Printf("MultipartRequest: type=%d", v.Type)
}
}
func parsePortInfo(d ofp4.MultipartReply, f func(ofp4.Port)) {
if d.Type() != ofp4.OFPMP_PORT_DESC {
return
}
body := d.Body()
for i := 0; i < len(body); i += 64 {
p := ofp4.Port(body[i:])
if p.PortNo() != ofp4.OFPP_LOCAL {
f(p)
}
}
}
type packetBuffer struct {
m map[uint32]map[string][]uint32
l sync.Mutex
}
func (b *packetBuffer) Add(port uint32, dst net.IP, bufid uint32) {
b.l.Lock()
defer b.l.Unlock()
if b.m == nil {
b.m = make(map[uint32]map[string][]uint32)
}
bufs, ok := b.m[port]
if !ok {
bufs = make(map[string][]uint32)
b.m[port] = bufs
}
ip := dst.String()
bufs[ip] = append(bufs[ip], bufid)
}
func (b *packetBuffer) Flush(port uint32, dst net.IP, w *gof.Writer, actions []gof.ActionMarshaler) {
b.l.Lock()
defer b.l.Unlock()
bufs, ok := b.m[port]
if !ok {
return
}
ip := dst.String()
for _, bufid := range bufs[ip] {
write(w, &gof.PacketOut{BufferID: bufid, Actions: actions})
}
delete(bufs, ip)
}
func makeARPRequest(src, dst net.IP) ([]byte, error) {
eth := layers.Ethernet{
SrcMAC: gwMAC,
DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
EthernetType: layers.EthernetTypeARP,
}
arp := layers.ARP{
AddrType: layers.LinkTypeEthernet,
Protocol: layers.EthernetTypeIPv4,
HwAddressSize: 6,
ProtAddressSize: 4,
Operation: layers.ARPRequest,
SourceHwAddress: gwMAC,
SourceProtAddress: src.To4(),
DstHwAddress: []byte{0, 0, 0, 0, 0, 0},
DstProtAddress: dst.To4(),
}
buf := gopacket.NewSerializeBuffer()
opts := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
if err := gopacket.SerializeLayers(buf, opts, ð, &arp); err != nil {
return nil, err
}
return buf.Bytes(), nil
}