forked from sdn-ixp/iSDX
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmds.py
236 lines (189 loc) · 9 KB
/
mds.py
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#!/usr/bin/env python
# Author:
# Rudiger Birkner (Networked Systems Group ETH Zurich)
import os
import sys
np = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
if np not in sys.path:
sys.path.append(np)
import util.log
from flowmodmsg import FlowModMsgBuilder
# Priorities
BGP_PRIORITY = 4
ARP_PRIORITY = 4
OUTBOUND_PRIORITY = 3
FORWARDING_PRIORITY = 2
INBOUND_PRIORITY = 1
DEFAULT_PRIORITY = 1
# Ports
BGP = 179
# ETH Types
ETH_TYPE_ARP = 0x0806
# MAC Addresses
MAC_BROADCAST = "ff:ff:ff:ff:ff:ff"
# OF Special Ports
OFPP_MAX = 0xffffff00
OFPP_IN_PORT = 0xfffffff8 # Send the packet out the input port. This
# virtual port must be explicitly used
# in order to send back out of the input
# port.
OFPP_TABLE = 0xfffffff9 # Perform actions in flow table.
# NB: This can only be the destination
# port for packet-out messages.
OFPP_NORMAL = 0xfffffffa # Process with normal L2/L3 switching.
OFPP_FLOOD = 0xfffffffb # All physical ports except input port and
# those disabled by STP.
OFPP_ALL = 0xfffffffc # All physical ports except input port.
OFPP_CONTROLLER = 0xfffffffd # Send to controller.
OFPP_LOCAL = 0xfffffffe # Local openflow "port".
OFPP_ANY = 0xffffffff # Not associated with a physical port.
class MDS(object):
def __init__(self, logger, sender, config):
self.logger = logger
self.sender = sender
self.config = config
self.fm_builder = FlowModMsgBuilder(0, self.config.flanc_auth["key"])
def handle_BGP(self, rule_type):
### BGP traffic to route server
port = self.config.route_server.ports[0]
action = {"fwd": [port.id]}
match = {"eth_dst": port.mac, "tcp_src": BGP}
self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)
match = {"eth_dst": port.mac, "tcp_dst": BGP}
self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)
### BGP traffic to participants
for participant in self.config.peers.values():
for port in participant.ports:
match = {"eth_dst": port.mac, "tcp_src": BGP}
action = {"fwd": [port.id]}
self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)
match = {"eth_dst": port.mac, "tcp_dst": BGP}
self.fm_builder.add_flow_mod("insert", rule_type, BGP_PRIORITY, match, action)
def handle_ARP(self, rule_type):
### direct ARP requests for VNHs to ARP proxy
port = self.config.arp_proxy.ports[0]
match = {"eth_type": ETH_TYPE_ARP, "arp_tpa": (str(self.config.vnhs.network), str(self.config.vnhs.netmask))}
action = {"fwd": [port.id]}
self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)
### direct all ARP requests for the route server to it
port = self.config.route_server.ports[0]
match = {"eth_type": ETH_TYPE_ARP, "eth_dst": port.mac}
action = {"fwd": [port.id]}
self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)
for participant in self.config.peers.values():
### make sure ARP replies reach the participants
for port in participant.ports:
match = {"eth_type": ETH_TYPE_ARP, "eth_dst": port.mac}
action = {"fwd": [port.id]}
self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)
### flood ARP requests
match = {"eth_type": ETH_TYPE_ARP, "eth_dst": MAC_BROADCAST}
ports = []
for participant in self.config.peers.values():
for port in participant.ports:
ports.append(port.id)
ports.append(self.config.arp_proxy.ports[0].id)
ports.append(self.config.route_server.ports[0].id)
action = {"fwd": ports}
self.fm_builder.add_flow_mod("insert", rule_type, ARP_PRIORITY, match, action)
def handle_participant_with_outbound(self, rule_type):
for participant in self.config.peers.values():
### outbound policies specified
if participant.outbound_rules:
mac = None
for port in participant.ports:
if mac is None:
mac = port.mac
match = {"in_port": port.id}
action = {"set_eth_src": mac, "fwd": ["outbound"]}
self.fm_builder.add_flow_mod("insert", rule_type, OUTBOUND_PRIORITY, match, action)
def handle_participant_with_inbound(self, rule_type):
for participant in self.config.peers.values():
### send all traffic for participants with inbound policies to inbound handler
if participant.inbound_rules:
for port in participant.ports:
match = {"eth_dst": port.mac}
action = {"fwd": ["inbound"]}
self.fm_builder.add_flow_mod("insert", rule_type, INBOUND_PRIORITY, match, action)
def default_forwarding(self, rule_type):
for participant in self.config.peers.values():
### default forwarding
if not participant.inbound_rules:
port = participant.ports[0]
match = {"eth_dst": port.mac}
action = {"fwd": [port.id]}
self.fm_builder.add_flow_mod("insert", rule_type, FORWARDING_PRIORITY, match, action)
def default_forwarding_inbound(self, rule_type, in_port):
### default forwarding for traffic to participants with inbound policies
for participant in self.config.peers.values():
if participant.inbound_rules:
for port in participant.ports:
match = {"eth_dst": port.mac}
if in_port:
match["in_port"] = 1
action = {"fwd": [port.id]}
self.fm_builder.add_flow_mod("insert", rule_type, FORWARDING_PRIORITY, match, action)
def match_any_fwd(self, rule_type, dst):
match = {}
action = {"fwd": [dst]}
self.fm_builder.add_flow_mod("insert", rule_type, DEFAULT_PRIORITY, match, action)
def start(self):
self.logger.info('start')
self.init_fabric()
self.sender.send(self.fm_builder.get_msg())
self.logger.info('sent flow mods to reference monitor')
class MDSmS(MDS):
def __init__(self, sender, config):
super(MDSmS, self).__init__(util.log.getLogger('MDSmS'), sender, config)
def init_fabric(self):
self.logger.info('init fabric')
# MAIN SWITCH
## handle BGP traffic
self.logger.info('create flow mods to handle BGP traffic')
self.handle_BGP("main-in")
## handle ARP traffic
self.logger.info('create flow mods to handle ARP traffic')
self.handle_ARP("main-in")
## handle all participant traffic depending on whether they specified inbound/outbound policies
self.logger.info('create flow mods to handle participant traffic')
### outbound policies specified
self.handle_participant_with_outbound("main-in")
### inbound policies specified
self.handle_participant_with_inbound("main-in")
self.default_forwarding_inbound("main-in", True)
### default forwarding
self.default_forwarding("main-in")
# OUTBOUND SWITCH
# INBOUND SWITCH
## send all other packets to main
self.match_any_fwd("inbound", "main-in")
self.sender.send(self.fm_builder.get_msg())
self.logger.info('sent flow mods to reference monitor')
class MDSmT(MDS):
def __init__(self, sender, config):
super(MDSmT, self).__init__(util.log.getLogger('MDSmT'), sender, config)
def init_fabric(self):
self.logger.info('init fabric')
# MAIN-IN TABLE
## handle BGP traffic
self.logger.info('create flow mods to handle BGP traffic')
self.handle_BGP("main-in")
## handle ARP traffic
self.logger.info('create flow mods to handle ARP traffic')
self.handle_ARP("main-in")
## handle all participant traffic depending on whether they specified inbound/outbound policies
self.logger.info('create flow mods to handle participant traffic')
### outbound policies specified
self.handle_participant_with_outbound("main-in")
### inbound policies specified
self.handle_participant_with_inbound("main-in")
## whatever doesn't match on any other rule, send to out table
self.match_any_fwd("main-in", "main-out")
# OUTBOUND SWITCH
# INBOUND SWITCH
## send all other packets to main
self.match_any_fwd("inbound", "main-out")
# MAIN-OUT TABLE
### default forwarding
self.default_forwarding("main-out")
self.default_forwarding_inbound("main-out", False)