Difference between revisions of "IETF 105 Hackathon"
From Yuma123 Wiki
Jump to navigationJump to search (→Plan) |
(→Plan) |
||
Line 21: | Line 21: | ||
* https://tools.ietf.org/html/draft-vassilev-bmwg-network-interconnect-tester |
* https://tools.ietf.org/html/draft-vassilev-bmwg-network-interconnect-tester |
||
* https://github.com/vlvassilev/yuma123/example-modules |
* 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: |
||
+ | |||
+ | <nowiki> |
||
+ | /* 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++; |
||
+ | } |
||
+ | |||
+ | </nowiki> |
Revision as of 19:34, 21 July 2019
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++; }