trema/trema-edge

View on GitHub
src/examples/openflow_message/group_mod.c

Summary

Maintainability
Test Coverage
/*
 * Copyright (C) 2013 NEC Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */


#include "trema.h"


static void
handle_multipart_reply( uint64_t datapath_id, uint32_t transaction_id, uint16_t type,
                        uint16_t flags, const buffer *data, void *user_data ) {
  UNUSED( user_data );

  if ( type != OFPMP_GROUP_DESC ) {
    return;
  }

  info( "datapath_id: %#" PRIx64, datapath_id );
  info( "transaction_id: %x", transaction_id );
  info( "type: %u", type );
  info( "flags: %u", flags );
  struct ofp_group_desc *group_desc = ( struct ofp_group_desc * ) data->data;
  size_t length = data->length;
  while ( length >= sizeof( struct ofp_group_desc ) ) {
    info( "group_id: %u", group_desc->group_id );
    info( "  type: %u", group_desc->type );
    struct ofp_bucket *bucket = group_desc->buckets;
    uint16_t bucket_length = ( uint16_t ) ( group_desc->length - offsetof( struct ofp_group_desc, buckets ) );
    while ( bucket_length >= sizeof( struct ofp_bucket ) ) {
      info( "  bucket:" );
      info( "    weight: %u", bucket->weight );
      info( "    watch_port: %u", bucket->watch_port );
      info( "    watch_group: %u", bucket->watch_group );
      uint16_t action_length = ( uint16_t ) ( bucket->len - offsetof( struct ofp_bucket, actions ) );
      char actions_str[ 4096 ];
      actions_str[ 0 ] = '\0';
      if ( action_length > 0 ) {
    actions_to_string( bucket->actions, action_length, actions_str, sizeof( actions_str ) );
      }
      info( "    actions: %s", actions_str );

      bucket_length = ( uint16_t ) ( bucket_length - bucket->len );
      bucket = ( struct ofp_bucket * ) ( ( char * ) bucket + bucket->len );
    }

    length -= group_desc->length;
    group_desc = ( struct ofp_group_desc * ) ( ( char * ) group_desc + group_desc->length );
  }
}


static void
send_group_mod( uint64_t datapath_id ) {

  openflow_actions *actions = create_actions();
  append_action_output( actions, OFPP_CONTROLLER, OFPCML_NO_BUFFER );
  openflow_buckets *buckets = create_buckets();
  append_bucket( buckets, 0, 0, 0, actions );

  buffer *group_mod = create_group_mod(
    get_transaction_id(),
    OFPGC_ADD,
    OFPGT_INDIRECT,
    200,
    buckets
  );
  send_openflow_message( datapath_id, group_mod );
  free_buffer( group_mod );

  delete_buckets( buckets );
  delete_actions( actions );
}


static void
send_group_desc_multipart_request( uint64_t datapath_id ) {
  buffer *group_desc_multipart_request = create_group_desc_multipart_request( get_transaction_id(), 0 );
  send_openflow_message( datapath_id, group_desc_multipart_request );
  free_buffer( group_desc_multipart_request );
}


static void
handle_switch_ready( uint64_t datapath_id, void *user_data ) {
  UNUSED( user_data );
  send_group_mod( datapath_id );
  send_group_desc_multipart_request( datapath_id );
}


int
main( int argc, char *argv[] ) {
  init_trema( &argc, &argv );

  set_switch_ready_handler( handle_switch_ready, NULL );
  set_multipart_reply_handler( handle_multipart_reply, NULL );

  start_trema();

  return 0;
}


/*
 * Local variables:
 * c-basic-offset: 2
 * indent-tabs-mode: nil
 * End:
 */