| /* |
| * Copyright 2016 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.ospf.protocol.ospfpacket.types; |
| |
| import com.google.common.base.MoreObjects; |
| import com.google.common.primitives.Bytes; |
| import org.jboss.netty.buffer.ChannelBuffer; |
| import org.onosproject.ospf.controller.OspfLsa; |
| import org.onosproject.ospf.exceptions.OspfErrorType; |
| import org.onosproject.ospf.exceptions.OspfParseException; |
| import org.onosproject.ospf.protocol.lsa.LsaHeader; |
| import org.onosproject.ospf.protocol.lsa.OpaqueLsaHeader; |
| import org.onosproject.ospf.protocol.lsa.types.AsbrSummaryLsa; |
| import org.onosproject.ospf.protocol.lsa.types.ExternalLsa; |
| import org.onosproject.ospf.protocol.lsa.types.NetworkLsa; |
| import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa10; |
| import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa11; |
| import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa9; |
| import org.onosproject.ospf.protocol.lsa.types.RouterLsa; |
| import org.onosproject.ospf.protocol.lsa.types.SummaryLsa; |
| import org.onosproject.ospf.protocol.ospfpacket.OspfPacketHeader; |
| import org.onosproject.ospf.protocol.util.OspfPacketType; |
| import org.onosproject.ospf.protocol.util.OspfParameters; |
| import org.onosproject.ospf.protocol.util.OspfUtil; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| import java.util.ArrayList; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| /** |
| * Representation of an OSPF Link State Update packet. |
| * Link State Update packets are OSPF packet type 4. These packets |
| * implement the flooding of LSAs. Each Link State Update packet |
| * carries a collection of LSAs one hop further from their origin. |
| * Several LSAs may be included in a single packet. |
| */ |
| public class LsUpdate extends OspfPacketHeader { |
| /* |
| 0 1 2 3 |
| 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Version # | 4 | Packet length | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Router ID | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Area ID | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Checksum | AuType | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Authentication | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | Authentication | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | # LSAs | |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | | |
| +- +-+ |
| | LSAs | |
| +- +-+ |
| | ... | |
| */ |
| private static final Logger log = LoggerFactory.getLogger(LsUpdate.class); |
| private int numberOfLsa; |
| private List<OspfLsa> lsaList = new LinkedList<>(); |
| |
| /** |
| * Creates an instance of Link State Update packet. |
| */ |
| public LsUpdate() { |
| } |
| |
| /** |
| * Creates an instance of Link State Update packet. |
| * |
| * @param ospfHeader ospf header instance. |
| */ |
| public LsUpdate(OspfPacketHeader ospfHeader) { |
| populateHeader(ospfHeader); |
| } |
| |
| /** |
| * Gets the LSA list. |
| * |
| * @return list of LSA |
| */ |
| public List getLsaList() { |
| return lsaList; |
| } |
| |
| /** |
| * Adds the LSA to list. |
| * |
| * @param lsa LSA |
| */ |
| public void addLsa(OspfLsa lsa) { |
| if (!lsaList.contains(lsa)) { |
| lsaList.add(lsa); |
| } |
| } |
| |
| /** |
| * Gets the number of LSA. |
| * |
| * @return number of LSA |
| */ |
| public int noLsa() { |
| return numberOfLsa; |
| } |
| |
| /** |
| * Sets number of LSA. |
| * |
| * @param numberOfLsa number of LSA |
| */ |
| public void setNumberOfLsa(int numberOfLsa) { |
| this.numberOfLsa = numberOfLsa; |
| } |
| |
| |
| @Override |
| public OspfPacketType ospfMessageType() { |
| return OspfPacketType.LSUPDATE; |
| } |
| |
| @Override |
| public void readFrom(ChannelBuffer channelBuffer) throws OspfParseException { |
| try { |
| //From header 4 bytes is number of lsa's |
| this.setNumberOfLsa(channelBuffer.readInt()); |
| //get the remaining bytes represents Number of LSA's present. Add all the LSA's |
| while (channelBuffer.readableBytes() > OspfUtil.LSA_HEADER_LENGTH) { |
| |
| LsaHeader header = OspfUtil.readLsaHeader(channelBuffer.readBytes(OspfUtil.LSA_HEADER_LENGTH)); |
| int lsaLength = header.lsPacketLen(); |
| int lsType = header.lsType(); |
| |
| switch (lsType) { |
| case OspfParameters.LINK_LOCAL_OPAQUE_LSA: |
| OpaqueLsa9 opaqueLsa9 = new OpaqueLsa9((OpaqueLsaHeader) header); |
| opaqueLsa9.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH)); |
| addLsa(opaqueLsa9); |
| break; |
| case OspfParameters.AREA_LOCAL_OPAQUE_LSA: |
| OpaqueLsa10 opaqueLsa10 = new OpaqueLsa10((OpaqueLsaHeader) header); |
| opaqueLsa10.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH)); |
| addLsa(opaqueLsa10); |
| break; |
| case OspfParameters.AS_OPAQUE_LSA: |
| OpaqueLsa11 opaqueLsa11 = new OpaqueLsa11((OpaqueLsaHeader) header); |
| opaqueLsa11.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH)); |
| addLsa(opaqueLsa11); |
| break; |
| case OspfParameters.ROUTER: |
| RouterLsa routerLsa = new RouterLsa(header); |
| routerLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH)); |
| addLsa(routerLsa); |
| break; |
| case OspfParameters.NETWORK: |
| NetworkLsa networkLsa = new NetworkLsa(header); |
| networkLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH)); |
| addLsa(networkLsa); |
| break; |
| case OspfParameters.ASBR_SUMMARY: |
| AsbrSummaryLsa asbrSummaryLsa = new AsbrSummaryLsa(header); |
| asbrSummaryLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH)); |
| addLsa(asbrSummaryLsa); |
| break; |
| case OspfParameters.SUMMARY: |
| SummaryLsa summaryLsa = new SummaryLsa(header); |
| summaryLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH)); |
| addLsa(summaryLsa); |
| break; |
| case OspfParameters.EXTERNAL_LSA: |
| ExternalLsa externalLsa = new ExternalLsa(header); |
| externalLsa.readFrom(channelBuffer.readBytes(lsaLength - OspfUtil.LSA_HEADER_LENGTH)); |
| addLsa(externalLsa); |
| break; |
| default: |
| log.debug("LSUpdate::readLsUpdateBody::UnKnown LS Type: {}", lsType); |
| break; |
| } |
| } |
| } catch (Exception e) { |
| log.debug("Error::LsUpdate:: {}", e.getMessage()); |
| throw new OspfParseException(OspfErrorType.MESSAGE_HEADER_ERROR, OspfErrorType.BAD_MESSAGE_LENGTH); |
| } |
| } |
| |
| @Override |
| public byte[] asBytes() { |
| byte[] lsuMessage = null; |
| |
| byte[] ospfHeader = getLsuHeaderAsByteArray(); |
| byte[] lsuBody = getLsuBodyAsByteArray(); |
| lsuMessage = Bytes.concat(ospfHeader, lsuBody); |
| |
| return lsuMessage; |
| } |
| |
| /** |
| * Gets lsu header. |
| * |
| * @return lsu header as byte array |
| */ |
| public byte[] getLsuHeaderAsByteArray() { |
| List<Byte> headerLst = new ArrayList<>(); |
| try { |
| headerLst.add((byte) this.ospfVersion()); |
| headerLst.add((byte) this.ospfType()); |
| headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.ospfPacLength()))); |
| headerLst.addAll(Bytes.asList(this.routerId().toOctets())); |
| headerLst.addAll(Bytes.asList(this.areaId().toOctets())); |
| headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.checksum()))); |
| headerLst.addAll(Bytes.asList(OspfUtil.convertToTwoBytes(this.authType()))); |
| //Authentication is 0 always. Total 8 bytes consist of zero |
| byte[] auth = new byte[OspfUtil.EIGHT_BYTES]; |
| headerLst.addAll(Bytes.asList(auth)); |
| } catch (Exception e) { |
| log.debug("Error::LSUpdate::getLsuHeaderAsByteArray:: {}", e.getMessage()); |
| return Bytes.toArray(headerLst); |
| } |
| |
| return Bytes.toArray(headerLst); |
| } |
| |
| /** |
| * Get lsu body as byte array. |
| * |
| * @return lsu body as byte array |
| */ |
| public byte[] getLsuBodyAsByteArray() { |
| List<Byte> bodyLst = new ArrayList<>(); |
| |
| try { |
| //add number of LSA's |
| bodyLst.addAll(Bytes.asList(OspfUtil.convertToFourBytes(this.noLsa()))); |
| //for each type of LSA's from the list get lsa bytes |
| for (OspfLsa ospfLsa : lsaList) { |
| //Check the type of lsa and build bytes accordingly |
| switch (ospfLsa.getOspfLsaType().value()) { |
| case OspfParameters.LINK_LOCAL_OPAQUE_LSA: |
| OpaqueLsa9 opaqueLsa9 = (OpaqueLsa9) ospfLsa; |
| bodyLst.addAll(Bytes.asList(opaqueLsa9.asBytes())); |
| break; |
| case OspfParameters.AREA_LOCAL_OPAQUE_LSA: |
| OpaqueLsa10 opaqueLsa10 = (OpaqueLsa10) ospfLsa; |
| bodyLst.addAll(Bytes.asList(opaqueLsa10.asBytes())); |
| break; |
| case OspfParameters.AS_OPAQUE_LSA: |
| OpaqueLsa11 opaqueLsa11 = (OpaqueLsa11) ospfLsa; |
| bodyLst.addAll(Bytes.asList(opaqueLsa11.asBytes())); |
| break; |
| case OspfParameters.ROUTER: |
| RouterLsa routerLsa = (RouterLsa) ospfLsa; |
| bodyLst.addAll(Bytes.asList(routerLsa.asBytes())); |
| break; |
| case OspfParameters.NETWORK: |
| NetworkLsa networkLsa = (NetworkLsa) ospfLsa; |
| bodyLst.addAll(Bytes.asList(networkLsa.asBytes())); |
| break; |
| case OspfParameters.ASBR_SUMMARY: |
| AsbrSummaryLsa asbrSummaryLsa = (AsbrSummaryLsa) ospfLsa; |
| bodyLst.addAll(Bytes.asList(asbrSummaryLsa.asBytes())); |
| break; |
| case OspfParameters.SUMMARY: |
| SummaryLsa summaryLsa = (SummaryLsa) ospfLsa; |
| bodyLst.addAll(Bytes.asList(summaryLsa.asBytes())); |
| break; |
| case OspfParameters.EXTERNAL_LSA: |
| ExternalLsa externalLsa = (ExternalLsa) ospfLsa; |
| bodyLst.addAll(Bytes.asList(externalLsa.asBytes())); |
| break; |
| default: |
| log.debug("LSUpdate::getLsuBodyAsByteArray::UnKnown ospfLsa: {}", ospfLsa); |
| break; |
| } |
| } |
| |
| } catch (Exception e) { |
| log.debug("Error::getLsuBodyAsByteArray {}", e.getMessage()); |
| return Bytes.toArray(bodyLst); |
| } |
| |
| return Bytes.toArray(bodyLst); |
| } |
| |
| @Override |
| public String toString() { |
| return MoreObjects.toStringHelper(getClass()) |
| .omitNullValues() |
| .add("noLsa", numberOfLsa) |
| .add("lsaList", lsaList) |
| .toString(); |
| } |
| } |