Toggle navigation
Toggle navigation
This project
Loading...
Sign in
홍길동
/
onos
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
Sho SHIMIZU
2015-09-01 17:37:00 -0700
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
7d2e48e0f1c9fee67174e5b2ef7baed89788a763
7d2e48e0
1 parent
51fb9c2d
Use LF as line separator
Change-Id: I2098e93a482507eebec0bca3c134d395359349d9
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
641 additions
and
641 deletions
apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
View file @
7d2e48e
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
onosproject
.
vtn
.
impl
;
import
static
java
.
util
.
concurrent
.
Executors
.
newSingleThreadScheduledExecutor
;
import
static
org
.
onlab
.
util
.
Tools
.
groupedThreads
;
import
static
org
.
slf4j
.
LoggerFactory
.
getLogger
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.concurrent.ScheduledExecutorService
;
import
org.apache.felix.scr.annotations.Activate
;
import
org.apache.felix.scr.annotations.Component
;
import
org.apache.felix.scr.annotations.Deactivate
;
import
org.apache.felix.scr.annotations.Reference
;
import
org.apache.felix.scr.annotations.ReferenceCardinality
;
import
org.apache.felix.scr.annotations.Service
;
import
org.onlab.packet.IpAddress
;
import
org.onlab.packet.MacAddress
;
import
org.onlab.util.KryoNamespace
;
import
org.onosproject.core.ApplicationId
;
import
org.onosproject.core.CoreService
;
import
org.onosproject.net.Device
;
import
org.onosproject.net.DeviceId
;
import
org.onosproject.net.Host
;
import
org.onosproject.net.HostId
;
import
org.onosproject.net.Port
;
import
org.onosproject.net.PortNumber
;
import
org.onosproject.net.behaviour.BridgeConfig
;
import
org.onosproject.net.behaviour.BridgeDescription
;
import
org.onosproject.net.behaviour.BridgeName
;
import
org.onosproject.net.behaviour.DefaultTunnelDescription
;
import
org.onosproject.net.behaviour.IpTunnelEndPoint
;
import
org.onosproject.net.behaviour.TunnelConfig
;
import
org.onosproject.net.behaviour.TunnelDescription
;
import
org.onosproject.net.behaviour.TunnelEndPoint
;
import
org.onosproject.net.device.DeviceEvent
;
import
org.onosproject.net.device.DeviceListener
;
import
org.onosproject.net.device.DeviceService
;
import
org.onosproject.net.driver.DriverHandler
;
import
org.onosproject.net.driver.DriverService
;
import
org.onosproject.net.flow.DefaultTrafficSelector
;
import
org.onosproject.net.flow.DefaultTrafficTreatment
;
import
org.onosproject.net.flow.FlowRuleService
;
import
org.onosproject.net.flow.TrafficSelector
;
import
org.onosproject.net.flow.TrafficTreatment
;
import
org.onosproject.net.flow.criteria.Criteria
;
import
org.onosproject.net.flow.instructions.Instructions
;
import
org.onosproject.net.flowobjective.DefaultForwardingObjective
;
import
org.onosproject.net.flowobjective.FlowObjectiveService
;
import
org.onosproject.net.flowobjective.ForwardingObjective
;
import
org.onosproject.net.flowobjective.ForwardingObjective.Flag
;
import
org.onosproject.net.flowobjective.Objective
;
import
org.onosproject.net.host.HostEvent
;
import
org.onosproject.net.host.HostListener
;
import
org.onosproject.net.host.HostService
;
import
org.onosproject.store.serializers.KryoNamespaces
;
import
org.onosproject.store.service.EventuallyConsistentMap
;
import
org.onosproject.store.service.StorageService
;
import
org.onosproject.store.service.WallClockTimestamp
;
import
org.onosproject.vtn.VTNService
;
import
org.onosproject.vtnrsc.SegmentationId
;
import
org.onosproject.vtnrsc.TenantNetwork
;
import
org.onosproject.vtnrsc.VirtualPort
;
import
org.onosproject.vtnrsc.VirtualPortId
;
import
org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService
;
import
org.onosproject.vtnrsc.virtualport.VirtualPortService
;
import
org.slf4j.Logger
;
import
com.google.common.collect.Sets
;
/**
* Provides implementation of VTNService.
*/
@Component
(
immediate
=
true
)
@Service
public
class
VTNManager
implements
VTNService
{
private
final
Logger
log
=
getLogger
(
getClass
());
private
static
final
String
APP_ID
=
"org.onosproject.app.vtn"
;
private
ScheduledExecutorService
backgroundService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
DeviceService
deviceService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
HostService
hostService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
FlowRuleService
flowRuleService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
CoreService
coreService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
StorageService
storageService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
TenantNetworkService
tenantNetworkService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
VirtualPortService
virtualPortService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
DriverService
driverService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
FlowObjectiveService
flowObjectiveService
;
private
EventuallyConsistentMap
<
HostId
,
SegmentationId
>
binding
;
private
ApplicationId
appId
;
private
HostListener
hostListener
=
new
InnerHostListener
();
private
DeviceListener
deviceListener
=
new
InnerDeviceListener
();
private
static
final
String
IFACEID
=
"ifaceid"
;
private
static
final
String
PORT_HEAD
=
"vxlan"
;
private
static
final
String
DEFAULT_BRIDGE_NAME
=
"br-int"
;
private
static
final
String
CONTROLLER_IP_KEY
=
"ipaddress"
;
private
static
final
int
DEFAULT_MAC_PRIORITY
=
0x0000
;
private
static
final
int
MAC_PRIORITY
=
0xffff
;
private
static
final
int
DEFAULT_PORT_PRIORITY
=
0x0000
;
private
static
final
int
PORT_PRIORITY
=
0xffff
;
private
static
final
String
SWITCH_CHANNEL_ID
=
"channelId"
;
@Activate
public
void
activate
()
{
KryoNamespace
.
Builder
serializer
=
KryoNamespace
.
newBuilder
()
.
register
(
KryoNamespaces
.
API
);
appId
=
coreService
.
registerApplication
(
APP_ID
);
deviceService
.
addListener
(
deviceListener
);
hostService
.
addListener
(
hostListener
);
backgroundService
=
newSingleThreadScheduledExecutor
(
groupedThreads
(
"onos-apps/vtn"
,
"manager-background"
));
binding
=
storageService
.<
HostId
,
SegmentationId
>
eventuallyConsistentMapBuilder
()
.
withName
(
"all_tunnel"
).
withSerializer
(
serializer
)
.
withTimestampProvider
((
k
,
v
)
->
new
WallClockTimestamp
())
.
build
();
log
.
info
(
"Started"
);
}
@Deactivate
public
void
deactivate
()
{
backgroundService
.
shutdown
();
binding
.
destroy
();
log
.
info
(
"Stopped"
);
}
@Override
public
void
onServerDetected
(
Device
device
)
{
Iterable
<
Device
>
devices
=
deviceService
.
getAvailableDevices
();
DriverHandler
handler
=
driverService
.
createHandler
(
device
.
id
());
BridgeConfig
bridgeConfig
=
handler
.
behaviour
(
BridgeConfig
.
class
);
bridgeConfig
.
addBridge
(
BridgeName
.
bridgeName
(
DEFAULT_BRIDGE_NAME
));
String
ipAddress
=
device
.
annotations
().
value
(
CONTROLLER_IP_KEY
);
IpAddress
ip
=
IpAddress
.
valueOf
(
ipAddress
);
Sets
.
newHashSet
(
devices
).
stream
()
.
filter
(
d
->
Device
.
Type
.
CONTROLLER
==
d
.
type
())
.
filter
(
d
->
!
device
.
id
().
equals
(
d
.
id
())).
forEach
(
d
->
{
if
(!
device
.
id
().
equals
(
d
.
id
())
&&
Device
.
Type
.
CONTROLLER
==
d
.
type
())
{
String
ipAddress1
=
d
.
annotations
()
.
value
(
CONTROLLER_IP_KEY
);
IpAddress
ip1
=
IpAddress
.
valueOf
(
ipAddress1
);
applyTunnelConfig
(
ip
,
ip1
,
handler
);
DriverHandler
handler1
=
driverService
.
createHandler
(
d
.
id
());
applyTunnelConfig
(
ip1
,
ip
,
handler1
);
}
});
}
@Override
public
void
onServerVanished
(
Device
device
)
{
Iterable
<
Device
>
devices
=
deviceService
.
getAvailableDevices
();
String
ipAddress
=
device
.
annotations
().
value
(
CONTROLLER_IP_KEY
);
IpAddress
dst
=
IpAddress
.
valueOf
(
ipAddress
);
Sets
.
newHashSet
(
devices
).
stream
()
.
filter
(
d
->
d
.
type
()
==
Device
.
Type
.
CONTROLLER
)
.
filter
(
d
->
!
device
.
id
().
equals
(
d
.
id
())).
forEach
(
d
->
{
String
ipAddress1
=
d
.
annotations
()
.
value
(
CONTROLLER_IP_KEY
);
DriverHandler
handler
=
driverService
.
createHandler
(
d
.
id
());
IpAddress
src
=
IpAddress
.
valueOf
(
ipAddress1
);
removeTunnelConfig
(
src
,
dst
,
handler
);
});
}
private
void
applyTunnelConfig
(
IpAddress
src
,
IpAddress
dst
,
DriverHandler
handler
)
{
TunnelEndPoint
tunnelAsSrc
=
IpTunnelEndPoint
.
ipTunnelPoint
(
src
);
TunnelEndPoint
tunnelAsDst
=
IpTunnelEndPoint
.
ipTunnelPoint
(
dst
);
TunnelDescription
tunnel
=
new
DefaultTunnelDescription
(
tunnelAsSrc
,
tunnelAsDst
,
TunnelDescription
.
Type
.
VXLAN
,
null
);
TunnelConfig
config
=
handler
.
behaviour
(
TunnelConfig
.
class
);
config
.
createTunnel
(
tunnel
);
}
private
void
removeTunnelConfig
(
IpAddress
src
,
IpAddress
dst
,
DriverHandler
handler
)
{
TunnelEndPoint
tunnelAsSrc
=
IpTunnelEndPoint
.
ipTunnelPoint
(
src
);
TunnelEndPoint
tunnelAsDst
=
IpTunnelEndPoint
.
ipTunnelPoint
(
dst
);
TunnelDescription
tunnel
=
new
DefaultTunnelDescription
(
tunnelAsSrc
,
tunnelAsDst
,
TunnelDescription
.
Type
.
VXLAN
,
null
);
TunnelConfig
config
=
handler
.
behaviour
(
TunnelConfig
.
class
);
config
.
removeTunnel
(
tunnel
);
}
@Override
public
void
onOvsDetected
(
Device
device
)
{
programMacDefaultRules
(
device
.
id
(),
appId
,
Objective
.
Operation
.
ADD
);
programPortDefaultRules
(
device
.
id
(),
appId
,
Objective
.
Operation
.
ADD
);
Set
<
Host
>
hosts
=
hostService
.
getConnectedHosts
(
device
.
id
());
hosts
.
forEach
(
h
->
{
String
ifaceId
=
h
.
annotations
().
value
(
IFACEID
);
String
currentControllerIp
=
getControllerIpOfSwitch
(
device
.
id
());
VirtualPortId
portId
=
VirtualPortId
.
portId
(
ifaceId
);
VirtualPort
port
=
virtualPortService
.
getPort
(
portId
);
TenantNetwork
network
=
tenantNetworkService
.
getNetwork
(
port
.
networkId
());
String
vxlanName
=
"vxlan-"
+
currentControllerIp
;
DriverHandler
handler
=
driverService
.
createHandler
(
device
.
id
());
BridgeConfig
bridgeConfig
=
handler
.
behaviour
(
BridgeConfig
.
class
);
Collection
<
BridgeDescription
>
bridgeDescriptions
=
bridgeConfig
.
getBridges
();
Iterator
<
BridgeDescription
>
it
=
bridgeDescriptions
.
iterator
();
if
(
it
.
hasNext
())
{
BridgeDescription
sw
=
it
.
next
();
Set
<
PortNumber
>
ports
=
bridgeConfig
.
getPortNumbers
();
ports
.
stream
().
filter
(
p
->
p
.
name
().
equalsIgnoreCase
(
vxlanName
))
.
forEach
(
p
->
{
programTunnelOut
(
sw
.
deviceId
(),
network
.
segmentationId
(),
p
,
h
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
);
});
}
});
}
@Override
public
void
onOvsVanished
(
Device
device
)
{
programMacDefaultRules
(
device
.
id
(),
appId
,
Objective
.
Operation
.
REMOVE
);
programPortDefaultRules
(
device
.
id
(),
appId
,
Objective
.
Operation
.
REMOVE
);
}
@Override
public
void
onHostDetected
(
Host
host
)
{
String
ifaceId
=
host
.
annotations
().
value
(
IFACEID
);
DeviceId
deviceId
=
host
.
location
().
deviceId
();
String
currentControllerIp
=
getControllerIpOfSwitch
(
deviceId
);
Iterable
<
Device
>
devices
=
deviceService
.
getAvailableDevices
();
VirtualPortId
portId
=
VirtualPortId
.
portId
(
ifaceId
);
VirtualPort
port
=
virtualPortService
.
getPort
(
portId
);
TenantNetwork
network
=
tenantNetworkService
.
getNetwork
(
port
.
networkId
());
String
tunnelName
=
"vxlan-"
+
currentControllerIp
;
binding
.
put
(
host
.
id
(),
network
.
segmentationId
());
List
<
Port
>
allPorts
=
deviceService
.
getPorts
(
deviceId
);
PortNumber
inPort
=
host
.
location
().
port
();
Set
<
Port
>
localPorts
=
new
HashSet
<>();
Set
<
Port
>
tunnelPorts
=
new
HashSet
<>();
List
<
Port
>
outports
=
new
ArrayList
<>();
Sets
.
newHashSet
(
allPorts
.
iterator
()).
stream
()
.
filter
(
p
->
!
p
.
number
().
equals
(
PortNumber
.
LOCAL
)).
forEach
(
p
->
{
if
(!
p
.
annotations
().
value
(
"portName"
).
startsWith
(
PORT_HEAD
))
{
localPorts
.
add
(
p
);
}
else
{
tunnelPorts
.
add
(
p
);
}
outports
.
add
(
p
);
});
programLocalBcastRules
(
deviceId
,
network
.
segmentationId
(),
inPort
,
outports
,
appId
,
Objective
.
Operation
.
ADD
);
programLocalOut
(
deviceId
,
network
.
segmentationId
(),
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
);
tunnelPorts
.
forEach
(
tp
->
programTunnelFloodOut
(
deviceId
,
network
.
segmentationId
(),
tp
.
number
(),
localPorts
,
appId
,
Objective
.
Operation
.
ADD
));
Sets
.
newHashSet
(
devices
).
stream
()
.
filter
(
d
->
d
.
type
()
==
Device
.
Type
.
CONTROLLER
).
forEach
(
d
->
{
DriverHandler
handler
=
driverService
.
createHandler
(
d
.
id
());
BridgeConfig
bridgeConfig
=
handler
.
behaviour
(
BridgeConfig
.
class
);
Collection
<
BridgeDescription
>
bridgeDescriptions
=
bridgeConfig
.
getBridges
();
Iterator
<
BridgeDescription
>
it
=
bridgeDescriptions
.
iterator
();
if
(
it
.
hasNext
())
{
BridgeDescription
sw
=
it
.
next
();
Set
<
PortNumber
>
ports
=
bridgeConfig
.
getPortNumbers
();
ports
.
stream
()
.
filter
(
p
->
p
.
name
()
.
equalsIgnoreCase
(
tunnelName
))
.
forEach
(
p
->
{
programTunnelOut
(
sw
.
deviceId
(),
network
.
segmentationId
(),
p
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
);
});
}
});
programLocalIn
(
deviceId
,
network
.
segmentationId
(),
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
);
tunnelPorts
.
forEach
(
tp
->
programTunnelIn
(
deviceId
,
network
.
segmentationId
(),
tp
.
number
(),
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
));
}
@Override
public
void
onHostVanished
(
Host
host
)
{
SegmentationId
segId
=
binding
.
remove
(
host
.
id
());
DeviceId
deviceId
=
host
.
location
().
deviceId
();
String
currentControllerIp
=
getControllerIpOfSwitch
(
deviceId
);
Iterable
<
Device
>
devices
=
deviceService
.
getAvailableDevices
();
List
<
Port
>
allPorts
=
deviceService
.
getPorts
(
deviceId
);
PortNumber
inPort
=
host
.
location
().
port
();
String
vxlanName
=
"vxlan-"
+
currentControllerIp
;
Set
<
Port
>
localPorts
=
new
HashSet
<>();
Set
<
Port
>
tunnelPorts
=
new
HashSet
<>();
List
<
Port
>
outports
=
new
ArrayList
<>();
Sets
.
newHashSet
(
allPorts
.
iterator
()).
stream
()
.
filter
(
p
->
!
p
.
number
().
equals
(
PortNumber
.
LOCAL
)).
forEach
(
p
->
{
if
(!
p
.
annotations
().
value
(
"portName"
).
startsWith
(
PORT_HEAD
))
{
localPorts
.
add
(
p
);
}
else
{
tunnelPorts
.
add
(
p
);
}
outports
.
add
(
p
);
});
programLocalBcastRules
(
deviceId
,
segId
,
inPort
,
outports
,
appId
,
Objective
.
Operation
.
REMOVE
);
programLocalOut
(
deviceId
,
segId
,
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
REMOVE
);
tunnelPorts
.
forEach
(
tp
->
programTunnelFloodOut
(
deviceId
,
segId
,
tp
.
number
(),
localPorts
,
appId
,
Objective
.
Operation
.
REMOVE
));
Sets
.
newHashSet
(
devices
).
stream
()
.
filter
(
d
->
d
.
type
()
==
Device
.
Type
.
CONTROLLER
).
forEach
(
d
->
{
DriverHandler
handler
=
driverService
.
createHandler
(
d
.
id
());
BridgeConfig
bridgeConfig
=
handler
.
behaviour
(
BridgeConfig
.
class
);
Collection
<
BridgeDescription
>
bridgeDescriptions
=
bridgeConfig
.
getBridges
();
Iterator
<
BridgeDescription
>
it
=
bridgeDescriptions
.
iterator
();
if
(
it
.
hasNext
())
{
BridgeDescription
sw
=
it
.
next
();
Set
<
PortNumber
>
ports
=
bridgeConfig
.
getPortNumbers
();
ports
.
stream
()
.
filter
(
p
->
p
.
name
()
.
equalsIgnoreCase
(
vxlanName
))
.
forEach
(
p
->
{
programTunnelOut
(
sw
.
deviceId
(),
segId
,
p
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
REMOVE
);
});
}
});
programLocalIn
(
deviceId
,
segId
,
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
REMOVE
);
tunnelPorts
.
forEach
(
tp
->
programTunnelIn
(
deviceId
,
segId
,
tp
.
number
(),
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
REMOVE
));
}
private
class
InnerDeviceListener
implements
DeviceListener
{
@Override
public
void
event
(
DeviceEvent
event
)
{
Device
device
=
event
.
subject
();
if
(
Device
.
Type
.
CONTROLLER
==
device
.
type
()
&&
DeviceEvent
.
Type
.
DEVICE_ADDED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onServerDetected
(
device
);
});
}
else
if
(
Device
.
Type
.
CONTROLLER
==
device
.
type
()
&&
DeviceEvent
.
Type
.
DEVICE_AVAILABILITY_CHANGED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onServerVanished
(
device
);
});
}
else
if
(
Device
.
Type
.
SWITCH
==
device
.
type
()
&&
DeviceEvent
.
Type
.
DEVICE_ADDED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onOvsDetected
(
device
);
});
}
else
if
(
Device
.
Type
.
SWITCH
==
device
.
type
()
&&
DeviceEvent
.
Type
.
DEVICE_AVAILABILITY_CHANGED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onOvsVanished
(
device
);
});
}
else
{
log
.
info
(
"Do nothing for this device type"
);
}
}
}
private
class
InnerHostListener
implements
HostListener
{
@Override
public
void
event
(
HostEvent
event
)
{
Host
host
=
event
.
subject
();
if
(
HostEvent
.
Type
.
HOST_ADDED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onHostDetected
(
host
);
});
}
else
if
(
HostEvent
.
Type
.
HOST_REMOVED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onHostVanished
(
host
);
});
}
else
if
(
HostEvent
.
Type
.
HOST_UPDATED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onHostVanished
(
host
);
onHostDetected
(
host
);
});
}
}
}
// Used to forward the flows to the local VM.
private
void
programLocalOut
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
outPort
,
MacAddress
sourceMac
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchEthDst
(
sourceMac
).
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
()
.
add
(
Instructions
.
modTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())))
.
setOutput
(
outPort
).
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to forward the flows into the VXLAN tunnel.
private
void
programTunnelOut
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
tunnelOutPort
,
MacAddress
dstMac
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchEthDst
(
dstMac
).
add
(
Criteria
.
matchTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())))
.
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
()
.
setOutput
(
tunnelOutPort
).
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to forward multicast flows to remote VMs of the same tenant via
// VXLAN tunnel.
private
void
programTunnelFloodOut
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
ofPortOut
,
Iterable
<
Port
>
localports
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchInPort
(
ofPortOut
)
.
add
(
Criteria
.
matchTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
()))).
matchEthDst
(
MacAddress
.
BROADCAST
)
.
build
();
TrafficTreatment
.
Builder
treatment
=
DefaultTrafficTreatment
.
builder
();
for
(
Port
outport
:
localports
)
{
treatment
.
setOutput
(
outport
.
number
());
}
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
.
build
())
.
withSelector
(
selector
).
fromApp
(
appId
).
makePermanent
()
.
withFlag
(
Flag
.
SPECIFIC
).
withPriority
(
MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Applies default flows to mac table.
private
void
programMacDefaultRules
(
DeviceId
dpid
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
().
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
().
drop
()
.
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
makePermanent
().
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
DEFAULT_MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to forward the flows to the local VMs with the same tenant.
private
void
programLocalBcastRules
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
inPort
,
List
<
Port
>
allports
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchInPort
(
inPort
).
matchEthDst
(
MacAddress
.
BROADCAST
)
.
add
(
Criteria
.
matchTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())))
.
build
();
TrafficTreatment
.
Builder
treatment
=
DefaultTrafficTreatment
.
builder
();
for
(
Port
outport
:
allports
)
{
if
(
inPort
!=
outport
.
number
())
{
treatment
.
setOutput
(
outport
.
number
());
}
}
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
.
build
())
.
withSelector
(
selector
).
fromApp
(
appId
).
makePermanent
()
.
withFlag
(
Flag
.
SPECIFIC
).
withPriority
(
MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to apply local entry flow.
private
void
programLocalIn
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
inPort
,
MacAddress
srcMac
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchInPort
(
inPort
).
matchEthSrc
(
srcMac
).
build
();
TrafficTreatment
.
Builder
treatment
=
DefaultTrafficTreatment
.
builder
();
treatment
.
add
(
Instructions
.
modTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())));
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
.
build
())
.
withSelector
(
selector
).
fromApp
(
appId
).
makePermanent
()
.
withFlag
(
Flag
.
SPECIFIC
).
withPriority
(
PORT_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to forward the flows from the egress tunnel to the VM.
private
void
programTunnelIn
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
tunnelInPort
,
PortNumber
outPort
,
MacAddress
sourceMac
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchInPort
(
tunnelInPort
).
add
(
Criteria
.
matchTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())))
.
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
().
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
makePermanent
().
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
PORT_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Applies the default flows to port table.
private
void
programPortDefaultRules
(
DeviceId
dpid
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
().
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
().
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
makePermanent
().
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
DEFAULT_PORT_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to get channelId from the device annotations.
private
String
getControllerIpOfSwitch
(
DeviceId
deviceId
)
{
Device
device
=
deviceService
.
getDevice
(
deviceId
);
String
url
=
device
.
annotations
().
value
(
SWITCH_CHANNEL_ID
);
return
url
.
substring
(
0
,
url
.
lastIndexOf
(
":"
));
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
onosproject
.
vtn
.
impl
;
import
static
java
.
util
.
concurrent
.
Executors
.
newSingleThreadScheduledExecutor
;
import
static
org
.
onlab
.
util
.
Tools
.
groupedThreads
;
import
static
org
.
slf4j
.
LoggerFactory
.
getLogger
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.concurrent.ScheduledExecutorService
;
import
org.apache.felix.scr.annotations.Activate
;
import
org.apache.felix.scr.annotations.Component
;
import
org.apache.felix.scr.annotations.Deactivate
;
import
org.apache.felix.scr.annotations.Reference
;
import
org.apache.felix.scr.annotations.ReferenceCardinality
;
import
org.apache.felix.scr.annotations.Service
;
import
org.onlab.packet.IpAddress
;
import
org.onlab.packet.MacAddress
;
import
org.onlab.util.KryoNamespace
;
import
org.onosproject.core.ApplicationId
;
import
org.onosproject.core.CoreService
;
import
org.onosproject.net.Device
;
import
org.onosproject.net.DeviceId
;
import
org.onosproject.net.Host
;
import
org.onosproject.net.HostId
;
import
org.onosproject.net.Port
;
import
org.onosproject.net.PortNumber
;
import
org.onosproject.net.behaviour.BridgeConfig
;
import
org.onosproject.net.behaviour.BridgeDescription
;
import
org.onosproject.net.behaviour.BridgeName
;
import
org.onosproject.net.behaviour.DefaultTunnelDescription
;
import
org.onosproject.net.behaviour.IpTunnelEndPoint
;
import
org.onosproject.net.behaviour.TunnelConfig
;
import
org.onosproject.net.behaviour.TunnelDescription
;
import
org.onosproject.net.behaviour.TunnelEndPoint
;
import
org.onosproject.net.device.DeviceEvent
;
import
org.onosproject.net.device.DeviceListener
;
import
org.onosproject.net.device.DeviceService
;
import
org.onosproject.net.driver.DriverHandler
;
import
org.onosproject.net.driver.DriverService
;
import
org.onosproject.net.flow.DefaultTrafficSelector
;
import
org.onosproject.net.flow.DefaultTrafficTreatment
;
import
org.onosproject.net.flow.FlowRuleService
;
import
org.onosproject.net.flow.TrafficSelector
;
import
org.onosproject.net.flow.TrafficTreatment
;
import
org.onosproject.net.flow.criteria.Criteria
;
import
org.onosproject.net.flow.instructions.Instructions
;
import
org.onosproject.net.flowobjective.DefaultForwardingObjective
;
import
org.onosproject.net.flowobjective.FlowObjectiveService
;
import
org.onosproject.net.flowobjective.ForwardingObjective
;
import
org.onosproject.net.flowobjective.ForwardingObjective.Flag
;
import
org.onosproject.net.flowobjective.Objective
;
import
org.onosproject.net.host.HostEvent
;
import
org.onosproject.net.host.HostListener
;
import
org.onosproject.net.host.HostService
;
import
org.onosproject.store.serializers.KryoNamespaces
;
import
org.onosproject.store.service.EventuallyConsistentMap
;
import
org.onosproject.store.service.StorageService
;
import
org.onosproject.store.service.WallClockTimestamp
;
import
org.onosproject.vtn.VTNService
;
import
org.onosproject.vtnrsc.SegmentationId
;
import
org.onosproject.vtnrsc.TenantNetwork
;
import
org.onosproject.vtnrsc.VirtualPort
;
import
org.onosproject.vtnrsc.VirtualPortId
;
import
org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService
;
import
org.onosproject.vtnrsc.virtualport.VirtualPortService
;
import
org.slf4j.Logger
;
import
com.google.common.collect.Sets
;
/**
* Provides implementation of VTNService.
*/
@Component
(
immediate
=
true
)
@Service
public
class
VTNManager
implements
VTNService
{
private
final
Logger
log
=
getLogger
(
getClass
());
private
static
final
String
APP_ID
=
"org.onosproject.app.vtn"
;
private
ScheduledExecutorService
backgroundService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
DeviceService
deviceService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
HostService
hostService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
FlowRuleService
flowRuleService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
CoreService
coreService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
StorageService
storageService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
TenantNetworkService
tenantNetworkService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
VirtualPortService
virtualPortService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
DriverService
driverService
;
@Reference
(
cardinality
=
ReferenceCardinality
.
MANDATORY_UNARY
)
protected
FlowObjectiveService
flowObjectiveService
;
private
EventuallyConsistentMap
<
HostId
,
SegmentationId
>
binding
;
private
ApplicationId
appId
;
private
HostListener
hostListener
=
new
InnerHostListener
();
private
DeviceListener
deviceListener
=
new
InnerDeviceListener
();
private
static
final
String
IFACEID
=
"ifaceid"
;
private
static
final
String
PORT_HEAD
=
"vxlan"
;
private
static
final
String
DEFAULT_BRIDGE_NAME
=
"br-int"
;
private
static
final
String
CONTROLLER_IP_KEY
=
"ipaddress"
;
private
static
final
int
DEFAULT_MAC_PRIORITY
=
0x0000
;
private
static
final
int
MAC_PRIORITY
=
0xffff
;
private
static
final
int
DEFAULT_PORT_PRIORITY
=
0x0000
;
private
static
final
int
PORT_PRIORITY
=
0xffff
;
private
static
final
String
SWITCH_CHANNEL_ID
=
"channelId"
;
@Activate
public
void
activate
()
{
KryoNamespace
.
Builder
serializer
=
KryoNamespace
.
newBuilder
()
.
register
(
KryoNamespaces
.
API
);
appId
=
coreService
.
registerApplication
(
APP_ID
);
deviceService
.
addListener
(
deviceListener
);
hostService
.
addListener
(
hostListener
);
backgroundService
=
newSingleThreadScheduledExecutor
(
groupedThreads
(
"onos-apps/vtn"
,
"manager-background"
));
binding
=
storageService
.<
HostId
,
SegmentationId
>
eventuallyConsistentMapBuilder
()
.
withName
(
"all_tunnel"
).
withSerializer
(
serializer
)
.
withTimestampProvider
((
k
,
v
)
->
new
WallClockTimestamp
())
.
build
();
log
.
info
(
"Started"
);
}
@Deactivate
public
void
deactivate
()
{
backgroundService
.
shutdown
();
binding
.
destroy
();
log
.
info
(
"Stopped"
);
}
@Override
public
void
onServerDetected
(
Device
device
)
{
Iterable
<
Device
>
devices
=
deviceService
.
getAvailableDevices
();
DriverHandler
handler
=
driverService
.
createHandler
(
device
.
id
());
BridgeConfig
bridgeConfig
=
handler
.
behaviour
(
BridgeConfig
.
class
);
bridgeConfig
.
addBridge
(
BridgeName
.
bridgeName
(
DEFAULT_BRIDGE_NAME
));
String
ipAddress
=
device
.
annotations
().
value
(
CONTROLLER_IP_KEY
);
IpAddress
ip
=
IpAddress
.
valueOf
(
ipAddress
);
Sets
.
newHashSet
(
devices
).
stream
()
.
filter
(
d
->
Device
.
Type
.
CONTROLLER
==
d
.
type
())
.
filter
(
d
->
!
device
.
id
().
equals
(
d
.
id
())).
forEach
(
d
->
{
if
(!
device
.
id
().
equals
(
d
.
id
())
&&
Device
.
Type
.
CONTROLLER
==
d
.
type
())
{
String
ipAddress1
=
d
.
annotations
()
.
value
(
CONTROLLER_IP_KEY
);
IpAddress
ip1
=
IpAddress
.
valueOf
(
ipAddress1
);
applyTunnelConfig
(
ip
,
ip1
,
handler
);
DriverHandler
handler1
=
driverService
.
createHandler
(
d
.
id
());
applyTunnelConfig
(
ip1
,
ip
,
handler1
);
}
});
}
@Override
public
void
onServerVanished
(
Device
device
)
{
Iterable
<
Device
>
devices
=
deviceService
.
getAvailableDevices
();
String
ipAddress
=
device
.
annotations
().
value
(
CONTROLLER_IP_KEY
);
IpAddress
dst
=
IpAddress
.
valueOf
(
ipAddress
);
Sets
.
newHashSet
(
devices
).
stream
()
.
filter
(
d
->
d
.
type
()
==
Device
.
Type
.
CONTROLLER
)
.
filter
(
d
->
!
device
.
id
().
equals
(
d
.
id
())).
forEach
(
d
->
{
String
ipAddress1
=
d
.
annotations
()
.
value
(
CONTROLLER_IP_KEY
);
DriverHandler
handler
=
driverService
.
createHandler
(
d
.
id
());
IpAddress
src
=
IpAddress
.
valueOf
(
ipAddress1
);
removeTunnelConfig
(
src
,
dst
,
handler
);
});
}
private
void
applyTunnelConfig
(
IpAddress
src
,
IpAddress
dst
,
DriverHandler
handler
)
{
TunnelEndPoint
tunnelAsSrc
=
IpTunnelEndPoint
.
ipTunnelPoint
(
src
);
TunnelEndPoint
tunnelAsDst
=
IpTunnelEndPoint
.
ipTunnelPoint
(
dst
);
TunnelDescription
tunnel
=
new
DefaultTunnelDescription
(
tunnelAsSrc
,
tunnelAsDst
,
TunnelDescription
.
Type
.
VXLAN
,
null
);
TunnelConfig
config
=
handler
.
behaviour
(
TunnelConfig
.
class
);
config
.
createTunnel
(
tunnel
);
}
private
void
removeTunnelConfig
(
IpAddress
src
,
IpAddress
dst
,
DriverHandler
handler
)
{
TunnelEndPoint
tunnelAsSrc
=
IpTunnelEndPoint
.
ipTunnelPoint
(
src
);
TunnelEndPoint
tunnelAsDst
=
IpTunnelEndPoint
.
ipTunnelPoint
(
dst
);
TunnelDescription
tunnel
=
new
DefaultTunnelDescription
(
tunnelAsSrc
,
tunnelAsDst
,
TunnelDescription
.
Type
.
VXLAN
,
null
);
TunnelConfig
config
=
handler
.
behaviour
(
TunnelConfig
.
class
);
config
.
removeTunnel
(
tunnel
);
}
@Override
public
void
onOvsDetected
(
Device
device
)
{
programMacDefaultRules
(
device
.
id
(),
appId
,
Objective
.
Operation
.
ADD
);
programPortDefaultRules
(
device
.
id
(),
appId
,
Objective
.
Operation
.
ADD
);
Set
<
Host
>
hosts
=
hostService
.
getConnectedHosts
(
device
.
id
());
hosts
.
forEach
(
h
->
{
String
ifaceId
=
h
.
annotations
().
value
(
IFACEID
);
String
currentControllerIp
=
getControllerIpOfSwitch
(
device
.
id
());
VirtualPortId
portId
=
VirtualPortId
.
portId
(
ifaceId
);
VirtualPort
port
=
virtualPortService
.
getPort
(
portId
);
TenantNetwork
network
=
tenantNetworkService
.
getNetwork
(
port
.
networkId
());
String
vxlanName
=
"vxlan-"
+
currentControllerIp
;
DriverHandler
handler
=
driverService
.
createHandler
(
device
.
id
());
BridgeConfig
bridgeConfig
=
handler
.
behaviour
(
BridgeConfig
.
class
);
Collection
<
BridgeDescription
>
bridgeDescriptions
=
bridgeConfig
.
getBridges
();
Iterator
<
BridgeDescription
>
it
=
bridgeDescriptions
.
iterator
();
if
(
it
.
hasNext
())
{
BridgeDescription
sw
=
it
.
next
();
Set
<
PortNumber
>
ports
=
bridgeConfig
.
getPortNumbers
();
ports
.
stream
().
filter
(
p
->
p
.
name
().
equalsIgnoreCase
(
vxlanName
))
.
forEach
(
p
->
{
programTunnelOut
(
sw
.
deviceId
(),
network
.
segmentationId
(),
p
,
h
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
);
});
}
});
}
@Override
public
void
onOvsVanished
(
Device
device
)
{
programMacDefaultRules
(
device
.
id
(),
appId
,
Objective
.
Operation
.
REMOVE
);
programPortDefaultRules
(
device
.
id
(),
appId
,
Objective
.
Operation
.
REMOVE
);
}
@Override
public
void
onHostDetected
(
Host
host
)
{
String
ifaceId
=
host
.
annotations
().
value
(
IFACEID
);
DeviceId
deviceId
=
host
.
location
().
deviceId
();
String
currentControllerIp
=
getControllerIpOfSwitch
(
deviceId
);
Iterable
<
Device
>
devices
=
deviceService
.
getAvailableDevices
();
VirtualPortId
portId
=
VirtualPortId
.
portId
(
ifaceId
);
VirtualPort
port
=
virtualPortService
.
getPort
(
portId
);
TenantNetwork
network
=
tenantNetworkService
.
getNetwork
(
port
.
networkId
());
String
tunnelName
=
"vxlan-"
+
currentControllerIp
;
binding
.
put
(
host
.
id
(),
network
.
segmentationId
());
List
<
Port
>
allPorts
=
deviceService
.
getPorts
(
deviceId
);
PortNumber
inPort
=
host
.
location
().
port
();
Set
<
Port
>
localPorts
=
new
HashSet
<>();
Set
<
Port
>
tunnelPorts
=
new
HashSet
<>();
List
<
Port
>
outports
=
new
ArrayList
<>();
Sets
.
newHashSet
(
allPorts
.
iterator
()).
stream
()
.
filter
(
p
->
!
p
.
number
().
equals
(
PortNumber
.
LOCAL
)).
forEach
(
p
->
{
if
(!
p
.
annotations
().
value
(
"portName"
).
startsWith
(
PORT_HEAD
))
{
localPorts
.
add
(
p
);
}
else
{
tunnelPorts
.
add
(
p
);
}
outports
.
add
(
p
);
});
programLocalBcastRules
(
deviceId
,
network
.
segmentationId
(),
inPort
,
outports
,
appId
,
Objective
.
Operation
.
ADD
);
programLocalOut
(
deviceId
,
network
.
segmentationId
(),
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
);
tunnelPorts
.
forEach
(
tp
->
programTunnelFloodOut
(
deviceId
,
network
.
segmentationId
(),
tp
.
number
(),
localPorts
,
appId
,
Objective
.
Operation
.
ADD
));
Sets
.
newHashSet
(
devices
).
stream
()
.
filter
(
d
->
d
.
type
()
==
Device
.
Type
.
CONTROLLER
).
forEach
(
d
->
{
DriverHandler
handler
=
driverService
.
createHandler
(
d
.
id
());
BridgeConfig
bridgeConfig
=
handler
.
behaviour
(
BridgeConfig
.
class
);
Collection
<
BridgeDescription
>
bridgeDescriptions
=
bridgeConfig
.
getBridges
();
Iterator
<
BridgeDescription
>
it
=
bridgeDescriptions
.
iterator
();
if
(
it
.
hasNext
())
{
BridgeDescription
sw
=
it
.
next
();
Set
<
PortNumber
>
ports
=
bridgeConfig
.
getPortNumbers
();
ports
.
stream
()
.
filter
(
p
->
p
.
name
()
.
equalsIgnoreCase
(
tunnelName
))
.
forEach
(
p
->
{
programTunnelOut
(
sw
.
deviceId
(),
network
.
segmentationId
(),
p
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
);
});
}
});
programLocalIn
(
deviceId
,
network
.
segmentationId
(),
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
);
tunnelPorts
.
forEach
(
tp
->
programTunnelIn
(
deviceId
,
network
.
segmentationId
(),
tp
.
number
(),
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
ADD
));
}
@Override
public
void
onHostVanished
(
Host
host
)
{
SegmentationId
segId
=
binding
.
remove
(
host
.
id
());
DeviceId
deviceId
=
host
.
location
().
deviceId
();
String
currentControllerIp
=
getControllerIpOfSwitch
(
deviceId
);
Iterable
<
Device
>
devices
=
deviceService
.
getAvailableDevices
();
List
<
Port
>
allPorts
=
deviceService
.
getPorts
(
deviceId
);
PortNumber
inPort
=
host
.
location
().
port
();
String
vxlanName
=
"vxlan-"
+
currentControllerIp
;
Set
<
Port
>
localPorts
=
new
HashSet
<>();
Set
<
Port
>
tunnelPorts
=
new
HashSet
<>();
List
<
Port
>
outports
=
new
ArrayList
<>();
Sets
.
newHashSet
(
allPorts
.
iterator
()).
stream
()
.
filter
(
p
->
!
p
.
number
().
equals
(
PortNumber
.
LOCAL
)).
forEach
(
p
->
{
if
(!
p
.
annotations
().
value
(
"portName"
).
startsWith
(
PORT_HEAD
))
{
localPorts
.
add
(
p
);
}
else
{
tunnelPorts
.
add
(
p
);
}
outports
.
add
(
p
);
});
programLocalBcastRules
(
deviceId
,
segId
,
inPort
,
outports
,
appId
,
Objective
.
Operation
.
REMOVE
);
programLocalOut
(
deviceId
,
segId
,
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
REMOVE
);
tunnelPorts
.
forEach
(
tp
->
programTunnelFloodOut
(
deviceId
,
segId
,
tp
.
number
(),
localPorts
,
appId
,
Objective
.
Operation
.
REMOVE
));
Sets
.
newHashSet
(
devices
).
stream
()
.
filter
(
d
->
d
.
type
()
==
Device
.
Type
.
CONTROLLER
).
forEach
(
d
->
{
DriverHandler
handler
=
driverService
.
createHandler
(
d
.
id
());
BridgeConfig
bridgeConfig
=
handler
.
behaviour
(
BridgeConfig
.
class
);
Collection
<
BridgeDescription
>
bridgeDescriptions
=
bridgeConfig
.
getBridges
();
Iterator
<
BridgeDescription
>
it
=
bridgeDescriptions
.
iterator
();
if
(
it
.
hasNext
())
{
BridgeDescription
sw
=
it
.
next
();
Set
<
PortNumber
>
ports
=
bridgeConfig
.
getPortNumbers
();
ports
.
stream
()
.
filter
(
p
->
p
.
name
()
.
equalsIgnoreCase
(
vxlanName
))
.
forEach
(
p
->
{
programTunnelOut
(
sw
.
deviceId
(),
segId
,
p
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
REMOVE
);
});
}
});
programLocalIn
(
deviceId
,
segId
,
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
REMOVE
);
tunnelPorts
.
forEach
(
tp
->
programTunnelIn
(
deviceId
,
segId
,
tp
.
number
(),
inPort
,
host
.
mac
(),
appId
,
Objective
.
Operation
.
REMOVE
));
}
private
class
InnerDeviceListener
implements
DeviceListener
{
@Override
public
void
event
(
DeviceEvent
event
)
{
Device
device
=
event
.
subject
();
if
(
Device
.
Type
.
CONTROLLER
==
device
.
type
()
&&
DeviceEvent
.
Type
.
DEVICE_ADDED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onServerDetected
(
device
);
});
}
else
if
(
Device
.
Type
.
CONTROLLER
==
device
.
type
()
&&
DeviceEvent
.
Type
.
DEVICE_AVAILABILITY_CHANGED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onServerVanished
(
device
);
});
}
else
if
(
Device
.
Type
.
SWITCH
==
device
.
type
()
&&
DeviceEvent
.
Type
.
DEVICE_ADDED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onOvsDetected
(
device
);
});
}
else
if
(
Device
.
Type
.
SWITCH
==
device
.
type
()
&&
DeviceEvent
.
Type
.
DEVICE_AVAILABILITY_CHANGED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onOvsVanished
(
device
);
});
}
else
{
log
.
info
(
"Do nothing for this device type"
);
}
}
}
private
class
InnerHostListener
implements
HostListener
{
@Override
public
void
event
(
HostEvent
event
)
{
Host
host
=
event
.
subject
();
if
(
HostEvent
.
Type
.
HOST_ADDED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onHostDetected
(
host
);
});
}
else
if
(
HostEvent
.
Type
.
HOST_REMOVED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onHostVanished
(
host
);
});
}
else
if
(
HostEvent
.
Type
.
HOST_UPDATED
==
event
.
type
())
{
backgroundService
.
execute
(()
->
{
onHostVanished
(
host
);
onHostDetected
(
host
);
});
}
}
}
// Used to forward the flows to the local VM.
private
void
programLocalOut
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
outPort
,
MacAddress
sourceMac
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchEthDst
(
sourceMac
).
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
()
.
add
(
Instructions
.
modTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())))
.
setOutput
(
outPort
).
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to forward the flows into the VXLAN tunnel.
private
void
programTunnelOut
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
tunnelOutPort
,
MacAddress
dstMac
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchEthDst
(
dstMac
).
add
(
Criteria
.
matchTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())))
.
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
()
.
setOutput
(
tunnelOutPort
).
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to forward multicast flows to remote VMs of the same tenant via
// VXLAN tunnel.
private
void
programTunnelFloodOut
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
ofPortOut
,
Iterable
<
Port
>
localports
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchInPort
(
ofPortOut
)
.
add
(
Criteria
.
matchTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
()))).
matchEthDst
(
MacAddress
.
BROADCAST
)
.
build
();
TrafficTreatment
.
Builder
treatment
=
DefaultTrafficTreatment
.
builder
();
for
(
Port
outport
:
localports
)
{
treatment
.
setOutput
(
outport
.
number
());
}
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
.
build
())
.
withSelector
(
selector
).
fromApp
(
appId
).
makePermanent
()
.
withFlag
(
Flag
.
SPECIFIC
).
withPriority
(
MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Applies default flows to mac table.
private
void
programMacDefaultRules
(
DeviceId
dpid
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
().
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
().
drop
()
.
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
makePermanent
().
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
DEFAULT_MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to forward the flows to the local VMs with the same tenant.
private
void
programLocalBcastRules
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
inPort
,
List
<
Port
>
allports
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchInPort
(
inPort
).
matchEthDst
(
MacAddress
.
BROADCAST
)
.
add
(
Criteria
.
matchTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())))
.
build
();
TrafficTreatment
.
Builder
treatment
=
DefaultTrafficTreatment
.
builder
();
for
(
Port
outport
:
allports
)
{
if
(
inPort
!=
outport
.
number
())
{
treatment
.
setOutput
(
outport
.
number
());
}
}
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
.
build
())
.
withSelector
(
selector
).
fromApp
(
appId
).
makePermanent
()
.
withFlag
(
Flag
.
SPECIFIC
).
withPriority
(
MAC_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to apply local entry flow.
private
void
programLocalIn
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
inPort
,
MacAddress
srcMac
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchInPort
(
inPort
).
matchEthSrc
(
srcMac
).
build
();
TrafficTreatment
.
Builder
treatment
=
DefaultTrafficTreatment
.
builder
();
treatment
.
add
(
Instructions
.
modTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())));
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
.
build
())
.
withSelector
(
selector
).
fromApp
(
appId
).
makePermanent
()
.
withFlag
(
Flag
.
SPECIFIC
).
withPriority
(
PORT_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to forward the flows from the egress tunnel to the VM.
private
void
programTunnelIn
(
DeviceId
dpid
,
SegmentationId
segmentationId
,
PortNumber
tunnelInPort
,
PortNumber
outPort
,
MacAddress
sourceMac
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
()
.
matchInPort
(
tunnelInPort
).
add
(
Criteria
.
matchTunnelId
(
Long
.
parseLong
(
segmentationId
.
toString
())))
.
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
().
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
makePermanent
().
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
PORT_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Applies the default flows to port table.
private
void
programPortDefaultRules
(
DeviceId
dpid
,
ApplicationId
appid
,
Objective
.
Operation
type
)
{
TrafficSelector
selector
=
DefaultTrafficSelector
.
builder
().
build
();
TrafficTreatment
treatment
=
DefaultTrafficTreatment
.
builder
().
build
();
ForwardingObjective
.
Builder
objective
=
DefaultForwardingObjective
.
builder
().
withTreatment
(
treatment
).
withSelector
(
selector
)
.
fromApp
(
appId
).
makePermanent
().
withFlag
(
Flag
.
SPECIFIC
)
.
withPriority
(
DEFAULT_PORT_PRIORITY
);
if
(
type
.
equals
(
Objective
.
Operation
.
ADD
))
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
add
());
}
else
{
flowObjectiveService
.
forward
(
dpid
,
objective
.
remove
());
}
}
// Used to get channelId from the device annotations.
private
String
getControllerIpOfSwitch
(
DeviceId
deviceId
)
{
Device
device
=
deviceService
.
getDevice
(
deviceId
);
String
url
=
device
.
annotations
().
value
(
SWITCH_CHANNEL_ID
);
return
url
.
substring
(
0
,
url
.
lastIndexOf
(
":"
));
}
}
...
...
Please
register
or
login
to post a comment