IETF 105 Hackathon

From Yuma123 Wiki
Revision as of 19:34, 21 July 2019 by Vladimir (talk | contribs) (→‎Plan)
Jump to navigationJump to search

Plan

From https://trac.ietf.org/trac/ietf/meeting/wiki/105hackathon :

Transactional network test framework for flow capable bridge nodes ( OpenFlow, NETCONF )
   * Champion(s)
     * Vladimir Vassilev <vladimir at transpacket.com>
   * Project(s)
     * Drafts
       * A YANG Data Model for Network Bridge Management
       * A YANG Data Model for Network Interconnect Tester Management
     * Node side (netconfd)
       * traffic-generator and traffic-analyzer modules for Linux
       * flow capable network bridge module OpenFlow->NETCONF convertor
     * Controller side (OpenDaylight)
       * Plugin for flow capable nodes with YANG/NETCONF interface
     * Application side (python-tntapi, python-litenc, yangcli)
       * RFC2544 implementation
     * Environment (mininet)
       * Topology instantiation script
   * References
      * https://tools.ietf.org/html/draft-vassilev-netmod-network-bridge
      * https://tools.ietf.org/html/draft-vassilev-bmwg-network-interconnect-tester
      * https://github.com/vlvassilev/yuma123/example-modules

Progress

  • SIL module implementing ietf-traffic-generator.yang for netconfd

YANG tree:

   |  |  +--:(multi-stream)
   |  |     +--rw streams
   |  |        +--rw stream* [id]
   |  |           +--rw id                   uint32
   |  |           +--rw frame-size           uint32
   |  |           +--rw (frame-data-type)?
   |  |           |  +--:(raw-frame-data)
   |  |           |     +--rw frame-data?    string
   |  |           +--rw interframe-gap       uint32
   |  |           +--rw interburst-gap?      uint32
   |  |           +--rw frames-per-burst?    uint32
   |  |           +--rw frames-per-stream    uint32
   |  |           +--rw interstream-gap      uint32
   |  |           +--rw src-mac-address?     yang:mac-address {ethernet}?
   |  |           +--rw dst-mac-address?     yang:mac-address {ethernet}?
   |  |           +--rw ether-type?          uint16 {ethernet}?
   |  |           +--rw (encapsulation)? {ethernet}?
   |  |              +--:(vlan)
   |  |                 +--rw vlan {ethernet-vlan}?
   |  |                    +--rw id      uint16
   |  |                    +--rw tpid?   uint16
   |  |                    +--rw pcp?    uint8
   |  |                    +--rw cfi?    uint8
   |  +--rw total-frames?             uint64


C implementation:

    /* 2 step (delete/add) interface configuration */

    /* 1. deactivation loop - deletes all deleted or modified interface/traffic-generator -s */
    if(interfaces_cur_val!=NULL) {
        for (interface_cur_val = val_get_first_child(interfaces_cur_val);
             interface_cur_val != NULL;
             interface_cur_val = val_get_next_child(interface_cur_val)) {
            traffic_generator_cur_val = val_find_child(interface_cur_val, TG_MOD, "traffic-generator");
            if(traffic_generator_cur_val==NULL) {
                continue;
            }
            traffic_generator_new_val = val123_find_match(config_new_val, traffic_generator_cur_val);
            if(traffic_generator_new_val==NULL || 0!=val_compare_ex(traffic_generator_cur_val,traffic_generator_new_val,TRUE)) {
                traffic_generator_delete(traffic_generator_cur_val);
            }
        }
    }

    /* 2. activation loop - adds all new or modified interface/traffic-generator -s */
    if(interfaces_new_val!=NULL) {
        for (interface_new_val = val_get_first_child(interfaces_new_val);
             interface_new_val != NULL;
             interface_new_val = val_get_next_child(interface_new_val)) {
            traffic_generator_new_val = val_find_child(interface_new_val, TG_MOD, "traffic-generator");
            if(traffic_generator_new_val==NULL) {
                continue;
            }
            traffic_generator_cur_val = val123_find_match(config_cur_val, traffic_generator_new_val);
            if(traffic_generator_cur_val==NULL || 0!=val_compare_ex(traffic_generator_new_val,traffic_generator_cur_val,TRUE)) {
                traffic_generator_create(traffic_generator_new_val);
            }
        }
    }

...

#include <stdint.h>

typedef struct burst_t_ {
    uint32_t frame_length;
    uint8_t* raw_frame_data;
    uint32_t interframe_gap;
    uint32_t frames_per_burst;
    uint32_t interburst_gap;
} burst_t;

typedef struct stream_t_ {
    unsigned int bursts_per_stream;
    unsigned int burst_index;
    uint32_t interstream_gap;
    burst_t* bursts;
} stream_t;

typedef struct traffic_generator_t_ {
    uint64_t total_frames;
    uint64_t total_frame_index;
    uint64_t sec;
    uint32_t nsec;
    float ns_per_octet;
    stream_t* streams;
    unsigned int streams_num;
    unsigned int stream_index;
    unsigned int burst_index;
    unsigned int frame_index;
} traffic_generator_t;


traffic_generator_t* traffic_generator_init(const char* config_str);
int traffic_generator_get_frame(traffic_generator_t* tg, uint32_t* frame_length, uint8_t** frame, uint64_t* tx_time_sec, uint32_t* tx_time_nsec);

...

    while(1) {
        ret = traffic_generator_get_frame(tg, &frame_len, &frame_buf, &tx_time_sec, &tx_time_nsec);
        if(ret!=0) {
            break;
        }
        clock_gettime( CLOCK_MONOTONIC, &now);
        rel.tv_sec = tx_time_sec;        /* seconds */
        rel.tv_nsec = tx_time_nsec;      /* nanoseconds */
        timespec_add(&rel, &epoch, &abs);
        timespec_sub(&now, &abs, &req);
        ret=nanosleep(&req,&rem);
        //assert(ret==0);
        ret = raw_socket_send(&raw_socket, frame_buf, frame_len);
        assert(ret==0);

        if(now.tv_sec>print_sec) {
            print_sec=now.tv_sec;
            printf("%llu\n",frm);
        }
        frm++;
    }