Skip to the content.

[TOC]


To run these examples, mmt-dpi must be installed first (see Compilation and Installation).

All example source code is in src/examples/ (root of the repo). This page walks through five of the seven examples there; MAC_extraction.c and mmt_export_info.c — the latter advertised in the README — are not covered by the walkthroughs below.

Attributes Listing

This example is intended to provide the list of available protocols and for each protocol, the list of its attributes.

#include <stdio.h>
#include <stdlib.h>
#include "mmt_core.h"

void attributes_iterator(attribute_metadata_t * attribute, uint32_t proto_id, void * args) {
  //Print the attribute ID and Name
  printf("\tAttribute id %i --- Name %s \n", attribute->id, attribute->alias);
}

void protocols_iterator(uint32_t proto_id, void * args) {
  //Print the protocol ID and Name (get_protocol_name_by_id)
  printf("Protocol id %i --- Name %s\n", proto_id, get_protocol_name_by_id(proto_id));
  //Iterate through the attributes of this protocol
  iterate_through_protocol_attributes(proto_id, attributes_iterator, NULL);
}
int main(int argc, char** argv) {
  init_extraction(); //Initialize MMT

  iterate_through_protocols(protocols_iterator, NULL); //Iterate through all registered protocols

  close_extraction();//We are done, close MMT
  return (EXIT_SUCCESS);
}

Compile the example:

gcc -o proto_attributes_iterator proto_attributes_iterator.c -I /opt/mmt/dpi/include -L /opt/mmt/dpi/lib -lmmt_core -ldl -lpthread

Run the example:

./proto_attributes_iterator

The output is the list of available protocols and for each protocol, the list of its attributes.

If you want to test with your own plugins, place them in /opt/mmt/plugins (the default plugin directory — the prefix contract is stated once, in Agent Environment Notes §4) or create a plugins/ folder alongside the example binary.

Extract All

This example is intended to extract everything! This means all the attributes of all registered protocols will be registered for extraction. When a packet is processed, the attributes found in the packet will be printed out.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>
#include <unistd.h>
#include "mmt_core.h"

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

#define MAX_FILENAME_SIZE 256
#define TRACE_FILE 1
#define LIVE_INTERFACE 2
#define MTU_BIG (16 * 1024)

static int quiet;

void usage(const char * prg_name) {
    fprintf(stderr, "%s [<option>]\n", prg_name);
    fprintf(stderr, "Option:\n");
    fprintf(stderr, "\t-t <trace file>: Gives the trace file to analyse.\n");
    fprintf(stderr, "\t-i <interface> : Gives the interface name for live traffic analysis.\n");
    fprintf(stderr, "\t-q             : Be quiet (no output whatsoever, helps profiling).\n");
    fprintf(stderr, "\t-h             : Prints this help.\n");
    exit(1);
}

void parseOptions(int argc, char ** argv, char * filename, int * type) {
    int opt, optcount = 0;
    while ((opt = getopt(argc, argv, "t:i:qh")) != EOF) {
        switch (opt) {
            case 't':
                optcount++;
                if (optcount > 1) {
                    usage(argv[0]);
                }
                strncpy((char *) filename, optarg, MAX_FILENAME_SIZE);
                *type = TRACE_FILE;
                break;
            case 'i':
                optcount++;
                if (optcount > 1) {
                    usage(argv[0]);
                }
                strncpy((char *) filename, optarg, MAX_FILENAME_SIZE);
                *type = LIVE_INTERFACE;
                break;
            case 'q':
                quiet = 1;
                break;
            case 'h':
            default: usage(argv[0]);
        }
    }

    if (filename == NULL || strcmp(filename, "") == 0) {
        if (*type == TRACE_FILE) {
            fprintf(stderr, "Missing trace file name\n");
        }
        if (*type == LIVE_INTERFACE) {
            fprintf(stderr, "Missing network interface name\n");
        }
        usage(argv[0]);
    }
    return;
}

void attributes_iterator(attribute_metadata_t * attribute, uint32_t proto_id, void * args) {
    //Register for extraction the attribute identified by the given protocol and attribute ids
    register_extraction_attribute(args, proto_id, attribute->id);
}

void protocols_iterator(uint32_t proto_id, void * args) {
    //Iterate through the attributes of the protocol with the given ID. For every attribute call the given callback function
    iterate_through_protocol_attributes(proto_id, attributes_iterator, args);
}

void live_capture_callback( u_char *user, const struct pcap_pkthdr *p_pkthdr, const u_char *data )
{
    mmt_handler_t *mmt = (mmt_handler_t*)user;
    struct pkthdr header;
    header.ts = p_pkthdr->ts;
    header.caplen = p_pkthdr->caplen;
    header.len = p_pkthdr->len;
    if (!packet_process( mmt, &header, data )) {
        fprintf(stderr, "Packet data extraction failure.\n");
    }
}

int main(int argc, char** argv) {
    mmt_handler_t *mmt_handler; //MMT handler
    char mmt_errbuf[1024];
    struct pkthdr header; //MMT packet header

    pcap_t *pcap;
    const unsigned char *data;
    struct pcap_pkthdr p_pkthdr;
    char errbuf[1024];
    char filename[MAX_FILENAME_SIZE + 1];
    int type;

    quiet = 0;
    parseOptions(argc, argv, filename, &type);

    //First of all initialize MMT
    init_extraction();

    //Initialize an MMT handler
    mmt_handler = mmt_init_handler(DLT_EN10MB, 0, mmt_errbuf);
    if (!mmt_handler) { /* pcap error ? */
        fprintf(stderr, "MMT handler init failed for the following reason: %s\n", mmt_errbuf);
        return EXIT_FAILURE;
    }

    //Iterate through registered protocols and call the given function for every one
    iterate_through_protocols(protocols_iterator, mmt_handler);

    //Register a packet handler, it will be called for every processed packet
    register_packet_handler(mmt_handler, 1, debug_extracted_attributes_printout_handler /* built in packet handler that will print all of the attributes */, &quiet);

    if (type == TRACE_FILE) {
        pcap = pcap_open_offline(filename, errbuf); // open offline trace
        if (!pcap) { /* pcap error ? */
            fprintf(stderr, "pcap_open failed for the following reason: %s\n", errbuf);
            return EXIT_FAILURE;
        }

        while ((data = pcap_next(pcap, &p_pkthdr))) {
            header.ts = p_pkthdr.ts;
            header.caplen = p_pkthdr.caplen;
            header.len = p_pkthdr.len;
            if (!packet_process(mmt_handler, &header, data)) {
                fprintf(stderr, "Packet data extraction failure.\n");
            }
        }
    } else {
        pcap = pcap_open_live(filename, MTU_BIG, 1, 1000, errbuf);
        if (!pcap) {
            fprintf(stderr, "pcap_open failed for the following reason: %s\n", errbuf);
            return EXIT_FAILURE;
        }
        (void)pcap_loop( pcap, -1, &live_capture_callback, (u_char*)mmt_handler );
    }

    //Close the MMT handler.
    mmt_close_handler(mmt_handler);

    //Close MMT.
    close_extraction();

    pcap_close(pcap);

    return EXIT_SUCCESS;
}

To compile the example:

gcc -g -o extract_all extract_all.c -I /opt/mmt/dpi/include -L /opt/mmt/dpi/lib -lmmt_core -ldl -lpcap

We can extract from a .pcap file, which can be generated by using WireShark tool .

./extract_all -t pcapfile.pcap

We also can extract from live stream. Need sudo permission

sudo ./extract_all -i eth0

The output is all the attributes of al registered protocols.

Packet Handler

This example is intended to show a simple packet handler. That is a callback function that will be called after the processing of every packet by the MMT core.

#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include "mmt_core.h"

void packet_handler(const ipacket_t * ipacket, void * user_args) {
    uint32_t * p_len # (uint32_t *) get_attribute_extracted_data_by_name(ipacket, "META", "PACKET_LEN"); //The names are case insensitive
    if(p_len) {
        printf("Received packet of size %u\n", *p_len);
    }
}

int main(int argc, char** argv) {
    mmt_handler_t *mmt_handler; //MMT Handler
    struct pkthdr header; //MMT packet header
    char mmt_errbuf[1024];

    pcap_t *pcap;
    const unsigned char *data;
    struct pcap_pkthdr p_pkthdr;
    char errbuf[1024];

    //First of all initialize the extraction engine
    init_extraction();

    //Initialize the MMT handler
    mmt_handler # mmt_init_handler(DLT_EN10MB, 0, mmt_errbuf);
    if (!mmt_handler) {
        fprintf(stderr, "MMT handler init failed for the following reason: %s\n", mmt_errbuf);
        return EXIT_FAILURE;
    }

    //Register the protocol attributes we need
    register_extraction_attribute_by_name(mmt_handler, "META", "PACKET_LEN"); //request the packet length. This is a META attribute.

    //Register a packet handler, it will be called for every processed packet
    register_packet_handler(mmt_handler, 1, packet_handler, NULL);

    pcap # pcap_open_offline(argv[1], errbuf); // open offline trace
    if (!pcap) { /* pcap error ? */
        fprintf(stderr, "pcap_open failed for the following reason: %s\n", errbuf);
        return EXIT_FAILURE;
    }
    while ((data # pcap_next(pcap, &p_pkthdr))) {
        header.ts # p_pkthdr.ts;
        header.caplen # p_pkthdr.caplen;
        header.len # p_pkthdr.len;
        if (!packet_process(mmt_handler, &header, data)) {
            fprintf(stderr, "Packet data extraction failure.\n");
            return EXIT_FAILURE;
        }
    }
    //Close the MMT handler
    mmt_close_handler(mmt_handler);

    //At the end close the extraction engine
    close_extraction();

    pcap_close(pcap);
    return EXIT_SUCCESS;
}

Compile this example with:

gcc -g -o packet_handler packet_handler.c -I /opt/mmt/dpi/include -L /opt/mmt/dpi/lib -lmmt_core -ldl -lpcap

Execute the program:

./packet_handler pcapDataFile.pcap

The output is the size of received packets.

Attribute Handler (Sessions counter)

This example is intended to show a simple attribute handler - count number of session.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcap.h>
#include "mmt_core.h"

#define __STDC_FORMAT_MACROS
#include <inttypes.h>

void session_attr_handler(const ipacket_t * ipacket, attribute_t * attribute, void * user_args) {
  *(uint64_t*) user_args # *(uint64_t*) user_args +1;
  printf("Session with id # %"PRIu64" is detected --- Total number of sessions is %"PRIu64"\n", ipacket->session->session_id, *(uint64_t *) user_args);
  // The session id is also accessible through: (uint64_t *) attribute->data
}

int main(int argc, char** argv) {
  mmt_handler_t *mmt_handler;
  struct pkthdr header;
  char mmt_errbuf[1024];

  pcap_t *pcap;
  const unsigned char *data;
  struct pcap_pkthdr p_pkthdr;
  char errbuf[1024];

  uint64_t sessions_count # 0;

  //First of all initialize the extraction engine
  init_extraction();

  //Initialize an MMT handler
  mmt_handler # mmt_init_handler(DLT_EN10MB, 0, mmt_errbuf);
  if (!mmt_handler) { /* pcap error ? */
    fprintf(stderr, "MMT handler init failed for the following reason: %s\n", mmt_errbuf);
    return EXIT_FAILURE;
  }

  //Register an attribute handler, it will be called for every time the indicated attribute is detected
  register_attribute_handler_by_name(
    mmt_handler,
    "IP", "SESSION",
    session_attr_handler,
    NULL /* Will be ignored, should be set to NULL */,
    &sessions_count
  );

  pcap # pcap_open_offline(argv[1], errbuf); // open offline trace
  if (!pcap) { /* pcap error ? */
    fprintf(stderr, "pcap_open failed for the following reason: %s\n", errbuf);
    return EXIT_FAILURE;
  }

  while ((data # pcap_next(pcap, &p_pkthdr))) {
    header.ts # p_pkthdr.ts;
    header.caplen # p_pkthdr.caplen;
    header.len # p_pkthdr.len;
    if (!packet_process(mmt_handler, &header, data)) {
      fprintf(stderr, "Packet data extraction failure.\n");
    }
  }

  //Close the MMT handler
  mmt_close_handler(mmt_handler);

  //At the end close the extraction engine
  close_extraction();

  pcap_close(pcap);
  return EXIT_SUCCESS;
}

Compile the example:

gcc -o attribute_handler_session_counter attribute_handler_session_counter.c -I /opt/mmt/dpi/include -L /opt/mmt/dpi/lib -lmmt_core -ldl -lpcap

Execute the example:

./attribute_handler_session_counter pcapDataFile.pcap

The output is the number of session

Simple Traffic Reporting

This example is intended to extract the statistics of all streams.

#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <time.h>
#include "mmt_core.h"
#include "mmt/tcpip/mmt_tcpip.h"
#ifdef WIN32
#include <ws2tcpip.h>
#include <windows.h>
#ifndef socklen_t
typedef int socklen_t;
#define socklen_t socklen_t
#endif
#else
#include <netinet/in.h>
#endif
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
    typedef struct ipv4_ipv6_id_struct {
        union {
            uint32_t ipv4;
            uint8_t ipv6[16];
        };
    } ipv4_ipv6_id_t;
    typedef struct internal_session_struct {
        ipv4_ipv6_id_t ipclient;
        ipv4_ipv6_id_t ipserver;
        uint16_t clientport;
        uint16_t serverport;
        uint8_t proto;
        uint8_t ipversion;
    } internal_session_struct_t;
#define TIMEVAL_2_MSEC(tval) ((tval.tv_sec << 10) + (tval.tv_usec >> 10))
void usage(const char *prg_name) {
    fprintf(stderr, "%s <pcap file>\n", prg_name);
}
int proto_hierarchy_names_to_str(const proto_hierarchy_t * proto_hierarchy, char * dest) {
    int offset = 0;
    if (proto_hierarchy->len < 1) {
        offset += sprintf(dest, ".");
    } else {
        int index = 1;
        offset += sprintf(dest, "%s", get_protocol_name_by_id(proto_hierarchy->proto_path[index]));
        index++;
        for (; index < proto_hierarchy->len && index < 16; index++) {
            offset += sprintf(&dest[offset], ".%s", get_protocol_name_by_id(proto_hierarchy->proto_path[index]));
        }
    }
    return offset;
}
void new_flow_handle(const ipacket_t * ipacket, attribute_t * attribute, void * user_args) {
    if(ipacket->session == NULL) return;
    if (attribute->data == NULL) {
        return; //This should never happen! check it anyway
    }
    internal_session_struct_t *temp_session = malloc(sizeof (internal_session_struct_t));
    if (temp_session == NULL) {
        return;
    }
    memset(temp_session, '\0', sizeof (internal_session_struct_t));
    // Flow extraction
    int ipindex = get_protocol_index_by_id(ipacket, PROTO_IP);
    //Process IPv4 flows
    if (ipindex != -1) {
        uint32_t * ip_src = (uint32_t *) get_attribute_extracted_data(ipacket, PROTO_IP, IP_SRC);
        uint32_t * ip_dst = (uint32_t *) get_attribute_extracted_data(ipacket, PROTO_IP, IP_DST);
        if (ip_src) {
            temp_session->ipclient.ipv4 = (*ip_src);
        }
        if (ip_dst) {
            temp_session->ipserver.ipv4 = (*ip_dst);
        }
        uint8_t * proto_id = (uint8_t *) get_attribute_extracted_data(ipacket, PROTO_IP, IP_PROTO_ID);
        if (proto_id != NULL) {
            temp_session->proto = *proto_id;
        } else {
            temp_session->proto = 0;
        }
        temp_session->ipversion = 4;
        uint16_t * cport = (uint16_t *) get_attribute_extracted_data(ipacket, PROTO_IP, IP_CLIENT_PORT);
        uint16_t * dport = (uint16_t *) get_attribute_extracted_data(ipacket, PROTO_IP, IP_SERVER_PORT);
        if (cport) {
            temp_session->clientport = *cport;
        }
        if (dport) {
            temp_session->serverport = *dport;
        }
    } else {
        void * ipv6_src = (void *) get_attribute_extracted_data(ipacket, PROTO_IPV6, IP6_SRC);
        void * ipv6_dst = (void *) get_attribute_extracted_data(ipacket, PROTO_IPV6, IP6_DST);
        if (ipv6_src) {
            memcpy(&temp_session->ipclient.ipv6, ipv6_src, 16);
        }
        if (ipv6_dst) {
            memcpy(&temp_session->ipserver.ipv6, ipv6_dst, 16);
        }
        uint8_t * proto_id = (uint8_t *) get_attribute_extracted_data(ipacket, PROTO_IPV6, IP6_NEXT_PROTO);
        if (proto_id != NULL) {
            temp_session->proto = *proto_id;
        } else {
            temp_session->proto = 0;
        }
        temp_session->ipversion = 6;
        uint16_t * cport = (uint16_t *) get_attribute_extracted_data(ipacket, PROTO_IPV6, IP6_CLIENT_PORT);
        uint16_t * dport = (uint16_t *) get_attribute_extracted_data(ipacket, PROTO_IPV6, IP6_SERVER_PORT);
        if (cport) {
            temp_session->clientport = *cport;
        }
        if (dport) {
            temp_session->serverport = *dport;
        }
    }
    set_user_session_context_for_packet(ipacket,temp_session);
    // ipacket->session->user_data = temp_session;
}
void session_expiry_handle(const mmt_session_t * expired_session, void * args) {
    FILE * out_file = (args != NULL) ? args : stdout;
    int keep_direction = 1;
    internal_session_struct_t * temp_session = get_user_session_context(expired_session);
    if (temp_session == NULL) {
        return;
    }
    //IP strings
    char ip_src_str[46];
    char ip_dst_str[46];
    if (temp_session->ipversion == 4) {
        inet_ntop(AF_INET, (void *) &temp_session->ipclient.ipv4, ip_src_str, INET_ADDRSTRLEN);
        inet_ntop(AF_INET, (void *) &temp_session->ipserver.ipv4, ip_dst_str, INET_ADDRSTRLEN);
        //keep_direction = is_local_net(temp_session->ipclient.ipv4);
    } else {
        inet_ntop(AF_INET6, (void *) &temp_session->ipclient.ipv6, ip_src_str, INET6_ADDRSTRLEN);
        inet_ntop(AF_INET6, (void *) &temp_session->ipserver.ipv6, ip_dst_str, INET6_ADDRSTRLEN);
    }
    uint32_t rtt_ms = TIMEVAL_2_MSEC(get_session_rtt(expired_session));
    char path[512];
    proto_hierarchy_names_to_str(get_session_protocol_hierarchy(expired_session), path);
    int proto_index = ((get_session_protocol_hierarchy(expired_session))->len <= 16) ? ((get_session_protocol_hierarchy(expired_session))->len - 1) : (16 - 1);
    int proto_id = (get_session_protocol_hierarchy(expired_session))->proto_path[proto_index];
    fprintf(out_file, "%"PRIu64",%lu.%lu,%lu.%lu,"
            "%u,%s,%s,%hu,%hu,%hu,"
            "%"PRIu64",%"PRIu64",%"PRIu64",%"PRIu64",%u,%u,%s,%s,%s"
            "\n",
            get_session_id(expired_session),
            (get_session_last_activity_time(expired_session)).tv_sec, (get_session_last_activity_time(expired_session)).tv_usec,
            (get_session_init_time(expired_session)).tv_sec, (get_session_init_time(expired_session)).tv_usec,
            (int) temp_session->ipversion,
            ip_dst_str, ip_src_str,
            temp_session->serverport, temp_session->clientport, (unsigned short) temp_session->proto,
            (keep_direction) ? get_session_ul_packet_count(expired_session) : get_session_dl_packet_count(expired_session),
            (keep_direction) ? get_session_dl_packet_count(expired_session) : get_session_ul_packet_count(expired_session),
            (keep_direction) ? get_session_ul_byte_count(expired_session): get_session_dl_byte_count(expired_session),
            (keep_direction) ? get_session_dl_byte_count(expired_session) : get_session_ul_byte_count(expired_session),
            rtt_ms, get_session_retransmission_count(expired_session),
            get_application_class_name_by_protocol_id(proto_id),
            path, get_protocol_name_by_id(proto_id)
            );
}
int main(int argc, const char **argv) {
    mmt_handler_t *mmt_handler, *m1;
    char mmt_errbuf[1024];
    int packets_count = 0;
    pcap_t *pcap;
    const u_char *data;
    struct pkthdr header;
    struct pcap_pkthdr pkthdr;
    char errbuf[1024];
    int ret;
    //flows = NULL;
    if (argc < 2) {
        usage(argv[0]);
        return EXIT_FAILURE;
    }
    pcap = pcap_open_offline(argv[1], errbuf); // open offline trace
    //pcap = pcap_open_offline("../mmt_dpi_test/imesh_p2p.pcap", errbuf); // open offline trace
    if (!pcap) { /* pcap error ? */
        fprintf(stderr, "pcap_open: %s\n", errbuf);
        return EXIT_FAILURE;
    }
    if (!init_extraction()) { // general ixE initialization
        fprintf(stderr, "MMT extract init error\n");
        return EXIT_FAILURE;
    }
    //Initialize an MMT handler
    mmt_handler = mmt_init_handler(DLT_EN10MB, 0, mmt_errbuf);
    if (!mmt_handler) { /* pcap error ? */
        fprintf(stderr, "MMT handler init failed for the following reason: %s\n", mmt_errbuf);
        return EXIT_FAILURE;
    }
    // customized packet and session handling functions are then registered
    register_session_timeout_handler(mmt_handler, session_expiry_handle, NULL);
    register_extraction_attribute(mmt_handler, PROTO_IP, IP_SRC);
    register_extraction_attribute(mmt_handler, PROTO_IP, IP_DST);
    register_extraction_attribute(mmt_handler, PROTO_IP, IP_PROTO_ID);
    register_extraction_attribute(mmt_handler, PROTO_IP, IP_SERVER_PORT);
    register_extraction_attribute(mmt_handler, PROTO_IP, IP_CLIENT_PORT);
    register_extraction_attribute(mmt_handler, PROTO_TCP, TCP_SRC_PORT);
    register_extraction_attribute(mmt_handler, PROTO_TCP, TCP_DEST_PORT);
    register_extraction_attribute(mmt_handler, PROTO_IPV6, IP6_NEXT_PROTO);
    register_extraction_attribute(mmt_handler, PROTO_IPV6, IP6_SRC);
    register_extraction_attribute(mmt_handler, PROTO_IPV6, IP6_DST);
    register_extraction_attribute(mmt_handler, PROTO_IPV6, IP6_SERVER_PORT);
    register_extraction_attribute(mmt_handler, PROTO_IPV6, IP6_CLIENT_PORT);
    register_attribute_handler(mmt_handler, PROTO_IP, PROTO_SESSION, new_flow_handle, NULL, NULL);
    register_attribute_handler(mmt_handler, PROTO_IPV6, PROTO_SESSION, new_flow_handle, NULL, NULL);
    printf("Start timestamp, End timestamp, Flow id, "
            "IP version, Server IP, Client IP, Server Port, Client Port, "
            "Proto, UL Packets, DL Packets, UL Volume, DL Volume, "
            "RTT, TCP retransmissions, Application Class, Proto Path, Application\n");
    struct timeval tval;
    gettimeofday(&tval, NULL);
    fprintf(stderr, "Time %lu.%lu\n", tval.tv_sec, tval.tv_usec);
    while ((data = pcap_next(pcap, &pkthdr))) {
        header.ts = pkthdr.ts;
        header.caplen = pkthdr.caplen;
        header.len = pkthdr.len;
        //header.msg_type = 0;
        //if(0) {
        if (!packet_process(mmt_handler, &header, data)) {
            fprintf(stderr, "Error 106: Packet data extraction failure.\n");
        }
        packets_count++;
    }
    mmt_close_handler(mmt_handler);
    gettimeofday(&tval, NULL);
    fprintf(stderr, "Time %lu.%lu\n", tval.tv_sec, tval.tv_usec);
    close_extraction();
    pcap_close(pcap);
    printf("Process Terimated successfully\n");
    return EXIT_SUCCESS;
}

Compile this example with:

gcc -o simple_traffic_reporting simple_traffic_reporting.c -lmmt_core -lmmt_tcpip -ldl -lpcap

To test example:

./simple_traffic_reporting pcapDataFile.pcap > simple_traffic_reporting.txt