/* * Copyright 2016-present 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.pcep.controller.impl; import static org.onosproject.pcep.controller.PcepLspSyncAction.SEND_UPDATE; import static org.onosproject.pcep.controller.PcepLspSyncAction.UNSTABLE; import java.net.SocketAddress; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffers; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelConfig; import org.jboss.netty.channel.ChannelFactory; import org.jboss.netty.channel.ChannelFuture; import org.jboss.netty.channel.ChannelPipeline; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.onlab.packet.IpAddress; import org.onosproject.core.ApplicationId; import org.onosproject.incubator.net.tunnel.DefaultTunnel; import org.onosproject.incubator.net.tunnel.Tunnel; import org.onosproject.incubator.net.tunnel.TunnelEndPoint; import org.onosproject.incubator.net.tunnel.TunnelId; import org.onosproject.incubator.net.tunnel.TunnelListener; import org.onosproject.incubator.net.tunnel.TunnelName; import org.onosproject.incubator.net.tunnel.TunnelService; import org.onosproject.incubator.net.tunnel.TunnelSubscription; import org.onosproject.incubator.net.tunnel.Tunnel.Type; import org.onosproject.net.Annotations; import org.onosproject.net.DeviceId; import org.onosproject.net.ElementId; import org.onosproject.net.Path; import org.onosproject.pcep.controller.ClientCapability; import org.onosproject.pcep.controller.PccId; import org.onosproject.pcep.controller.PcepEventListener; import org.onosproject.pcep.controller.PcepLspSyncAction; import org.onosproject.pcep.controller.PcepPacketStats; import org.onosproject.pcep.controller.PcepSyncStatus; import org.onosproject.pcepio.exceptions.PcepOutOfBoundMessageException; import org.onosproject.pcepio.exceptions.PcepParseException; import org.onosproject.pcepio.protocol.PcepFactories; import org.onosproject.pcepio.protocol.PcepInitiateMsg; import org.onosproject.pcepio.protocol.PcepMessage; import org.onosproject.pcepio.protocol.PcepMessageReader; import org.onosproject.pcepio.protocol.PcepVersion; import com.google.common.collect.ImmutableSet; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.Is.is; public class PcepClientControllerImplTest { PcepClientControllerImpl controllerImpl = new PcepClientControllerImpl(); TunnelService tunnelService = new MockTunnelService(); private PcepEventListener listener; private Channel channel; @Before public void startUp() { controllerImpl.tunnelService = tunnelService; listener = new PcepEventListenerAdapter(); controllerImpl.addEventListener(listener); channel = new MockChannel(); } @After public void tearDown() { controllerImpl.removeEventListener(listener); listener = null; controllerImpl.tunnelService = null; } @Test public void tunnelProviderAddedTest1() throws PcepParseException, PcepOutOfBoundMessageException { PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1")); byte[] reportMsg = new byte[] {0x20, 0x0a, 0x00, (byte) 0x50, 0x21, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // SRP object 0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x24, // LSP object 0x00, 0x00, 0x10, (byte) 0xAB, 0x00, 0x11, 0x00, 0x02, 0x54, 0x31, 0x00, 0x00, // symbolic path tlv 0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x05, 0x07, 0x10, 0x00, 0x14, // ERO object 0x01, 0x08, (byte) 0x01, 0x01, // ERO IPv4 sub objects 0x01, 0x01, 0x04, 0x00, 0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00, }; ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); buffer.writeBytes(reportMsg); PcepMessageReader<PcepMessage> reader = PcepFactories.getGenericReader(); PcepMessage message = reader.readFrom(buffer); PcepClientImpl pc = new PcepClientImpl(); PcepPacketStats pktStats = new PcepPacketStatsImpl(); pc.init(pccId, PcepVersion.PCEP_1, pktStats); pc.setChannel(channel); pc.setAgent(controllerImpl.agent); pc.setConnected(true); pc.setCapability(new ClientCapability(true, true, true, true, true)); controllerImpl.agent.addConnectedClient(pccId, pc); controllerImpl.processClientMessage(pccId, message); pc.setLspDbSyncStatus(PcepSyncStatus.SYNCED); pc.setLabelDbSyncStatus(PcepSyncStatus.IN_SYNC); pc.setLabelDbSyncStatus(PcepSyncStatus.SYNCED); List<PcepMessage> deleteMsgs = ((MockChannel) channel).msgsWritten(); assertThat(deleteMsgs.size(), is(1)); for (PcepMessage msg : deleteMsgs) { assertThat(((PcepInitiateMsg) msg).getPcInitiatedLspRequestList().getFirst().getSrpObject().getRFlag(), is(true)); } } @Test public void tunnelProviderAddedTest2() throws PcepParseException, PcepOutOfBoundMessageException { PccId pccId = PccId.pccId(IpAddress.valueOf("1.1.1.1")); byte[] reportMsg = new byte[] {0x20, 0x0a, 0x00, (byte) 0x50, 0x21, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // SRP object 0x00, 0x1c, 0x00, 0x04, // PATH-SETUP-TYPE TLV 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x24, 0x00, // LSP object 0x00, 0x10, (byte) 0xAB, 0x00, 0x11, 0x00, 0x02, 0x54, 0x31, 0x00, 0x00, // symbolic path tlv 0x00, 0x12, 0x00, 0x10, // IPv4-LSP-IDENTIFIER-TLV 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x05, 0x05, 0x05, 0x07, 0x10, 0x00, 0x14, // ERO object 0x01, 0x08, (byte) 0x01, 0x01, 0x01, 0x01, 0x04, 0x00, // ERO IPv4 sub objects 0x01, 0x08, (byte) 0x05, 0x05, 0x05, 0x05, 0x04, 0x00, }; ChannelBuffer buffer = ChannelBuffers.dynamicBuffer(); buffer.writeBytes(reportMsg); PcepMessageReader<PcepMessage> reader = PcepFactories.getGenericReader(); PcepMessage message = reader.readFrom(buffer); PcepClientImpl pc = new PcepClientImpl(); PcepPacketStats pktStats = new PcepPacketStatsImpl(); pc.init(pccId, PcepVersion.PCEP_1, pktStats); pc.setChannel(channel); pc.setAgent(controllerImpl.agent); pc.setConnected(true); pc.setCapability(new ClientCapability(true, true, true, true, true)); controllerImpl.agent.addConnectedClient(pccId, pc); controllerImpl.processClientMessage(pccId, message); pc.setLspDbSyncStatus(PcepSyncStatus.SYNCED); pc.setLabelDbSyncStatus(PcepSyncStatus.IN_SYNC); pc.setLabelDbSyncStatus(PcepSyncStatus.SYNCED); } class PcepEventListenerAdapter implements PcepEventListener { public List<PcepMessage> handledMsg = new ArrayList<>(); public List<Tunnel> tunnelsToBeUpdatedToNw = new ArrayList<>(); public List<Tunnel> deletedFromNwTunnels = new ArrayList<>(); @Override public void handleMessage(PccId pccId, PcepMessage msg) { handledMsg.add(msg); } @Override public void handleEndOfSyncAction(Tunnel tunnel, PcepLspSyncAction endOfSyncAction) { if (endOfSyncAction == SEND_UPDATE) { tunnelsToBeUpdatedToNw.add(tunnel); return; } else if (endOfSyncAction == UNSTABLE) { deletedFromNwTunnels.add(tunnel); } } } class MockChannel implements Channel { private List<PcepMessage> msgOnWire = new ArrayList<>(); @Override public ChannelFuture write(Object o) { if (o instanceof List<?>) { @SuppressWarnings("unchecked") List<PcepMessage> msgs = (List<PcepMessage>) o; for (PcepMessage msg : msgs) { if (msg instanceof PcepInitiateMsg) { msgOnWire.add(msg); } } } return null; } public List<PcepMessage> msgsWritten() { return msgOnWire; } @Override public int compareTo(Channel o) { // TODO Auto-generated method stub return 0; } @Override public Integer getId() { // TODO Auto-generated method stub return null; } @Override public ChannelFactory getFactory() { // TODO Auto-generated method stub return null; } @Override public Channel getParent() { // TODO Auto-generated method stub return null; } @Override public ChannelConfig getConfig() { // TODO Auto-generated method stub return null; } @Override public ChannelPipeline getPipeline() { // TODO Auto-generated method stub return null; } @Override public boolean isOpen() { // TODO Auto-generated method stub return false; } @Override public boolean isBound() { // TODO Auto-generated method stub return false; } @Override public boolean isConnected() { // TODO Auto-generated method stub return false; } @Override public SocketAddress getLocalAddress() { // TODO Auto-generated method stub return null; } @Override public SocketAddress getRemoteAddress() { // TODO Auto-generated method stub return null; } @Override public ChannelFuture write(Object message, SocketAddress remoteAddress) { // TODO Auto-generated method stub return null; } @Override public ChannelFuture bind(SocketAddress localAddress) { // TODO Auto-generated method stub return null; } @Override public ChannelFuture connect(SocketAddress remoteAddress) { // TODO Auto-generated method stub return null; } @Override public ChannelFuture disconnect() { // TODO Auto-generated method stub return null; } @Override public ChannelFuture unbind() { // TODO Auto-generated method stub return null; } @Override public ChannelFuture close() { // TODO Auto-generated method stub return null; } @Override public ChannelFuture getCloseFuture() { // TODO Auto-generated method stub return null; } @Override public int getInterestOps() { // TODO Auto-generated method stub return 0; } @Override public boolean isReadable() { // TODO Auto-generated method stub return false; } @Override public boolean isWritable() { // TODO Auto-generated method stub return false; } @Override public ChannelFuture setInterestOps(int interestOps) { // TODO Auto-generated method stub return null; } @Override public ChannelFuture setReadable(boolean readable) { // TODO Auto-generated method stub return null; } @Override public boolean getUserDefinedWritability(int index) { // TODO Auto-generated method stub return false; } @Override public void setUserDefinedWritability(int index, boolean isWritable) { // TODO Auto-generated method stub } @Override public Object getAttachment() { // TODO Auto-generated method stub return null; } @Override public void setAttachment(Object attachment) { // TODO Auto-generated method stub } } class MockTunnelService implements TunnelService { private HashMap<TunnelId, Tunnel> tunnelIdAsKeyStore = new HashMap<TunnelId, Tunnel>(); private int tunnelIdCounter = 0; @Override public TunnelId setupTunnel(ApplicationId producerId, ElementId srcElementId, Tunnel tunnel, Path path) { TunnelId tunnelId = TunnelId.valueOf(String.valueOf(++tunnelIdCounter)); Tunnel tunnelToInsert = new DefaultTunnel(tunnel.providerId(), tunnel.src(), tunnel.dst(), tunnel.type(), tunnel.state(), tunnel.groupId(), tunnelId, tunnel.tunnelName(), path, tunnel.annotations()); tunnelIdAsKeyStore.put(tunnelId, tunnelToInsert); return tunnelId; } @Override public Tunnel queryTunnel(TunnelId tunnelId) { for (TunnelId tunnelIdKey : tunnelIdAsKeyStore.keySet()) { if (tunnelIdKey.equals(tunnelId)) { return tunnelIdAsKeyStore.get(tunnelId); } } return null; } @Override public Collection<Tunnel> queryTunnel(TunnelEndPoint src, TunnelEndPoint dst) { Collection<Tunnel> result = new HashSet<Tunnel>(); Tunnel tunnel = null; for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) { tunnel = tunnelIdAsKeyStore.get(tunnelId); if ((null != tunnel) && (src.equals(tunnel.src())) && (dst.equals(tunnel.dst()))) { result.add(tunnel); } } return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result); } @Override public Collection<Tunnel> queryTunnel(Tunnel.Type type) { Collection<Tunnel> result = new HashSet<Tunnel>(); for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) { result.add(tunnelIdAsKeyStore.get(tunnelId)); } return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result); } @Override public Collection<Tunnel> queryAllTunnels() { Collection<Tunnel> result = new HashSet<Tunnel>(); for (TunnelId tunnelId : tunnelIdAsKeyStore.keySet()) { result.add(tunnelIdAsKeyStore.get(tunnelId)); } return result.size() == 0 ? Collections.emptySet() : ImmutableSet.copyOf(result); } @Override public void addListener(TunnelListener listener) { // TODO Auto-generated method stub } @Override public void removeListener(TunnelListener listener) { // TODO Auto-generated method stub } @Override public Tunnel borrowTunnel(ApplicationId consumerId, TunnelId tunnelId, Annotations... annotations) { // TODO Auto-generated method stub return null; } @Override public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelName tunnelName, Annotations... annotations) { // TODO Auto-generated method stub return null; } @Override public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst, Annotations... annotations) { // TODO Auto-generated method stub return null; } @Override public Collection<Tunnel> borrowTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst, Type type, Annotations... annotations) { // TODO Auto-generated method stub return null; } @Override public boolean downTunnel(ApplicationId producerId, TunnelId tunnelId) { // TODO Auto-generated method stub return false; } @Override public boolean returnTunnel(ApplicationId consumerId, TunnelId tunnelId, Annotations... annotations) { // TODO Auto-generated method stub return false; } @Override public boolean returnTunnel(ApplicationId consumerId, TunnelName tunnelName, Annotations... annotations) { // TODO Auto-generated method stub return false; } @Override public boolean returnTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst, Type type, Annotations... annotations) { // TODO Auto-generated method stub return false; } @Override public boolean returnTunnel(ApplicationId consumerId, TunnelEndPoint src, TunnelEndPoint dst, Annotations... annotations) { // TODO Auto-generated method stub return false; } @Override public Collection<TunnelSubscription> queryTunnelSubscription(ApplicationId consumerId) { // TODO Auto-generated method stub return null; } @Override public int tunnelCount() { // TODO Auto-generated method stub return 0; } @Override public Iterable<Tunnel> getTunnels(DeviceId deviceId) { // TODO Auto-generated method stub return null; } } }