app注册
private ApplicationId appId;
appId = coreService .registerApplication("org.onosproject.fwd");
//注册应用,一般在activate函数中完成
拓扑监听器
//自定义拓扑监听器,覆盖event函数,具体功能可自己实现,这里是避免路由黑洞
private class InternalTopologyListener implements TopologyListener {
@Override
public void event(TopologyEvent event) {
List< Event> reasons = event.reasons();
if (reasons != null) {
reasons.forEach(re -> {
if (re instanceof LinkEvent) {
LinkEvent le = (LinkEvent) re;
if (le .type() == LinkEvent.Type.LINK_REMOVED) {
fixBlackhole( le.subject().src());
}
}
});
}
}
}
private final TopologyListener topologyListener = new InternalTopologyListener();
//定义一个拓扑监听器
topologyService.addListener( topologyListener);
//添加监听器,般在activate函数中完成
设备监听器
/**
* Listener to Device Event and OVSDB connection.
* 这段代码来自github,供参考。网址:https://github.com/MaoJianwei/ONOS_OVS_Manager_Bootcamp2016
*/
private class InnerDeviceListener implements DeviceListener {
@Override
public void event(DeviceEvent event) {
if (!event.type().equals(DeviceEvent.Type.DEVICE_ADDED)) {
return;
}
Device device = event.subject();
if (device.type() == Device.Type.CONTROLLER) {
dealController(device.id());
} else {
dealSwitch(device.id());
}
}
/**
* Catch the new OVSDB connection.
* @param deviceId : The OVSDB connection ID.
*/
private void dealController(DeviceId deviceId) {
controllerId = deviceId;
log.info( "controllerId is ready !!!" );
}
/**
* Separate two type of switches.
* @param deviceId : The DeviceId of target device.
*/
private void dealSwitch(DeviceId deviceId) {
String datapathId = deviceId.toString().split( ":")[1];
if (Integer.valueOf(datapathId) > CORE_DEVICEID_CARDINALITY) {
dealCoreSwitch(deviceId);
} else {
dealAccessSwitch(deviceId);
}
}
/**
* Add specific ForwardingObject to CORE switch.
* @param deviceId : The DeviceId of target device.
*/
private void dealCoreSwitch(DeviceId deviceId) {
TrafficSelector.Builder trafficSelectorBuilder0 = DefaultTrafficSelector.builder();
trafficSelectorBuilder0.matchEthType(EthType.EtherType.IPV4.ethType().toShort())
.matchIPDst(IpPrefix.valueOf( "192.168.1.1/28"))
.matchIPSrc(IpPrefix.valueOf( "1.2.3.4/32"));
TrafficTreatment.Builder trafficTreatmentBuilder0 = DefaultTrafficTreatment.builder();
trafficTreatmentBuilder0.setEthDst(MacAddress.BROADCAST).transition(1);
addForward(deviceId, BOTH_TABLE_PRIORITY,
trafficSelectorBuilder0.build(), trafficTreatmentBuilder0.build());
}
/**
* Add specific ForwardingObject to ACCESS switch.
* @param deviceId : The DeviceId of target device.
*/
private void dealAccessSwitch(DeviceId deviceId) {
TrafficSelector.Builder trafficSelectorBuilder0 = DefaultTrafficSelector.builder();
trafficSelectorBuilder0.matchEthType(EthType.EtherType.IPV4.ethType().toShort())
.matchIPSrc(IpPrefix.valueOf( "10.0.0.0/24"));
TrafficTreatment.Builder trafficTreatmentBuilder0 = DefaultTrafficTreatment.builder();
trafficTreatmentBuilder0.setEthDst(MacAddress.BROADCAST).transition(1);
addForward(deviceId, BOTH_TABLE_PRIORITY,
trafficSelectorBuilder0.build(), trafficTreatmentBuilder0.build());
TrafficSelector.Builder trafficSelectorBuilder1 = DefaultTrafficSelector.builder();
trafficSelectorBuilder1.matchEthDst(MacAddress.BROADCAST);
TrafficTreatment.Builder trafficTreatmentBuilder1 = DefaultTrafficTreatment.builder();
trafficTreatmentBuilder1.drop();
addForward(deviceId, BOTH_TABLE_PRIORITY,
trafficSelectorBuilder1.build(), trafficTreatmentBuilder1.build());
}
/**
* Utility method to add ForwardingObjective.
* @param deviceId : The DeviceId of target device.
* @param priority : Priority of ForwardingObjective.
* @param selector : Match fields.
* @param treatment : Instructions.
*/
private void addForward(DeviceId deviceId, int priority, TrafficSelector selector, TrafficTreatment treatment) {
ForwardingObjective.Builder forwardingObjectiveBuilder = DefaultForwardingObjective.builder();
forwardingObjectiveBuilder
.withFlag(ForwardingObjective.Flag.SPECIFIC)
.withTreatment(treatment)
.withSelector(selector)
.withPriority(priority)
.fromApp(applicationId)
.makePermanent();
flowObjectiveService.forward(deviceId, forwardingObjectiveBuilder.add());
}
}
private InnerDeviceListener innerDeviceListener;
innerDeviceListener = new InnerDeviceListener();
deviceService.addListener(innerDeviceListener);//一般放在activate中
包处理器
/**
* Packet processor responsible for forwarding packets along their paths.
* 主要为process函数,处理的是一个PacketContext,在开发自己的应用时对于包的处理
* 可以从这段代码中得到启发。
*/
private class ReactivePacketProcessor implements PacketProcessor {
@Override
public void process (PacketContext context ) {
// Stop processing if the packet has been handled, since we
// can't do any more to it.
if (context .isHandled()) {
return;
}
InboundPacket pkt = context .inPacket();
Ethernet ethPkt = pkt .parsed();
if (ethPkt == null) {
return;
}
// Bail if this is deemed to be a control packet.
if (isControlPacket(ethPkt )) {
return;
}
// Skip IPv6 multicast packet when IPv6 forward is disabled.
if (!ipv6Forwarding && isIpv6Multicast(ethPkt)) {
return;
}
HostId id = HostId. hostId(ethPkt.getDestinationMAC());
// Do not process link-local addresses in any way.
if (id .mac().isLinkLocal()) {
return;
}
// Do not process IPv4 multicast packets, let mfwd handle them
if (ignoreIpv4McastPackets && ethPkt.getEtherType() == Ethernet.TYPE_IPV4 ) {
if (id .mac().isMulticast()) {
return;
}
}
// Do we know who this is for? If not, flood and bail.
Host dst = hostService .getHost(id);
if (dst == null) {
flood( context);
return;
}
// Are we on an edge switch that our destination is on? If so,
// simply forward out to the destination and bail.
if (pkt.receivedFrom().deviceId().equals(dst .location().deviceId())) {
if (!context.inPacket().receivedFrom().port().equals(dst.location().port())) {
installRule( context, dst .location().port());
}
return;
}
// Otherwise, get a set of paths that lead from here to the
// destination edge switch.
Set paths =
topologyService.getPaths(topologyService .currentTopology(),
pkt.receivedFrom().deviceId(),
dst.location().deviceId());
if (paths .isEmpty()) {
// If there are no paths, flood and bail.
flood( context);
return;
}
// Otherwise, pick a path that does not lead back to where we
// came from; if no such path, flood and bail.
Path path = pickForwardPathIfPossible(paths , pkt.receivedFrom().port());
if (path == null) {
log.warn("Don't know where to go from here {} for {} -> {}",
pkt.receivedFrom(), ethPkt .getSourceMAC(), ethPkt.getDestinationMAC());
flood( context);
return;
}
// Otherwise forward and be done with it.
installRule( context, path .src().port());
}
}
private ReactivePacketProcessor processor = new ReactivePacketProcessor();
//Packet processor responsible for forwarding packets along their paths.
//负责数据包在特定路径上转发的数据包处理器
packetService.addProcessor(processor , PacketProcessor.director(2));
//添加包处理器,一般放在activate函数中
流表下发与删除过程
/*
* 制定流表规则,比较重要的部分有两个:
* 一个是selector,用来指定源目的 ip,源目的mac,源目的port
* 另一个treatment,用来说明怎么处理包,丢弃还是转发,从哪儿转发
* 再有就是确定优先级,然后发到哪个设备上
*/
private void installRule(TrafficSelector selector, TrafficTreatment treatment , DeviceId deviceId, int priority ){
ForwardingObjective.Builder forwardingObjectiveBuilder = DefaultForwardingObjective.builder();
forwardingObjectiveBuilder
.withFlag(ForwardingObjective.Flag. VERSATILE)
.withSelector( selector)
.withTreatment( treatment)
.withPriority( priority)
.makePermanent()
.fromApp( appId);
flowObjectiveService.forward(deviceId , forwardingObjectiveBuilder .add());
}
//流表下发测试函数,当前拓扑中的交换机都发一遍
private void testInstallRules(){
src_ip_0 = 10;
src_ip_1 = 0;
src_ip_2 = 0;
src_ip_3 = 1;
des_ip_0 =10;
des_ip_1 = 0;
des_ip_2 = 0;
des_ip_3 = 2;
src_port = 8011;
des_port = 8012;
byte[] ip = {(byte) src_ip_0, (byte )src_ip_1 , (byte) src_ip_2, (byte)src_ip_3 };
IpAddress src_ip = IpAddress.valueOf(IpAddress.Version. INET, ip);
Host src_host = getHostByIp(src_ip );
byte[] ips = {(byte) des_ip_0, (byte )des_ip_1 , (byte)des_ip_2 , (byte) des_ip_3};
IpAddress des_ip = IpAddress.valueOf(IpAddress.Version. INET, ips);
Host des_host = getHostByIp(des_ip );
MacAddress src_mac = src_host .mac();
MacAddress des_mac = des_host .mac();
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
TrafficSelector selector = selectorBuilder.matchEthSrc(src_mac )
.matchEthDst( des_mac)
.matchEthType(Ethernet. TYPE_IPV4)
.matchIPSrc(Ip4Prefix. valueOf(src_ip, Ip4Prefix.MAX_MASK_LENGTH ))
.matchIPDst(Ip4Prefix. valueOf(des_ip, Ip4Prefix.MAX_MASK_LENGTH ))
.matchIPProtocol(org.onlab.packet.IPv4. PROTOCOL_UDP)
.matchTcpSrc(TpPort. tpPort(src_port))
.matchTcpDst(TpPort. tpPort(des_port))
.build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setEthDst( des_mac)
.build();
Iterator devices = deviceService.getDevices(Type.SWITCH).iterator();
while(devices .hasNext()){
Device device = devices .next();
DeviceId deviceId = device .id();
//log.info(deviceId.toString());
installRule( selector, treatment , deviceId , 10);
}
}
// 删除流表
private void cleanFlowRules(SrcDstPair pair , DeviceId id) {
log.info(">>>>>Searching for flow rules to remove from: " + id);
log.info(">>>>>Removing flows w/ SRC=" + pair.src + ", DST=" + pair.dst );
for (FlowEntry r : flowRuleService.getFlowEntries( id)) {
boolean matchesSrc = false, matchesDst = false ;
for (Instruction i : r.treatment().allInstructions()) {
if (i .type() == Instruction.Type.OUTPUT) {
// if the flow has matching src and dst
for (Criterion cr : r.selector().criteria()) {
if (cr .type() == Criterion.Type.ETH_DST) {
if (((EthCriterion) cr).mac().equals(pair .dst )) {
matchesDst = true ;
}
} else if (cr .type() == Criterion.Type.ETH_SRC) {
if (((EthCriterion) cr).mac().equals(pair .src )) {
matchesSrc = true ;
}
}
}
}
}
if (matchesDst && matchesSrc) {
log.info(">>>>>Removed flow rule from device: " + id);
flowRuleService.removeFlowRules((FlowRule) r );
}
}
}
//流表删除测试函数
private void testCleanRules(){
src_ip_0 = 10;
src_ip_1 = 0;
src_ip_2 = 0;
src_ip_3 = 1;
des_ip_0 =10;
des_ip_1 = 0;
des_ip_2 = 0;
des_ip_3 = 2;
src_port = 8013;
des_port = 8014;
byte[] ip = {(byte) src_ip_0, (byte )src_ip_1 , (byte) src_ip_2, (byte)src_ip_3 };
IpAddress src_ip = IpAddress.valueOf(IpAddress.Version. INET, ip);
Host src_host = getHostByIp(src_ip );
byte[] ips = {(byte) des_ip_0, (byte )des_ip_1 , (byte)des_ip_2 , (byte) des_ip_3};
IpAddress des_ip = IpAddress.valueOf(IpAddress.Version. INET, ips);
Host des_host = getHostByIp(des_ip );
MacAddress src_mac = src_host .mac();
MacAddress des_mac = des_host .mac();
Iterator devices = deviceService.getDevices(Type.SWITCH).iterator();
while(devices .hasNext()){
Device device = devices .next();
DeviceId deviceId = device .id();
//log.info(deviceId.toString());
SrcDstPair pair = new SrcDstPair(src_mac, des_mac);
cleanFlowRules( pair, deviceId );
}
}