-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathofcontroller.go
129 lines (110 loc) · 3.29 KB
/
ofcontroller.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
package goof
import (
"fmt"
"net"
"strings"
"time"
log "github.com/Sirupsen/logrus"
"github.com/kopwei/goof/protocols/ofp10"
"github.com/kopwei/goof/protocols/ofp15"
"github.com/kopwei/goof/protocols/ofpgeneral"
)
// OfpPacketInMsg is the interface for the openflow package
type OfpPacketInMsg interface{}
// OFApplication defines the openflow application interface
type OFApplication interface {
// A Switch connected to the controller
Connected(sw *OpenflowSwitch)
// Switch disconnected from the controller
Disconnected(sw *OpenflowSwitch)
// Controller received a message packet from the switch
PacketRcvd(sw *OpenflowSwitch, msg OfpPacketInMsg)
}
// OfpController represents the openflow controller structure
type OfpController interface {
StartListen(portNo int)
}
type ofpControllerImpl struct {
bridges []OpenflowSwitch
}
// NewOfpController creates a new openflow controller
func NewOfpController() (OfpController, error) {
ctrler := &ofpControllerImpl{}
ctrler.bridges = make([]OpenflowSwitch, 0)
return ctrler, nil
}
// StartListen will start a tcp listener
func (oc *ofpControllerImpl) StartListen(portNo int) {
portNoStr := fmt.Sprintf(":%d", portNo)
addr, err := net.ResolveTCPAddr("tcp", portNoStr)
if err != nil {
log.Fatal(err)
}
listener, err := net.ListenTCP("tcp", addr)
if err != nil {
log.Fatal(err)
}
defer listener.Close()
log.Println("Listening for connections on", addr)
for {
conn, err := listener.AcceptTCP()
if err != nil {
if strings.Contains(err.Error(), "use of closed network connection") {
return
}
log.Fatal(err)
}
go handleConnection(conn)
}
}
func handleConnection(conn *net.TCPConn) {
msgStream := NewOfpMsgTunnel(conn)
hello := ofpgeneral.NewHelloMsg(4)
msgStream.Outgoing <- hello
for {
select {
case msg := <-msgStream.Incomming:
switch m := msg.(type) {
case *ofpgeneral.OfpHelloMsg:
log.Debugf("Hello message %+v is received", m)
version, _ := ofpgeneral.GetOfpMsgVersion(m)
if isVersionValid(version) {
msgStream.Version = version
msgStream.SendFeatureRequest()
} else {
// Connection should be severed if controller
// doesn't support switch version.
log.Println("Received unsupported ofp version", version)
msgStream.Shutdown <- true
}
// After a vaild FeaturesReply has been received we
// have all the information we need. Create a new
// switch object and notify applications.
case *ofp10.OfpSwitchFeatureMsg:
log.Printf("Received ofp1.0 Switch feature response: %+v", *m)
// Create a new switch and handover the stream
NewSwitch(msgStream, m)
// Let switch instance handle all future messages..
return
// An error message may indicate a version mismatch. We
// disconnect if an error occurs this early.
case *ofpgeneral.OfpErrMsg:
log.Warnf("Received error msg: %+v", *m)
msgStream.Shutdown <- true
}
case err := <-msgStream.Error:
// The connection has been shutdown.
log.Println(err)
return
case <-time.After(time.Second * 3):
// This shouldn't happen. If it does, both the controller
// and switch are no longer communicating. The TCPConn is
// still established though.
log.Warnln("Connection timed out.")
return
}
}
}
func isVersionValid(v uint8) bool {
return v > 0 && v < ofp15.Version
}