com.exalttech.trex.util.PacketUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.exalttech.trex.util.PacketUtil.java

Source

/**
 * *****************************************************************************
 * Copyright (c) 2016
 *
 * 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 com.exalttech.trex.util;

import com.exalttech.trex.packets.TrexEthernetPacket;
import com.exalttech.trex.packets.TrexVlanPacket;
import com.exalttech.trex.simulator.models.EthernetData;
import com.exalttech.trex.simulator.models.IPV4Data;
import com.exalttech.trex.simulator.models.PacketData;
import com.exalttech.trex.simulator.models.PacketLength;
import com.exalttech.trex.simulator.models.PayloadData;
import com.exalttech.trex.remote.models.profiles.Profile;
import com.exalttech.trex.ui.models.PacketInfo;
import com.exalttech.trex.ui.views.streams.builder.PacketBuilderHelper;
import com.exalttech.trex.ui.views.streams.builder.Payload;
import com.exalttech.trex.ui.views.streams.builder.PayloadType;
import com.exalttech.trex.ui.views.streams.builder.VMInstructionBuilder;
import com.exalttech.trex.ui.views.streams.viewer.PacketParser;
import com.exalttech.trex.util.files.FileManager;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.pcap4j.core.NotOpenException;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.Pcaps;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.IllegalRawDataException;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.EtherType;

/**
 *
 * Utility class
 *
 * @author Georgekh
 */
public class PacketUtil {

    private static final Logger LOG = Logger.getLogger(PacketUtil.class.getName());
    private final TrafficProfile trafficProfile = new TrafficProfile();
    private final String filePath;
    private final String STL_SIM_COMMAND;

    public PacketUtil() {
        filePath = FileManager.getProfilesFilePath();
        STL_SIM_COMMAND = "./stl-sim -f " + filePath + "[FILE_NAME].yaml -o " + filePath
                + "generated_[FILE_NAME].pcap -l 10 ";
    }

    /**
     * @param packetRawData
     * @return encoded data
     */
    public String getEncodedPacket(byte[] packetRawData) {
        String hexDataString = PacketBuilderHelper.getPacketHex(packetRawData);
        return trafficProfile.encodeBinaryFromHexString(hexDataString);
    }

    /**
     * Decode string and return packet info data
     *
     * @param encodedBinaryPacket
     * @return packet info
     * @throws IOException
     */
    public PacketInfo getPacketInfoData(String encodedBinaryPacket) throws IOException {
        // decode binary data
        File pcapFile = trafficProfile.decodePcapBinary(encodedBinaryPacket);
        PacketInfo packetInfo = new PacketInfo();
        PacketParser parser = new PacketParser();
        parser.parseFile(pcapFile.getAbsolutePath(), packetInfo);
        return packetInfo;
    }

    /**
     * @param packet
     * @return packet length
     * @throws org.pcap4j.packet.IllegalRawDataException
     */
    public int getPacketLength(Packet packet) throws IllegalRawDataException {
        return trafficProfile.getPacketTypeText(packet).getLength();
    }

    /**
     * Get packet from encoded string
     *
     * @param encodedBinaryPacket
     * @return packet
     * @throws IllegalRawDataException
     */
    public Packet getPacketFromEncodedString(String encodedBinaryPacket) throws IllegalRawDataException {
        byte[] pkt = Base64.decodeBase64(encodedBinaryPacket);
        return EthernetPacket.newPacket(pkt, 0, pkt.length);
    }

    /**
     * Read file as String
     *
     * @param fileName
     * @return
     * @throws IOException
     * @throws URISyntaxException
     */
    public String getFileContent(String fileName) throws IOException, URISyntaxException {
        return new String(Files.readAllBytes(Paths.get(getClass().getResource("/files/" + fileName).toURI())));
    }

    /**
     * Run stl-sim command to generates pcap file
     *
     * @param fileName
     * @throws IOException
     * @throws InterruptedException
     */
    public void generatePcapFile(String fileName) throws IOException, InterruptedException {
        String line;
        String command = STL_SIM_COMMAND.replace("[FILE_NAME]", fileName);
        Process process = Runtime.getRuntime().exec(command);
        BufferedReader bufferReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        while ((line = bufferReader.readLine()) != null) {
            LOG.info("line: " + line);
        }
        process.waitFor();
        process.destroy();
    }

    /**
     * Compare 2 pcap files, return true if equal, otherwise return false
     *
     * @param firstPCAP
     * @param secondPCAP
     * @return
     * @throws PcapNativeException
     * @throws NotOpenException
     */
    public boolean comparePcaps(String firstPCAP, String secondPCAP)
            throws PcapNativeException, NotOpenException, URISyntaxException {
        LOG.info("Comparing pcap files");
        List<String> firstPcapPacketList = getpcapPacketList(
                getClass().getResource("/pcaps/" + firstPCAP + ".pcap").toURI().getPath());
        List<String> secondPcapPacketList = getpcapPacketList(filePath + secondPCAP + ".pcap");
        if (firstPcapPacketList.size() != secondPcapPacketList.size()) {
            return false;
        }
        boolean equal = true;
        for (int index = 0; index < firstPcapPacketList.size(); index++) {
            equal = equal && (firstPcapPacketList.get(index).equals(secondPcapPacketList.get(index)));
        }
        return equal;
    }

    /**
     * Read pcap file to get all includes packet
     *
     * @param pcapFile
     * @return
     * @throws PcapNativeException
     * @throws NotOpenException
     */
    private List<String> getpcapPacketList(String pcapFile) throws PcapNativeException, NotOpenException {
        PcapHandle handler = Pcaps.openOffline(pcapFile);
        Packet packet = null;
        List<String> packetList = new ArrayList<>();
        while ((packet = handler.getNextPacket()) != null) {
            packetList.add(Hex.encodeHexString(packet.getRawData()));
        }
        return packetList;
    }

    /**
     * Create vm instruction
     *
     * @param packetData
     * @return vm instruction
     */
    public Map<String, Object> getVm(PacketData packetData) {
        VMInstructionBuilder vmInstructionBuilder = new VMInstructionBuilder(packetData.isTaggedVlan(),
                packetData.getUdpData().isEnable());
        ArrayList<Object> instructionsList = new ArrayList<>();

        // add VM instructions
        EthernetData ethernetData = packetData.getEthernetData();
        instructionsList.addAll(vmInstructionBuilder.addVmInstruction(VMInstructionBuilder.InstructionType.MAC_DST,
                ethernetData.getDstAddress().getType(), ethernetData.getDstAddress().getCount(),
                ethernetData.getDstAddress().getStep(), ethernetData.getDstAddress().getAddress()));
        instructionsList.addAll(vmInstructionBuilder.addVmInstruction(VMInstructionBuilder.InstructionType.MAC_SRC,
                ethernetData.getSrcAddress().getType(), ethernetData.getSrcAddress().getCount(),
                ethernetData.getSrcAddress().getStep(), ethernetData.getSrcAddress().getAddress()));

        IPV4Data ipv4Data = packetData.getIpv4Data();
        instructionsList.addAll(vmInstructionBuilder.addVmInstruction(VMInstructionBuilder.InstructionType.IP_DST,
                ipv4Data.getDstAddress().getType(), ipv4Data.getDstAddress().getCount(), "1",
                ipv4Data.getDstAddress().getAddress()));
        instructionsList.addAll(vmInstructionBuilder.addVmInstruction(VMInstructionBuilder.InstructionType.IP_SRC,
                ipv4Data.getSrcAddress().getType(), ipv4Data.getSrcAddress().getCount(), "1",
                ipv4Data.getSrcAddress().getAddress()));
        // add ipv4 checksum instructions
        instructionsList.addAll(vmInstructionBuilder.addChecksumInstruction());
        // add packet length instruction
        PacketLength packetLength = packetData.getPacketLength();
        instructionsList.addAll(vmInstructionBuilder.getPacketLenVMInstruction("pkt_len",
                packetLength.getLengthType(), String.valueOf(packetLength.getMinLength()),
                String.valueOf(packetLength.getMaxLength()), packetData.isTaggedVlan()));

        Map<String, Object> additionalProperties = new HashMap<>();

        LinkedHashMap<String, Object> vmBody = new LinkedHashMap<>();
        vmBody.put("split_by_var", vmInstructionBuilder.getSplitByVar());
        vmBody.put("instructions", instructionsList);

        // add cache size
        vmInstructionBuilder.addCacheSize(vmBody);

        additionalProperties.put("vm", vmBody);

        return additionalProperties;
    }

    /**
     * Parse data file to extract test data info
     *
     * @param fileName
     * @return
     * @throws IOException
     * @throws URISyntaxException
     */
    public Object[][] parsePacketDataFile(String fileName) throws IOException, URISyntaxException {
        String fileData = getFileContent(fileName);
        List<PacketData> data = new ObjectMapper().readValue(fileData, new TypeReference<List<PacketData>>() {
        });
        Object[][] dataList = new Object[data.size()][1];
        for (int i = 0; i < data.size(); i++) {
            dataList[i][0] = data.get(i);
        }
        return dataList;
    }

    /**
     * Create payload
     *
     * @param payloadData
     * @return
     */
    public Payload getPayload(PayloadData payloadData) {
        Payload payload = new Payload();
        payload.setPayloadPattern(payloadData.getPattern());
        payload.setPayloadType(PayloadType.getPayloadType(payloadData.getType()));
        return payload;
    }

    /**
     * Prepare and save yaml file
     *
     * @param packetRawData
     * @param packetData
     * @throws JsonProcessingException
     * @throws IOException
     */
    public void prepareAndSaveYamlFile(byte[] packetRawData, PacketData packetData)
            throws JsonProcessingException, IOException {

        String encodedBinaryPacket = getEncodedPacket(packetRawData);
        // save pqacket in the profile
        Profile profile = new Profile();
        profile.setName("stream0");
        profile.getStream().getMode().setType("continuous");
        profile.getStream().getPacket().setBinary(encodedBinaryPacket);
        profile.getStream().setAdditionalProperties(getVm(packetData));

        // save data to yaml file
        List<Profile> profileList = new ArrayList();
        profileList.add(profile);
        String yamlData = trafficProfile
                .getProfileYamlContent(profileList.toArray(new Profile[profileList.size()]));

        File newFile = FileManager.createNewFile(packetData.getTestFileName() + ".yaml");
        FileUtils.writeStringToFile(newFile, yamlData);
    }

    /**
     * Prepare Ethernet packet
     *
     * @param packetData
     * @param packetLength
     * @param payload
     * @return
     */
    public TrexEthernetPacket prepareEthernetPacket(PacketData packetData, int packetLength, Payload payload) {
        TrexEthernetPacket ethernetPacket = new TrexEthernetPacket();
        ethernetPacket.setSrcAddr(packetData.getEthernetData().getSrcAddress().getAddress());
        ethernetPacket.setDstAddr(packetData.getEthernetData().getDstAddress().getAddress());

        ethernetPacket.setLength(packetLength);

        ethernetPacket.setPayload(payload);

        return ethernetPacket;
    }

    /**
     * Add VLan to the generated packet
     *
     * @param ethernetPacket
     * @param ipV4Packet
     */
    public void addVlanToPacket(TrexEthernetPacket ethernetPacket, IpV4Packet.Builder ipV4Packet) {
        LOG.info("Add VLAN data");
        ethernetPacket.setType(EtherType.DOT1Q_VLAN_TAGGED_FRAMES.value());
        TrexVlanPacket vlanPacket = new TrexVlanPacket();
        if (ipV4Packet == null) {
            ethernetPacket.setAddPad(true);
            vlanPacket.setType((short) 0xFFFF);
        } else {
            vlanPacket.setType(EtherType.IPV4.value());
        }
        vlanPacket.buildPacket(ipV4Packet);
        ethernetPacket.buildPacket(vlanPacket.getBuilder());
    }
}