From bfc7a48ae678ca7a5e796c52fc5fc65892e49a0a Mon Sep 17 00:00:00 2001 From: lupo89 <19lupo89@gmail.com> Date: Wed, 3 Jun 2015 09:04:08 -0700 Subject: [PATCH] experimenter match field refactoring (V.0.1) --- lib/vconn.c | 8 +- lib/vlog.h | 2 + oflib-exp/ofl-exp-openflow.h | 3 - oflib-exp/ofl-exp-openstate.c | 308 +++++++- oflib-exp/ofl-exp-openstate.h | 40 +- oflib-exp/ofl-exp.c | 42 +- oflib-exp/ofl-exp.h | 12 +- oflib/ofl-messages-pack.c | 6 +- oflib/ofl-messages-unpack.c | 2 +- oflib/ofl-structs-match.c | 108 --- oflib/ofl-structs-pack.c | 2 +- oflib/ofl-structs-unpack.c | 6 +- oflib/ofl.h | 25 +- oflib/oxm-match.c | 208 +---- oflib/oxm-match.h | 4 +- udatapath/datapath.c | 12 +- udatapath/dp_exp.c | 6 +- udatapath/flow_table.c | 5 +- udatapath/flow_table.h | 2 +- udatapath/match_std.c | 25 +- udatapath/match_std.h | 2 +- udatapath/packet_handle_std.c | 5 +- udatapath/packet_handle_std.h | 2 +- udatapath/pipeline.c | 9 +- udatapath/udatapath.c | 5 +- utilities/dpctl.c | 8 +- utilities/dpctl.c.bak | 1408 ++++++++++++++++++++++++++++----- 27 files changed, 1694 insertions(+), 571 deletions(-) diff --git a/lib/vconn.c b/lib/vconn.c index 059234b..6abc405 100644 --- a/lib/vconn.c +++ b/lib/vconn.c @@ -90,12 +90,18 @@ static struct ofl_exp_stats ofl_exp_stats = .reply_free = ofl_exp_stats_reply_free, .reply_to_string = ofl_exp_stats_reply_to_string}; +static struct ofl_exp_field ofl_exp_field = + {.unpack = ofl_exp_field_unpack, + .pack = ofl_exp_field_pack, + .match = ofl_exp_field_match}; + static struct ofl_exp ofl_exp = {.act = &ofl_exp_act, .inst = NULL, .match = NULL, .stats = &ofl_exp_stats, - .msg = &ofl_exp_msg}; + .msg = &ofl_exp_msg, + .field = &ofl_exp_field}; static struct vconn_class *vconn_classes[] = { &tcp_vconn_class, diff --git a/lib/vlog.h b/lib/vlog.h index 17d107d..2cca695 100644 --- a/lib/vlog.h +++ b/lib/vlog.h @@ -196,5 +196,7 @@ void print_file(const char* format, ...); } while (0) extern enum vlog_level min_vlog_levels[VLM_N_MODULES]; +void +pfile(const char* format, ...); #endif /* vlog.h */ diff --git a/oflib-exp/ofl-exp-openflow.h b/oflib-exp/ofl-exp-openflow.h index fa80a6f..f48223c 100644 --- a/oflib-exp/ofl-exp-openflow.h +++ b/oflib-exp/ofl-exp-openflow.h @@ -90,7 +90,4 @@ ofl_exp_openflow_act_free(struct ofl_action_header *act); char * ofl_exp_openflow_act_to_string(struct ofl_action_header *act); -void -ofl_exp_stats_type_print(FILE *stream, uint32_t type); - #endif /* OFL_EXP_OPENFLOW_H */ diff --git a/oflib-exp/ofl-exp-openstate.c b/oflib-exp/ofl-exp-openstate.c index d7979e5..e236154 100644 --- a/oflib-exp/ofl-exp-openstate.c +++ b/oflib-exp/ofl-exp-openstate.c @@ -13,6 +13,7 @@ #include "oflib/ofl-structs.h" #include "oflib/oxm-match.h" #include "lib/hash.h" +#include "lib/ofp.h" #define LOG_MODULE ofl_exp_os @@ -563,7 +564,7 @@ ofl_exp_openstate_stats_reply_pack(struct ofl_msg_multipart_reply_experimenter * } ofl_err -ofl_exp_openstate_stats_req_unpack(struct ofp_multipart_request *os, uint8_t* buf, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp) { +ofl_exp_openstate_stats_req_unpack(struct ofp_multipart_request *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp) { struct ofp_experimenter_stats_header *ext = (struct ofp_experimenter_stats_header *)os->body; switch (ntohl(ext->exp_type)){ @@ -601,7 +602,7 @@ ofl_exp_openstate_stats_req_unpack(struct ofp_multipart_request *os, uint8_t* bu return error; } - *msg = (struct ofl_msg_header *)dm; + *msg = (struct ofl_msg_multipart_request_header *)dm; return 0; } case (OFPMP_EXP_FLAGS_STATS): @@ -611,7 +612,7 @@ ofl_exp_openstate_stats_req_unpack(struct ofp_multipart_request *os, uint8_t* bu dm->header.type = ntohl(ext->exp_type); dm->header.header.experimenter_id = ntohl(ext->experimenter); *len -= sizeof(struct ofp_exp_global_state_stats_request); - *msg = (struct ofl_msg_header *)dm; + *msg = (struct ofl_msg_multipart_request_header *)dm; return 0; } default: @@ -620,7 +621,7 @@ ofl_exp_openstate_stats_req_unpack(struct ofp_multipart_request *os, uint8_t* bu } ofl_err -ofl_exp_openstate_stats_reply_unpack(struct ofp_multipart_reply *os, uint8_t* buf, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp) { +ofl_exp_openstate_stats_reply_unpack(struct ofp_multipart_reply *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp) { struct ofp_experimenter_stats_header *ext = (struct ofp_experimenter_stats_header *)os->body; @@ -659,7 +660,7 @@ ofl_exp_openstate_stats_reply_unpack(struct ofp_multipart_reply *os, uint8_t* bu stat = (struct ofp_state_stats *)((uint8_t *)stat + ntohs(stat->length)); } - *msg = (struct ofl_msg_header *)dm; + *msg = (struct ofl_msg_multipart_request_header *)dm; return 0; } case (OFPMP_EXP_FLAGS_STATS): @@ -816,6 +817,190 @@ ofl_exp_openstate_stats_reply_free(struct ofl_msg_multipart_reply_header *msg) { return 0; } +/*experimenter match fields*/ + +static void +oxm_put_exp_header(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id) +{ + uint32_t n_header = htonl(header); + ofpbuf_put(buf, &n_header, sizeof n_header); + ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); + +} + +static void +oxm_put_exp_8(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint8_t value) +{ + oxm_put_exp_header(buf, header, experimenter_id); + ofpbuf_put(buf, &value, sizeof value); +} + +static void +oxm_put_exp_8w(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint8_t value, uint8_t mask) +{ + oxm_put_exp_header(buf, header, experimenter_id); + ofpbuf_put(buf, &value, sizeof value); + ofpbuf_put(buf, &mask, sizeof mask); +} + +static void +oxm_put_exp_16(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint16_t value) +{ + oxm_put_exp_header(buf, header, experimenter_id); + ofpbuf_put(buf, &value, sizeof value); +} + +static void +oxm_put_exp_16w(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint16_t value, uint16_t mask) +{ + oxm_put_exp_header(buf, header, experimenter_id); + ofpbuf_put(buf, &value, sizeof value); + ofpbuf_put(buf, &mask, sizeof mask); +} + +static void +oxm_put_exp_32(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint32_t value) +{ + oxm_put_exp_header(buf, header, experimenter_id); + ofpbuf_put(buf, &value, sizeof value); +} + +static void +oxm_put_exp_32w(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint32_t value, uint32_t mask) +{ + oxm_put_exp_header(buf, header, experimenter_id); + ofpbuf_put(buf, &value, sizeof value); + ofpbuf_put(buf, &mask, sizeof mask); +} + +static void +oxm_put_exp_64(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint64_t value) +{ + oxm_put_exp_header(buf, header, experimenter_id); + ofpbuf_put(buf, &value, sizeof value); +} + +static void +oxm_put_exp_64w(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint64_t value, uint64_t mask) +{ + oxm_put_exp_header(buf, header, experimenter_id); + ofpbuf_put(buf, &value, sizeof value); + ofpbuf_put(buf, &mask, sizeof mask); +} + +int +ofl_exp_openstate_field_unpack(struct ofl_match *match, struct oxm_field *f, void *experimenter_id, void *value, void *mask) { + switch (f->index) { + case OFI_OXM_EXP_STATE:{ + ofl_structs_match_put32e(match, f->header, ntohl(*((uint32_t*) experimenter_id)), ntohl(*((uint32_t*) value))); + return 0; + } + case OFI_OXM_EXP_STATE_W:{ + if (check_bad_wildcard32(ntohl(*((uint32_t*) value)), ntohl(*((uint32_t*) mask)))){ + return ofp_mkerr(OFPET_BAD_MATCH, OFPBMC_BAD_WILDCARDS); + } + ofl_structs_match_put32me(match, f->header, ntohl(*((uint32_t*) experimenter_id)), ntohl(*((uint32_t*) value)), ntohl(*((uint32_t*) mask))); + return 0; + } + case OFI_OXM_EXP_FLAGS:{ + ofl_structs_match_put32e(match, f->header, ntohl(*((uint32_t*) experimenter_id)), ntohl(*((uint32_t*) value))); + return 0; + } + case OFI_OXM_EXP_FLAGS_W:{ + if (check_bad_wildcard32(ntohl(*((uint32_t*) value)), ntohl(*((uint32_t*) mask)))){ + return ofp_mkerr(OFPET_BAD_MATCH, OFPBMC_BAD_WILDCARDS); + } + ofl_structs_match_put32me(match, f->header, ntohl(*((uint32_t*) experimenter_id)), ntohl(*((uint32_t*) value)), ntohl(*((uint32_t*) mask))); + return 0; + } + default: + NOT_REACHED(); + } +} + +void +ofl_exp_openstate_field_pack(struct ofpbuf *buf, struct ofl_match_tlv *oft){ + uint8_t length = OXM_LENGTH(oft->header); + bool has_mask =false; + + length = length - EXP_ID_LEN; /* field length should exclude experimenter_id */ + if (OXM_HASMASK(oft->header)){ + length = length / 2; + has_mask = true; + } + switch (length){ + case (sizeof(uint8_t)):{ + uint32_t experimenter_id; + uint8_t value; + memcpy(&experimenter_id, oft->value, sizeof(uint32_t)); + memcpy(&value, oft->value + EXP_ID_LEN, sizeof(uint8_t)); + if(!has_mask) + oxm_put_exp_8(buf,oft->header, htonl(experimenter_id), value); + else { + uint8_t mask; + memcpy(&mask, oft->value + EXP_ID_LEN + length , sizeof(uint8_t)); + oxm_put_exp_8w(buf, oft->header, htonl(experimenter_id), value, mask); + } + break; + } + case (sizeof(uint16_t)):{ + uint32_t experimenter_id; + uint16_t value; + memcpy(&experimenter_id, oft->value, sizeof(uint32_t)); + memcpy(&value, oft->value + EXP_ID_LEN, sizeof(uint16_t)); + if(!has_mask) + oxm_put_exp_16(buf,oft->header, htonl(experimenter_id), htons(value)); + else { + uint16_t mask; + memcpy(&mask, oft->value + EXP_ID_LEN + length , sizeof(uint16_t)); + oxm_put_exp_16w(buf, oft->header, htonl(experimenter_id), htons(value), htons(mask)); + } + break; + } + case (sizeof(uint32_t)):{ + uint32_t experimenter_id, value; + memcpy(&experimenter_id, oft->value, sizeof(uint32_t)); + memcpy(&value, oft->value + EXP_ID_LEN, sizeof(uint32_t)); + if(!has_mask) + oxm_put_exp_32(buf,oft->header, htonl(experimenter_id), htonl(value)); + else { + uint32_t mask; + memcpy(&mask, oft->value + EXP_ID_LEN + length , sizeof(uint32_t)); + oxm_put_exp_32w(buf, oft->header, htonl(experimenter_id), htonl(value), htonl(mask)); + } + break; + } + case (sizeof(uint64_t)):{ + uint32_t experimenter_id; + uint64_t value; + memcpy(&experimenter_id, oft->value, sizeof(uint32_t)); + memcpy(&value, oft->value + EXP_ID_LEN, sizeof(uint64_t)); + if(!has_mask) + oxm_put_exp_64(buf,oft->header, htonl(experimenter_id), hton64(value)); + else { + uint64_t mask; + memcpy(&mask, oft->value + EXP_ID_LEN + length , sizeof(uint64_t)); + oxm_put_exp_64w(buf, oft->header, htonl(experimenter_id), hton64(value), hton64(mask)); + } + break; + } + } +} + +void +ofl_exp_openstate_field_match(struct ofl_match_tlv *f, int *packet_header, int *field_len, uint8_t **flow_val, uint8_t **flow_mask){ + bool has_mask = OXM_HASMASK(f->header); + (*field_len) = (OXM_LENGTH(f->header) - EXP_ID_LEN); + *flow_val = f->value + EXP_ID_LEN; + if (has_mask) { + /* Clear the has_mask bit and divide the field_len by two in the packet field header */ + *field_len /= 2; + (*packet_header) &= 0xfffffe00; + (*packet_header) |= (*field_len) + EXP_ID_LEN; + *flow_mask = f->value + EXP_ID_LEN + (*field_len); + } +} + /*experimenter table functions*/ int __extract_key(uint8_t *, struct key_extractor *, struct packet *); @@ -1114,7 +1299,7 @@ handle_stats_request_state(struct pipeline *pl, struct ofl_exp_msg_multipart_req } ofl_err -handle_stats_request_global_state(struct pipeline *pl, struct ofl_exp_msg_multipart_request_global_state *msg, const struct sender *sender, struct ofl_exp_msg_multipart_reply_global_state *reply) { +handle_stats_request_global_state(struct pipeline *pl, const struct sender *sender, struct ofl_exp_msg_multipart_reply_global_state *reply) { uint32_t global_states = pl->dp->global_states; *reply = (struct ofl_exp_msg_multipart_reply_global_state) @@ -1772,3 +1957,114 @@ oxm_pull_match_no_prereqs(struct ofpbuf *buf, struct ofl_match * match_dst, int } */ + +/*Functions used by experimenter match fields*/ + +void +ofl_structs_match_put8e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint8_t value){ + struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); + int len = sizeof(uint8_t); + + m->header = header; + m->value = malloc(EXP_ID_LEN + len); + memcpy(m->value, &experimenter_id, EXP_ID_LEN); + memcpy(m->value + EXP_ID_LEN, &value, len); + hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); + match->header.length += EXP_ID_LEN + len + 4; +} + +void +ofl_structs_match_put8me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint8_t value, uint8_t mask){ + struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); + int len = sizeof(uint8_t); + + m->header = header; + m->value = malloc(EXP_ID_LEN + len*2); + memcpy(m->value, &experimenter_id, EXP_ID_LEN); + memcpy(m->value + EXP_ID_LEN, &value, len); + memcpy(m->value + EXP_ID_LEN + len, &mask, len); + hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); + match->header.length += EXP_ID_LEN + len*2 + 4; +} + +void +ofl_structs_match_put16e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint16_t value){ + struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); + int len = sizeof(uint16_t); + + m->header = header; + m->value = malloc(EXP_ID_LEN + len); + memcpy(m->value, &experimenter_id, EXP_ID_LEN); + memcpy(m->value + EXP_ID_LEN, &value, len); + hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); + match->header.length += EXP_ID_LEN + len + 4; +} + +void +ofl_structs_match_put16me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint16_t value, uint16_t mask){ + struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); + int len = sizeof(uint16_t); + + m->header = header; + m->value = malloc(EXP_ID_LEN + len*2); + memcpy(m->value, &experimenter_id, EXP_ID_LEN); + memcpy(m->value + EXP_ID_LEN, &value, len); + memcpy(m->value + EXP_ID_LEN + len, &mask, len); + hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); + match->header.length += EXP_ID_LEN + len*2 + 4; +} + +void +ofl_structs_match_put32e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint32_t value){ + struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); + int len = sizeof(uint32_t); + + m->header = header; + m->value = malloc(EXP_ID_LEN + len); + memcpy(m->value, &experimenter_id, EXP_ID_LEN); + memcpy(m->value + EXP_ID_LEN, &value, len); + hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); + match->header.length += EXP_ID_LEN + len + 4; +} + +void +ofl_structs_match_put32me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint32_t value, uint32_t mask){ + struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); + int len = sizeof(uint32_t); + + m->header = header; + m->value = malloc(EXP_ID_LEN + len*2); + memcpy(m->value, &experimenter_id, EXP_ID_LEN); + memcpy(m->value + EXP_ID_LEN, &value, len); + memcpy(m->value + EXP_ID_LEN + len, &mask, len); + hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); + match->header.length += EXP_ID_LEN + len*2 + 4; +} + +void +ofl_structs_match_put64e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint64_t value){ + struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); + int len = sizeof(uint64_t); + + m->header = header; + m->value = malloc(EXP_ID_LEN + len); + memcpy(m->value, &experimenter_id, EXP_ID_LEN); + memcpy(m->value + EXP_ID_LEN, &value, len); + hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); + match->header.length += EXP_ID_LEN + len + 4; +} + +void +ofl_structs_match_put64me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint64_t value, uint64_t mask){ + struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); + int len = sizeof(uint64_t); + + m->header = header; + m->value = malloc(EXP_ID_LEN + len*2); + memcpy(m->value, &experimenter_id, EXP_ID_LEN); + memcpy(m->value + EXP_ID_LEN, &value, len); + memcpy(m->value + EXP_ID_LEN + len, &mask, len); + hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); + match->header.length += EXP_ID_LEN + len*2 + 4; +} + diff --git a/oflib-exp/ofl-exp-openstate.h b/oflib-exp/ofl-exp-openstate.h index e4e069e..8e71342 100644 --- a/oflib-exp/ofl-exp-openstate.h +++ b/oflib-exp/ofl-exp-openstate.h @@ -234,10 +234,10 @@ char * ofl_exp_openstate_stats_reply_to_string(struct ofl_msg_multipart_reply_experimenter *ext, struct ofl_exp *exp); ofl_err -ofl_exp_openstate_stats_req_unpack(struct ofp_multipart_request *os, uint8_t* buf, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp); +ofl_exp_openstate_stats_req_unpack(struct ofp_multipart_request *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp); ofl_err -ofl_exp_openstate_stats_reply_unpack(struct ofp_multipart_reply *os, uint8_t* buf, size_t *len, struct ofl_msg_header **msg, struct ofl_exp *exp); +ofl_exp_openstate_stats_reply_unpack(struct ofp_multipart_reply *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp); int ofl_exp_openstate_stats_req_free(struct ofl_msg_multipart_request_header *msg); @@ -245,6 +245,16 @@ ofl_exp_openstate_stats_req_free(struct ofl_msg_multipart_request_header *msg); int ofl_exp_openstate_stats_reply_free(struct ofl_msg_multipart_reply_header *msg); +/*experimenter match fields functions*/ +int +ofl_exp_openstate_field_unpack(struct ofl_match *match, struct oxm_field *f, void *experimenter_id, void *value, void *mask); + +void +ofl_exp_openstate_field_pack(struct ofpbuf *buf, struct ofl_match_tlv *oft); + +void +ofl_exp_openstate_field_match(struct ofl_match_tlv *f, int *packet_header, int *field_len, uint8_t **flow_val, uint8_t **flow_mask); + /* Handles a flag_mod message */ ofl_err handle_flag_mod(struct pipeline *pl, struct ofl_exp_msg_flag_mod *msg, const struct sender *sender); @@ -259,7 +269,7 @@ handle_stats_request_state(struct pipeline *pl, struct ofl_exp_msg_multipart_req /* Handles a global state stats request. */ ofl_err -handle_stats_request_global_state(struct pipeline *pl, struct ofl_exp_msg_multipart_request_global_state *msg, const struct sender *sender, struct ofl_exp_msg_multipart_reply_global_state *reply); +handle_stats_request_global_state(struct pipeline *pl, const struct sender *sender, struct ofl_exp_msg_multipart_reply_global_state *reply); void state_table_stats(struct state_table *table, struct ofl_exp_msg_multipart_request_state *msg, @@ -300,7 +310,31 @@ int oxm_pull_match_no_prereqs(struct ofpbuf *buf, struct ofl_match * match_dst, int match_len); */ +void +ofl_exp_stats_type_print(FILE *stream, uint32_t type); + +void +ofl_structs_match_put8e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint8_t value); + +void +ofl_structs_match_put8me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint8_t value, uint8_t mask); + +void +ofl_structs_match_put16e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint16_t value); + +void +ofl_structs_match_put16me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint16_t value, uint16_t mask); + +void +ofl_structs_match_put32e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint32_t value); +void +ofl_structs_match_put32me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint32_t value, uint32_t mask); +void +ofl_structs_match_put64e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint64_t value); + +void +ofl_structs_match_put64me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint64_t value, uint64_t mask); #endif /* OFL_EXP_OPENSTATE_H */ \ No newline at end of file diff --git a/oflib-exp/ofl-exp.c b/oflib-exp/ofl-exp.c index 7ed6272..1b8911f 100644 --- a/oflib-exp/ofl-exp.c +++ b/oflib-exp/ofl-exp.c @@ -261,7 +261,7 @@ ofl_exp_stats_reply_pack (struct ofl_msg_multipart_reply_header *msg, uint8_t ** } ofl_err -ofl_exp_stats_req_unpack (struct ofp_multipart_request *os, uint8_t* buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp){ +ofl_exp_stats_req_unpack (struct ofp_multipart_request *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp){ struct ofp_experimenter_stats_header *ext = (struct ofp_experimenter_stats_header *)os->body; @@ -282,7 +282,7 @@ ofl_exp_stats_req_unpack (struct ofp_multipart_request *os, uint8_t* buf, size_t } ofl_err -ofl_exp_stats_reply_unpack (struct ofp_multipart_reply *os, uint8_t* buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp){ +ofl_exp_stats_reply_unpack (struct ofp_multipart_reply *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp){ struct ofp_experimenter_stats_header *ext = (struct ofp_experimenter_stats_header *)os->body; if (*len < sizeof(struct ofp_experimenter_stats_header)) { @@ -292,7 +292,7 @@ ofl_exp_stats_reply_unpack (struct ofp_multipart_reply *os, uint8_t* buf, size_t switch (ntohl(ext->experimenter)) { case (OPENSTATE_VENDOR_ID): { - return ofl_exp_openstate_stats_reply_unpack(os, buf, len, msg, exp); + return ofl_exp_openstate_stats_reply_unpack(os, buf, len, (struct ofl_msg_multipart_request_header **)msg, exp); } default: { OFL_LOG_WARN(LOG_MODULE, "Trying to unpack unknown EXPERIMENTER message (%u).", ntohl(ext->experimenter)); @@ -370,3 +370,39 @@ ofl_exp_stats_reply_free (struct ofl_msg_multipart_reply_header *msg){ } } +void +ofl_exp_field_pack (struct ofpbuf *buf, struct ofl_match_tlv *oft){ + /*pollins: probabilmente ci sarà da definire una struttura che determina la posizione dell'experimenter ID (come è fatto adesso presuppone che sia il primo valore in value)*/ + switch(*((uint32_t*) (oft->value))) + { + case OPENSTATE_VENDOR_ID:{ + ofl_exp_openstate_field_pack(buf, oft); + break; + } + default: + break; + } +} + +int +ofl_exp_field_unpack (struct ofl_match *match, struct oxm_field *f, void *experimenter_id, void *value, void *mask){ + switch (ntohl(*((uint32_t*) experimenter_id))) { + case OPENSTATE_VENDOR_ID:{ + return ofl_exp_openstate_field_unpack(match, f, experimenter_id, value, mask); + } + default: + NOT_REACHED(); + } + NOT_REACHED(); +} + +void +ofl_exp_field_match (struct ofl_match_tlv *f, int *packet_header, int *field_len, uint8_t **flow_val, uint8_t **flow_mask){ + switch(*((uint32_t*) (f->value))){ + case OPENSTATE_VENDOR_ID: + ofl_exp_openstate_field_match(f, packet_header, field_len, flow_val, flow_mask); + break; + default: + break; + } +} \ No newline at end of file diff --git a/oflib-exp/ofl-exp.h b/oflib-exp/ofl-exp.h index ee181fc..47d5eae 100644 --- a/oflib-exp/ofl-exp.h +++ b/oflib-exp/ofl-exp.h @@ -70,10 +70,10 @@ int ofl_exp_stats_reply_pack (struct ofl_msg_multipart_reply_header *msg, uint8_t **buf, size_t *buf_len, struct ofl_exp *exp); ofl_err -ofl_exp_stats_req_unpack (struct ofp_multipart_request *os, uint8_t* buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp); +ofl_exp_stats_req_unpack (struct ofp_multipart_request *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp); ofl_err -ofl_exp_stats_reply_unpack (struct ofp_multipart_reply *os, uint8_t* buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp); +ofl_exp_stats_reply_unpack (struct ofp_multipart_reply *os, uint8_t *buf, size_t *len, struct ofl_msg_multipart_request_header **msg, struct ofl_exp *exp); char * ofl_exp_stats_req_to_string (struct ofl_msg_multipart_request_header *msg, struct ofl_exp *exp); @@ -87,6 +87,14 @@ ofl_exp_stats_req_free (struct ofl_msg_multipart_request_header *msg); int ofl_exp_stats_reply_free (struct ofl_msg_multipart_reply_header *msg); +void +ofl_exp_field_pack(struct ofpbuf *buf, struct ofl_match_tlv *oft); + +int +ofl_exp_field_unpack(struct ofl_match *match, struct oxm_field *f, void *experimenter_id, void *value, void *mask); + +void +ofl_exp_field_match(struct ofl_match_tlv *f, int *packet_header, int *field_len, uint8_t **flow_val, uint8_t **flow_mask); #endif /* OFL_EXP_H */ diff --git a/oflib/ofl-messages-pack.c b/oflib/ofl-messages-pack.c index 8bd90eb..a38fc48 100644 --- a/oflib/ofl-messages-pack.c +++ b/oflib/ofl-messages-pack.c @@ -140,7 +140,7 @@ ofl_msg_pack_set_config(struct ofl_msg_set_config *msg, uint8_t **buf, size_t *b } static int -ofl_msg_pack_packet_in(struct ofl_msg_packet_in *msg, uint8_t **buf, size_t *buf_len) { +ofl_msg_pack_packet_in(struct ofl_msg_packet_in *msg, uint8_t **buf, size_t *buf_len, struct ofl_exp *exp) { struct ofp_packet_in *packet_in; uint8_t *ptr; @@ -154,7 +154,7 @@ ofl_msg_pack_packet_in(struct ofl_msg_packet_in *msg, uint8_t **buf, size_t *buf packet_in->cookie = hton64(msg->cookie); ptr = (*buf) + (sizeof(struct ofp_packet_in) - 4); - ofl_structs_match_pack(msg->match,&(packet_in->match),ptr, NULL); + ofl_structs_match_pack(msg->match,&(packet_in->match),ptr, exp); ptr = (*buf) + ROUND_UP((sizeof(struct ofp_packet_in)-4) + msg->match->length,8); /*padding bytes*/ @@ -1026,7 +1026,7 @@ ofl_msg_pack(struct ofl_msg_header *msg, uint32_t xid, uint8_t **buf, size_t *bu /* Asynchronous messages. */ case OFPT_PACKET_IN: { - error = ofl_msg_pack_packet_in((struct ofl_msg_packet_in *)msg, buf, buf_len); + error = ofl_msg_pack_packet_in((struct ofl_msg_packet_in *)msg, buf, buf_len, exp); break; } case OFPT_FLOW_REMOVED: { diff --git a/oflib/ofl-messages-unpack.c b/oflib/ofl-messages-unpack.c index 9c3b3bc..7fe5307 100644 --- a/oflib/ofl-messages-unpack.c +++ b/oflib/ofl-messages-unpack.c @@ -1475,7 +1475,7 @@ ofl_msg_unpack_multipart_reply(struct ofp_header *src, uint8_t *buf, size_t *len OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER stats reply, but no callback was given."); error = ofl_error(OFPET_BAD_REQUEST, OFPBRC_BAD_MULTIPART); } else { - error = exp->stats->reply_unpack(os, buf, len, (struct ofl_msg_multipart_reply_header **)msg, exp); + error = exp->stats->reply_unpack(os, buf, len, msg, exp); } break; } diff --git a/oflib/ofl-structs-match.c b/oflib/ofl-structs-match.c index 92ad525..a20090a 100644 --- a/oflib/ofl-structs-match.c +++ b/oflib/ofl-structs-match.c @@ -53,19 +53,6 @@ ofl_structs_match_put8(struct ofl_match *match, uint32_t header, uint8_t value){ match->header.length += len + 4; } -void -ofl_structs_match_put8e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint8_t value){ - struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); - int len = sizeof(uint8_t); - - m->header = header; - m->value = malloc(EXP_ID_LEN + len); - memcpy(m->value, &experimenter_id, EXP_ID_LEN); - memcpy(m->value + EXP_ID_LEN, &value, len); - hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); - match->header.length += EXP_ID_LEN + len + 4; -} - void ofl_structs_match_put8m(struct ofl_match *match, uint32_t header, uint8_t value, uint8_t mask){ struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); @@ -79,20 +66,6 @@ ofl_structs_match_put8m(struct ofl_match *match, uint32_t header, uint8_t value, match->header.length += len*2 + 4; } -void -ofl_structs_match_put8me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint8_t value, uint8_t mask){ - struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); - int len = sizeof(uint8_t); - - m->header = header; - m->value = malloc(EXP_ID_LEN + len*2); - memcpy(m->value, &experimenter_id, EXP_ID_LEN); - memcpy(m->value + EXP_ID_LEN, &value, len); - memcpy(m->value + EXP_ID_LEN + len, &mask, len); - hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); - match->header.length += EXP_ID_LEN + len*2 + 4; -} - void ofl_structs_match_put16(struct ofl_match *match, uint32_t header, uint16_t value){ struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); @@ -105,19 +78,6 @@ ofl_structs_match_put16(struct ofl_match *match, uint32_t header, uint16_t value match->header.length += len + 4; } -void -ofl_structs_match_put16e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint16_t value){ - struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); - int len = sizeof(uint16_t); - - m->header = header; - m->value = malloc(EXP_ID_LEN + len); - memcpy(m->value, &experimenter_id, EXP_ID_LEN); - memcpy(m->value + EXP_ID_LEN, &value, len); - hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); - match->header.length += EXP_ID_LEN + len + 4; -} - void ofl_structs_match_put16m(struct ofl_match *match, uint32_t header, uint16_t value, uint16_t mask){ struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); @@ -131,20 +91,6 @@ ofl_structs_match_put16m(struct ofl_match *match, uint32_t header, uint16_t valu match->header.length += len*2 + 4; } -void -ofl_structs_match_put16me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint16_t value, uint16_t mask){ - struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); - int len = sizeof(uint16_t); - - m->header = header; - m->value = malloc(EXP_ID_LEN + len*2); - memcpy(m->value, &experimenter_id, EXP_ID_LEN); - memcpy(m->value + EXP_ID_LEN, &value, len); - memcpy(m->value + EXP_ID_LEN + len, &mask, len); - hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); - match->header.length += EXP_ID_LEN + len*2 + 4; -} - void ofl_structs_match_put32(struct ofl_match *match, uint32_t header, uint32_t value){ struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); @@ -157,19 +103,6 @@ ofl_structs_match_put32(struct ofl_match *match, uint32_t header, uint32_t value match->header.length += len + 4; } -void -ofl_structs_match_put32e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint32_t value){ - struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); - int len = sizeof(uint32_t); - - m->header = header; - m->value = malloc(EXP_ID_LEN + len); - memcpy(m->value, &experimenter_id, EXP_ID_LEN); - memcpy(m->value + EXP_ID_LEN, &value, len); - hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); - match->header.length += EXP_ID_LEN + len + 4; -} - void ofl_structs_match_put32m(struct ofl_match *match, uint32_t header, uint32_t value, uint32_t mask){ struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); @@ -183,20 +116,6 @@ ofl_structs_match_put32m(struct ofl_match *match, uint32_t header, uint32_t valu match->header.length += len*2 + 4; } -void -ofl_structs_match_put32me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint32_t value, uint32_t mask){ - struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); - int len = sizeof(uint32_t); - - m->header = header; - m->value = malloc(EXP_ID_LEN + len*2); - memcpy(m->value, &experimenter_id, EXP_ID_LEN); - memcpy(m->value + EXP_ID_LEN, &value, len); - memcpy(m->value + EXP_ID_LEN + len, &mask, len); - hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); - match->header.length += EXP_ID_LEN + len*2 + 4; -} - void ofl_structs_match_put64(struct ofl_match *match, uint32_t header, uint64_t value){ struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); @@ -209,19 +128,6 @@ ofl_structs_match_put64(struct ofl_match *match, uint32_t header, uint64_t value match->header.length += len + 4; } -void -ofl_structs_match_put64e(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint64_t value){ - struct ofl_match_tlv *m = xmalloc(sizeof (struct ofl_match_tlv)); - int len = sizeof(uint64_t); - - m->header = header; - m->value = malloc(EXP_ID_LEN + len); - memcpy(m->value, &experimenter_id, EXP_ID_LEN); - memcpy(m->value + EXP_ID_LEN, &value, len); - hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); - match->header.length += EXP_ID_LEN + len + 4; -} - void ofl_structs_match_put64m(struct ofl_match *match, uint32_t header, uint64_t value, uint64_t mask){ struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); @@ -236,20 +142,6 @@ ofl_structs_match_put64m(struct ofl_match *match, uint32_t header, uint64_t valu } -void -ofl_structs_match_put64me(struct ofl_match *match, uint32_t header, uint32_t experimenter_id, uint64_t value, uint64_t mask){ - struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); - int len = sizeof(uint64_t); - - m->header = header; - m->value = malloc(EXP_ID_LEN + len*2); - memcpy(m->value, &experimenter_id, EXP_ID_LEN); - memcpy(m->value + EXP_ID_LEN, &value, len); - memcpy(m->value + EXP_ID_LEN + len, &mask, len); - hmap_insert(&match->match_fields,&m->hmap_node,hash_int(header, 0)); - match->header.length += EXP_ID_LEN + len*2 + 4; -} - void ofl_structs_match_put_eth(struct ofl_match *match, uint32_t header, uint8_t value[ETH_ADDR_LEN]){ struct ofl_match_tlv *m = malloc(sizeof (struct ofl_match_tlv)); diff --git a/oflib/ofl-structs-pack.c b/oflib/ofl-structs-pack.c index 2ea85b0..8af82b7 100644 --- a/oflib/ofl-structs-pack.c +++ b/oflib/ofl-structs-pack.c @@ -935,7 +935,7 @@ ofl_structs_match_pack(struct ofl_match_header *src, struct ofp_match *dst, uint oxm_fields = (uint8_t*) &dst->oxm_fields; dst->length = htons(sizeof(struct ofp_match) - 4); if (src->length){ - oxm_len = oxm_put_match(b, m); + oxm_len = oxm_put_match(b, m, exp); memcpy(oxm_fields, (uint8_t*) ofpbuf_pull(b,oxm_len), oxm_len); dst->length = htons(oxm_len + ((sizeof(struct ofp_match )-4))); ofpbuf_delete(b); diff --git a/oflib/ofl-structs-unpack.c b/oflib/ofl-structs-unpack.c index 56e5803..9c80824 100644 --- a/oflib/ofl-structs-unpack.c +++ b/oflib/ofl-structs-unpack.c @@ -1140,7 +1140,7 @@ ofl_structs_meter_band_unpack(struct ofp_meter_band_header *src, size_t *len, st static ofl_err -ofl_structs_oxm_match_unpack(struct ofp_match* src, uint8_t* buf, size_t *len, struct ofl_match **dst){ +ofl_structs_oxm_match_unpack(struct ofp_match* src, uint8_t* buf, size_t *len, struct ofl_match **dst, struct ofl_exp *exp){ int error = 0; @@ -1149,7 +1149,7 @@ ofl_structs_oxm_match_unpack(struct ofp_match* src, uint8_t* buf, size_t *len, s *len -= ROUND_UP(ntohs(src->length),8); if(ntohs(src->length) > sizeof(struct ofp_match)){ ofpbuf_put(b, buf, ntohs(src->length) - (sizeof(struct ofp_match) -4)); - error = oxm_pull_match(b, m, ntohs(src->length) - (sizeof(struct ofp_match) -4)); + error = oxm_pull_match(b, m, ntohs(src->length) - (sizeof(struct ofp_match) -4), exp); m->header.length = ntohs(src->length) - 4; } else { @@ -1167,7 +1167,7 @@ ofl_structs_match_unpack(struct ofp_match *src,uint8_t * buf, size_t *len, struc switch (ntohs(src->type)) { case (OFPMT_OXM): { - return ofl_structs_oxm_match_unpack(src, buf, len, (struct ofl_match**) dst ); + return ofl_structs_oxm_match_unpack(src, buf, len, (struct ofl_match**) dst, exp); } default: { if (exp == NULL || exp->match == NULL || exp->match->unpack == NULL) { diff --git a/oflib/ofl.h b/oflib/ofl.h index 0e83371..49f2272 100644 --- a/oflib/ofl.h +++ b/oflib/ofl.h @@ -48,6 +48,12 @@ struct ofp_action_header; struct ofp_instruction; struct ofp_multipart_reply; struct ofp_match; +struct ofl_exp; +struct ofpbuf; +struct ofl_match; +struct oxm_field; +struct ofl_match_tlv; +struct ofl_msg_header; /* ofl_err is used to return OpenFlow error type/code's from functions. @@ -129,13 +135,21 @@ struct ofl_exp_msg { char *(*to_string) (struct ofl_msg_experimenter *msg); }; +/* Callback functions for handling experimenter match fields. */ +struct ofl_exp_field { + void (*pack) (struct ofpbuf *buf, struct ofl_match_tlv *oft); + int (*unpack) (struct ofl_match *match, struct oxm_field *f, void *experimenter_id, void *value, void *mask); + void (*match) (struct ofl_match_tlv *f, int * packet_header, int *field_len, uint8_t **flow_val, uint8_t **flow_mask); +}; + /* Convenience structure for passing all callback groups at once. */ struct ofl_exp { - struct ofl_exp_act *act; - struct ofl_exp_inst *inst; - struct ofl_exp_match *match; - struct ofl_exp_stats *stats; - struct ofl_exp_msg *msg; + struct ofl_exp_act *act; + struct ofl_exp_inst *inst; + struct ofl_exp_match *match; + struct ofl_exp_stats *stats; + struct ofl_exp_msg *msg; + struct ofl_exp_field *field; }; @@ -165,7 +179,6 @@ ofl_error_code(ofl_err error) { return error & 0x0000ffff; } - static inline void ofl_enable_colors(){ colors = 1; diff --git a/oflib/oxm-match.c b/oflib/oxm-match.c index 9e76c5d..054e953 100644 --- a/oflib/oxm-match.c +++ b/oflib/oxm-match.c @@ -544,45 +544,6 @@ parse_oxm_entry(struct ofl_match *match, const struct oxm_field *f, } -static int -parse_exp_oxm_entry(struct ofl_match *match, const struct oxm_field *f, const void *experimenter_id, - const void *value, const void *mask){ - switch (ntohl(*((uint32_t*) experimenter_id))) { - case OPENSTATE_VENDOR_ID:{ - switch (f->index) { - case OFI_OXM_EXP_STATE:{ - ofl_structs_match_put32e(match, f->header, ntohl(*((uint32_t*) experimenter_id)), ntohl(*((uint32_t*) value))); - return 0; - } - case OFI_OXM_EXP_STATE_W:{ - if (check_bad_wildcard32(ntohl(*((uint32_t*) value)), ntohl(*((uint32_t*) mask)))){ - return ofp_mkerr(OFPET_BAD_MATCH, OFPBMC_BAD_WILDCARDS); - } - ofl_structs_match_put32me(match, f->header, ntohl(*((uint32_t*) experimenter_id)), ntohl(*((uint32_t*) value)), ntohl(*((uint32_t*) mask))); - return 0; - } - case OFI_OXM_EXP_FLAGS:{ - ofl_structs_match_put32e(match, f->header, ntohl(*((uint32_t*) experimenter_id)), ntohl(*((uint32_t*) value))); - return 0; - } - case OFI_OXM_EXP_FLAGS_W:{ - if (check_bad_wildcard32(ntohl(*((uint32_t*) value)), ntohl(*((uint32_t*) mask)))){ - return ofp_mkerr(OFPET_BAD_MATCH, OFPBMC_BAD_WILDCARDS); - } - ofl_structs_match_put32me(match, f->header, ntohl(*((uint32_t*) experimenter_id)), ntohl(*((uint32_t*) value)), ntohl(*((uint32_t*) mask))); - return 0; - } - default: - NOT_REACHED(); - } - default: - NOT_REACHED(); - } - NOT_REACHED(); - } -NOT_REACHED(); -} - /*hmap_insert(match_dst, &f->hmap_node, hash_int(f->header, 0)); */ @@ -592,7 +553,7 @@ NOT_REACHED(); /* Puts the match in a hash_map structure */ int -oxm_pull_match(struct ofpbuf *buf, struct ofl_match * match_dst, int match_len) +oxm_pull_match(struct ofpbuf *buf, struct ofl_match * match_dst, int match_len, struct ofl_exp *exp) { uint32_t header; @@ -640,18 +601,24 @@ oxm_pull_match(struct ofpbuf *buf, struct ofl_match * match_dst, int match_len) * checked them already. */ error = parse_oxm_entry(match_dst, f, p + 4, p + 4 + length / 2); break; + case(OFPXMC_EXPERIMENTER): /* 'hasmask' and 'length' are known to be correct at this point * because they are included in 'header' and oxm_field_lookup() - * checked them already. */ - //parse_exp_oxm_entry() args are match, oxm_fields, experimenter_id, value and mask - //sizeof(header) is 4 byte - //sizeof(experimenter_id) is 4 byte - //experimenter_id is @ p + 4 (p + header) - //value is @ p + 8 (p + header + experimenter_id) - //mask depends on field's size - error = parse_exp_oxm_entry(match_dst, f, p + 4, p + 4 + EXP_ID_LEN, p + 4 + EXP_ID_LEN + (length-EXP_ID_LEN) / 2); + * checked them already. + * exp->field->unpack() args are match, oxm_fields, experimenter_id, value and mask + * sizeof(header) is 4 byte + * sizeof(experimenter_id) is 4 byte + * experimenter_id is @ p + 4 (p + header) + * value is @ p + 8 (p + header + experimenter_id) + * mask depends on field's size*/ + if (exp == NULL || exp->field == NULL || exp->field->unpack == NULL) { + VLOG_DBG_RL(LOG_MODULE, &rl,"Received match is experimental, but no callback was given."); + error = ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE); + } + error = exp->field->unpack(match_dst, f, p + 4, p + 4 + EXP_ID_LEN, p + 4 + EXP_ID_LEN + (length-EXP_ID_LEN) / 2); break; + default: error = ofp_mkerr(OFPET_BAD_MATCH, OFPBMC_BAD_FIELD); } @@ -725,14 +692,6 @@ oxm_put_8(struct ofpbuf *buf, uint32_t header, uint8_t value) ofpbuf_put(buf, &value, sizeof value); } -static void -oxm_put_8e(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint8_t value) -{ - oxm_put_header(buf, header); - ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); - ofpbuf_put(buf, &value, sizeof value); -} - static void oxm_put_8w(struct ofpbuf *buf, uint32_t header, uint8_t value, uint8_t mask) { @@ -741,15 +700,6 @@ oxm_put_8w(struct ofpbuf *buf, uint32_t header, uint8_t value, uint8_t mask) ofpbuf_put(buf, &mask, sizeof mask); } -static void -oxm_put_8we(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint8_t value, uint8_t mask) -{ - oxm_put_header(buf, header); - ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); - ofpbuf_put(buf, &value, sizeof value); - ofpbuf_put(buf, &mask, sizeof mask); -} - static void oxm_put_16(struct ofpbuf *buf, uint32_t header, uint16_t value) { @@ -757,14 +707,6 @@ oxm_put_16(struct ofpbuf *buf, uint32_t header, uint16_t value) ofpbuf_put(buf, &value, sizeof value); } -static void -oxm_put_16e(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint16_t value) -{ - oxm_put_header(buf, header); - ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); - ofpbuf_put(buf, &value, sizeof value); -} - static void oxm_put_16w(struct ofpbuf *buf, uint32_t header, uint16_t value, uint16_t mask) { @@ -773,15 +715,6 @@ oxm_put_16w(struct ofpbuf *buf, uint32_t header, uint16_t value, uint16_t mask) ofpbuf_put(buf, &mask, sizeof mask); } -static void -oxm_put_16we(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint16_t value, uint16_t mask) -{ - oxm_put_header(buf, header); - ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); - ofpbuf_put(buf, &value, sizeof value); - ofpbuf_put(buf, &mask, sizeof mask); -} - static void oxm_put_32(struct ofpbuf *buf, uint32_t header, uint32_t value) { @@ -789,14 +722,6 @@ oxm_put_32(struct ofpbuf *buf, uint32_t header, uint32_t value) ofpbuf_put(buf, &value, sizeof value); } -static void -oxm_put_32e(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint32_t value) -{ - oxm_put_header(buf, header); - ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); - ofpbuf_put(buf, &value, sizeof value); -} - static void oxm_put_32w(struct ofpbuf *buf, uint32_t header, uint32_t value, uint32_t mask) { @@ -805,15 +730,6 @@ oxm_put_32w(struct ofpbuf *buf, uint32_t header, uint32_t value, uint32_t mask) ofpbuf_put(buf, &mask, sizeof mask); } -static void -oxm_put_32we(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint32_t value, uint32_t mask) -{ - oxm_put_header(buf, header); - ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); - ofpbuf_put(buf, &value, sizeof value); - ofpbuf_put(buf, &mask, sizeof mask); -} - static void oxm_put_64(struct ofpbuf *buf, uint32_t header, uint64_t value) { @@ -821,14 +737,6 @@ oxm_put_64(struct ofpbuf *buf, uint32_t header, uint64_t value) ofpbuf_put(buf, &value, sizeof value); } -static void -oxm_put_64e(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint64_t value) -{ - oxm_put_header(buf, header); - ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); - ofpbuf_put(buf, &value, sizeof value); -} - static void oxm_put_64w(struct ofpbuf *buf, uint32_t header, uint64_t value, uint64_t mask) { @@ -837,15 +745,6 @@ oxm_put_64w(struct ofpbuf *buf, uint32_t header, uint64_t value, uint64_t mask) ofpbuf_put(buf, &mask, sizeof mask); } -static void -oxm_put_64we(struct ofpbuf *buf, uint32_t header, uint32_t experimenter_id, uint64_t value, uint64_t mask) -{ - oxm_put_header(buf, header); - ofpbuf_put(buf, &experimenter_id, EXP_ID_LEN); - ofpbuf_put(buf, &value, sizeof value); - ofpbuf_put(buf, &mask, sizeof mask); -} - static void oxm_put_eth(struct ofpbuf *buf, uint32_t header, const uint8_t value[ETH_ADDR_LEN]) @@ -911,7 +810,7 @@ is_requisite(uint32_t header){ } /* Puts the match in the buffer */ -int oxm_put_match(struct ofpbuf *buf, struct ofl_match *omt){ +int oxm_put_match(struct ofpbuf *buf, struct ofl_match *omt, struct ofl_exp *exp){ struct ofl_match_tlv *oft; int start_len = buf->size; @@ -955,17 +854,19 @@ int oxm_put_match(struct ofpbuf *buf, struct ofl_match *omt){ /* Loop through the remaining fields */ HMAP_FOR_EACH(oft, struct ofl_match_tlv, hmap_node, &omt->match_fields){ + + uint8_t length = OXM_LENGTH(oft->header); + bool has_mask =false; + if (is_requisite(oft->header)) /*We already inserted fields that are pre requisites to others */ continue; else { - uint8_t length = OXM_LENGTH(oft->header); - - bool has_mask =false; - switch (OXM_VENDOR(oft->header)) { case (OFPXMC_OPENFLOW_BASIC): + pfile("pack match field openflow basic\n"); + if (OXM_HASMASK(oft->header)){ length = length / 2; has_mask = true; @@ -1055,68 +956,11 @@ int oxm_put_match(struct ofpbuf *buf, struct ofl_match *omt){ } break; case (OFPXMC_EXPERIMENTER): - length = length - EXP_ID_LEN; /* field length should exclude experimenter_id */ - if (OXM_HASMASK(oft->header)){ - length = length / 2; - has_mask = true; - } - switch (length){ - case (sizeof(uint8_t)):{ - uint32_t experimenter_id; - uint8_t value; - memcpy(&experimenter_id, oft->value, sizeof(uint32_t)); - memcpy(&value, oft->value + EXP_ID_LEN, sizeof(uint8_t)); - if(!has_mask) - oxm_put_8e(buf,oft->header, htonl(experimenter_id), value); - else { - uint8_t mask; - memcpy(&mask, oft->value + EXP_ID_LEN + length , sizeof(uint8_t)); - oxm_put_8we(buf, oft->header, htonl(experimenter_id), value, mask); - } - break; - } - case (sizeof(uint16_t)):{ - uint32_t experimenter_id; - uint16_t value; - memcpy(&experimenter_id, oft->value, sizeof(uint32_t)); - memcpy(&value, oft->value + EXP_ID_LEN, sizeof(uint16_t)); - if(!has_mask) - oxm_put_16e(buf,oft->header, htonl(experimenter_id), htons(value)); - else { - uint16_t mask; - memcpy(&mask, oft->value + EXP_ID_LEN + length , sizeof(uint16_t)); - oxm_put_16we(buf, oft->header, htonl(experimenter_id), htons(value), htons(mask)); - } - break; - } - case (sizeof(uint32_t)):{ - uint32_t experimenter_id, value; - memcpy(&experimenter_id, oft->value, sizeof(uint32_t)); - memcpy(&value, oft->value + EXP_ID_LEN, sizeof(uint32_t)); - if(!has_mask) - oxm_put_32e(buf,oft->header, htonl(experimenter_id), htonl(value)); - else { - uint32_t mask; - memcpy(&mask, oft->value + EXP_ID_LEN + length , sizeof(uint32_t)); - oxm_put_32we(buf, oft->header, htonl(experimenter_id), htonl(value), htonl(mask)); - } - break; - } - case (sizeof(uint64_t)):{ - uint32_t experimenter_id; - uint64_t value; - memcpy(&experimenter_id, oft->value, sizeof(uint32_t)); - memcpy(&value, oft->value + EXP_ID_LEN, sizeof(uint64_t)); - if(!has_mask) - oxm_put_64e(buf,oft->header, htonl(experimenter_id), hton64(value)); - else { - uint64_t mask; - memcpy(&mask, oft->value + EXP_ID_LEN + length , sizeof(uint64_t)); - oxm_put_64we(buf, oft->header, htonl(experimenter_id), hton64(value), hton64(mask)); - } - break; - } + if (exp == NULL || exp->field == NULL || exp->field->pack == NULL) { + VLOG_DBG_RL(LOG_MODULE, &rl, "Received match is experimental, but no callback was given."); + break; } + exp->field->pack(buf, oft); break; } diff --git a/oflib/oxm-match.h b/oflib/oxm-match.h index b42a37c..28db314 100644 --- a/oflib/oxm-match.h +++ b/oflib/oxm-match.h @@ -331,10 +331,10 @@ bool oxm_prereqs_ok(const struct oxm_field *field, const struct ofl_match *rule); int -oxm_pull_match(struct ofpbuf * buf, struct ofl_match *match_dst, int match_len); +oxm_pull_match(struct ofpbuf * buf, struct ofl_match *match_dst, int match_len, struct ofl_exp *exp); int -oxm_put_match(struct ofpbuf *buf, struct ofl_match *omt); +oxm_put_match(struct ofpbuf *buf, struct ofl_match *omt, struct ofl_exp *exp); struct ofl_match_tlv * oxm_match_lookup(uint32_t header, const struct ofl_match *omt); diff --git a/udatapath/datapath.c b/udatapath/datapath.c index 25af22b..626e21a 100644 --- a/udatapath/datapath.c +++ b/udatapath/datapath.c @@ -104,7 +104,7 @@ static struct ofl_exp_act dp_exp_act = .ofp_len = ofl_exp_act_ofp_len, .to_string = ofl_exp_act_to_string}; - +/* Callbacks for processing experimenter stats in OFLib.*/ static struct ofl_exp_stats dp_exp_statistics = {.req_pack = ofl_exp_stats_req_pack, .req_unpack = ofl_exp_stats_req_unpack, @@ -115,12 +115,20 @@ static struct ofl_exp_stats dp_exp_statistics = .reply_free = ofl_exp_stats_reply_free, .reply_to_string = ofl_exp_stats_reply_to_string}; +/* Callbacks for processing experimenter match fields in OFLib.*/ +static struct ofl_exp_field dp_exp_field = + {.unpack = ofl_exp_field_unpack, + .pack = ofl_exp_field_pack, + .match = ofl_exp_field_match}; + + static struct ofl_exp dp_exp = {.act = &dp_exp_act, .inst = NULL, .match = NULL, .stats = &dp_exp_statistics, - .msg = &dp_exp_msg}; + .msg = &dp_exp_msg, + .field = &dp_exp_field}; /* Generates and returns a random datapath id. */ static uint64_t diff --git a/udatapath/dp_exp.c b/udatapath/dp_exp.c index c97fa5c..032348d 100644 --- a/udatapath/dp_exp.c +++ b/udatapath/dp_exp.c @@ -112,15 +112,15 @@ dp_exp_stats(struct datapath *dp UNUSED, struct ofl_msg_multipart_request_experi switch(exp->type) { case (OFPMP_EXP_STATE_STATS): { struct ofl_exp_msg_multipart_reply_state reply; - err = handle_stats_request_state(dp->pipeline, (struct ofl_exp_msg_state_mod *)msg, sender, &reply); + err = handle_stats_request_state(dp->pipeline, (struct ofl_exp_msg_multipart_request_state *)msg, sender, &reply); dp_send_message(dp, (struct ofl_msg_header *)&reply, sender); free(reply.stats); ofl_msg_free((struct ofl_msg_header *)msg, dp->exp); return err; } case (OFPMP_EXP_FLAGS_STATS): { - struct ofl_exp_msg_multipart_reply_state reply; - err = handle_stats_request_global_state(dp->pipeline, (struct ofl_exp_msg_flag_mod *)msg, sender, &reply); + struct ofl_exp_msg_multipart_reply_global_state reply; + err = handle_stats_request_global_state(dp->pipeline, sender, &reply); dp_send_message(dp, (struct ofl_msg_header *)&reply, sender); ofl_msg_free((struct ofl_msg_header *)msg, dp->exp); return err; diff --git a/udatapath/flow_table.c b/udatapath/flow_table.c index 39dbd58..8801520 100644 --- a/udatapath/flow_table.c +++ b/udatapath/flow_table.c @@ -209,7 +209,7 @@ flow_table_flow_mod(struct flow_table *table, struct ofl_msg_flow_mod *mod, bool struct flow_entry * -flow_table_lookup(struct flow_table *table, struct packet *pkt) { +flow_table_lookup(struct flow_table *table, struct packet *pkt, struct ofl_exp *exp) { struct flow_entry *entry; table->stats->lookup_count++; @@ -221,8 +221,7 @@ flow_table_lookup(struct flow_table *table, struct packet *pkt) { /* select appropriate handler, based on match type of flow entry. */ switch (m->type) { case (OFPMT_OXM): { - if (packet_handle_std_match(pkt->handle_std, - (struct ofl_match *)m)) { + if (packet_handle_std_match(pkt->handle_std, (struct ofl_match *)m, exp)) { if (!entry->no_byt_count) entry->stats->byte_count += pkt->buffer->size; if (!entry->no_pkt_count) diff --git a/udatapath/flow_table.h b/udatapath/flow_table.h index df6bf6d..4092536 100644 --- a/udatapath/flow_table.h +++ b/udatapath/flow_table.h @@ -74,7 +74,7 @@ flow_table_flow_mod(struct flow_table *table, struct ofl_msg_flow_mod *mod, bool /* Finds the flow entry with the highest priority, which matches the packet. */ struct flow_entry * -flow_table_lookup(struct flow_table *table, struct packet *pkt); +flow_table_lookup(struct flow_table *table, struct packet *pkt, struct ofl_exp *exp); /* Orders the flow table to check the timeout its flows. */ void diff --git a/udatapath/match_std.c b/udatapath/match_std.c index 3421227..cc71f25 100644 --- a/udatapath/match_std.c +++ b/udatapath/match_std.c @@ -133,7 +133,7 @@ match_mask128(uint8_t *a, uint8_t *am, uint8_t *b) { /* Returns true if the fields in *packet matches the flow entry in *flow_match */ bool -packet_match(struct ofl_match *flow_match, struct ofl_match *packet){ +packet_match(struct ofl_match *flow_match, struct ofl_match *packet, struct ofl_exp *exp){ struct ofl_match_tlv *f; struct ofl_match_tlv *packet_f; @@ -150,7 +150,7 @@ packet_match(struct ofl_match *flow_match, struct ofl_match *packet){ HMAP_FOR_EACH(f, struct ofl_match_tlv, hmap_node, &flow_match->match_fields) { /* Check presence of match field in packet */ - + has_mask = OXM_HASMASK(f->header); packet_header = f->header; switch (OXM_VENDOR(f->header)) @@ -168,23 +168,12 @@ packet_match(struct ofl_match *flow_match, struct ofl_match *packet){ break; case(OFPXMC_EXPERIMENTER): - switch(*((uint32_t*) (f->value))) - { - case OPENSTATE_VENDOR_ID: - field_len = (OXM_LENGTH(f->header) - EXP_ID_LEN); - flow_val = f->value + EXP_ID_LEN; - if (has_mask) { - /* Clear the has_mask bit and divide the field_len by two in the packet field header */ - field_len /= 2; - packet_header &= 0xfffffe00; - packet_header |= field_len + EXP_ID_LEN; - flow_mask = f->value + EXP_ID_LEN + field_len; - } - break; - default: - break; + if (exp == NULL || exp->field == NULL || exp->field->match == NULL) { + VLOG_WARN(LOG_MODULE,"Received match is experimental, but no callback was given."); + ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE); } - break; + exp->field->match(f, &packet_header, &field_len, &flow_val, &flow_mask); + break; default: break; diff --git a/udatapath/match_std.h b/udatapath/match_std.h index 79ed1c2..7aac0a7 100644 --- a/udatapath/match_std.h +++ b/udatapath/match_std.h @@ -44,7 +44,7 @@ bool match_std_overlap(struct ofl_match *a, struct ofl_match *b); bool -packet_match(struct ofl_match *a, struct ofl_match *b); +packet_match(struct ofl_match *a, struct ofl_match *b, struct ofl_exp *exp); /* Returns true if match a matches match b, in a strict manner. */ bool diff --git a/udatapath/packet_handle_std.c b/udatapath/packet_handle_std.c index 0d33799..7296235 100644 --- a/udatapath/packet_handle_std.c +++ b/udatapath/packet_handle_std.c @@ -45,6 +45,7 @@ #include "nbee_link/nbee_link.h" #include "dp_capabilities.h" +#include "oflib-exp/ofl-exp-openstate.h" /* Resets all protocol fields to NULL */ @@ -149,14 +150,14 @@ packet_handle_std_is_fragment(struct packet_handle_std *handle) { bool -packet_handle_std_match(struct packet_handle_std *handle, struct ofl_match *match){ +packet_handle_std_match(struct packet_handle_std *handle, struct ofl_match *match, struct ofl_exp *exp){ if (!handle->valid){ packet_handle_std_validate(handle); if (!handle->valid){ return false; } } - return packet_match(match ,&handle->match ); + return packet_match(match ,&handle->match, exp); } diff --git a/udatapath/packet_handle_std.h b/udatapath/packet_handle_std.h index 6873253..9233dc3 100644 --- a/udatapath/packet_handle_std.h +++ b/udatapath/packet_handle_std.h @@ -75,7 +75,7 @@ packet_handle_std_is_fragment(struct packet_handle_std *handle); /* Returns true if the packet matches the given standard match structure. */ bool -packet_handle_std_match(struct packet_handle_std *handle, struct ofl_match *match); +packet_handle_std_match(struct packet_handle_std *handle, struct ofl_match *match, struct ofl_exp *exp); /* Converts the packet to a string representation */ char * diff --git a/udatapath/pipeline.c b/udatapath/pipeline.c index 0b2b714..ec653ff 100644 --- a/udatapath/pipeline.c +++ b/udatapath/pipeline.c @@ -90,7 +90,6 @@ is_table_miss(struct flow_entry *entry){ static void send_packet_to_controller(struct pipeline *pl, struct packet *pkt, uint8_t table_id, uint8_t reason) { - printf("here is send packet to controller\n"); struct ofl_msg_packet_in msg; struct ofl_match *m; msg.header.type = OFPT_PACKET_IN; @@ -124,7 +123,7 @@ send_packet_to_controller(struct pipeline *pl, struct packet *pkt, uint8_t table void pipeline_process_packet(struct pipeline *pl, struct packet *pkt) { struct flow_table *table, *next_table; - + struct ofl_match_tlv *f; //printf("here is pipeline processing packet\n"); if (VLOG_IS_DBG_ENABLED(LOG_MODULE)) { @@ -172,10 +171,10 @@ pipeline_process_packet(struct pipeline *pl, struct packet *pkt) { free(m); } - entry = flow_table_lookup(table, pkt); + entry = flow_table_lookup(table, pkt, pkt->dp->exp); //removes 'state' virtual header field - struct ofl_match_tlv *f; + HMAP_FOR_EACH_WITH_HASH(f, struct ofl_match_tlv, hmap_node, hash_int(OXM_EXP_STATE,0), &pkt->handle_std->match.match_fields){ hmap_remove_and_shrink(&pkt->handle_std->match.match_fields,&f->hmap_node); @@ -677,7 +676,7 @@ void pipeline_global_states_write_flags(struct packet *pkt){ HMAP_FOR_EACH_WITH_HASH(f, struct ofl_match_tlv, hmap_node, hash_int(OXM_EXP_FLAGS,0), &pkt->handle_std->match.match_fields){ - int32_t *flags = (uint32_t*) (f->value + EXP_ID_LEN); + uint32_t *flags = (uint32_t*) (f->value + EXP_ID_LEN); *flags = (*flags & 0x00000000 ) | (pkt->dp->global_states); } } diff --git a/udatapath/udatapath.c b/udatapath/udatapath.c index 8484ef8..630f754 100644 --- a/udatapath/udatapath.c +++ b/udatapath/udatapath.c @@ -130,11 +130,12 @@ udatapath_cmd(int argc, char *argv[]) for (i = optind; i < argc; i += 2) { const char *pvconn_name = argv[i]; const char *pvconn_name_aux = NULL; + struct pvconn *pvconn, *pvconn_aux = NULL; + int retval, retval_aux; + if (use_multiple_connections) pvconn_name_aux = argv[i + 1]; - struct pvconn *pvconn, *pvconn_aux = NULL; - int retval, retval_aux; retval = pvconn_open(pvconn_name, &pvconn); if (!retval || retval == EAGAIN) { diff --git a/utilities/dpctl.c b/utilities/dpctl.c index 9a5ee31..f8bf7f3 100644 --- a/utilities/dpctl.c +++ b/utilities/dpctl.c @@ -218,12 +218,18 @@ static struct ofl_exp_stats dpctl_exp_stats = .reply_free = ofl_exp_stats_reply_free, .reply_to_string = ofl_exp_stats_reply_to_string}; +static struct ofl_exp_field dpctl_exp_field = + {.unpack = ofl_exp_field_unpack, + .pack = ofl_exp_field_pack, + .match = ofl_exp_field_match}; + static struct ofl_exp dpctl_exp = {.act = &dpctl_exp_act, .inst = NULL, .match = NULL, .stats = &dpctl_exp_stats, - .msg = &dpctl_exp_msg}; + .msg = &dpctl_exp_msg, + .field = &dpctl_exp_field}; static void diff --git a/utilities/dpctl.c.bak b/utilities/dpctl.c.bak index 9600b0f..5e7c2a4 100644 --- a/utilities/dpctl.c.bak +++ b/utilities/dpctl.c.bak @@ -1,4 +1,5 @@ /* Copyright (c) 2011, TrafficLab, Ericsson Research, Hungary + * Copyright (c) 2012, CPqD, Brazil * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,7 +27,6 @@ * POSSIBILITY OF SUCH DAMAGE. * * - * Author: Zoltán Lajos Kis */ #include @@ -51,6 +51,7 @@ #include "oflib/ofl.h" #include "oflib-exp/ofl-exp.h" #include "oflib-exp/ofl-exp-openflow.h" +#include "oflib-exp/ofl-exp-openstate.h" #include "oflib/oxm-match.h" #include "command-line.h" @@ -58,6 +59,7 @@ #include "dpif.h" #include "openflow/nicira-ext.h" #include "openflow/openflow-ext.h" +#include "openflow/openstate-ext.h" #include "ofpbuf.h" #include "openflow/openflow.h" #include "packets.h" @@ -82,6 +84,7 @@ // response, barrier resp., or the error #define XID 0xf0ff00f0 +static uint32_t global_xid = XID; struct command { char *name; @@ -108,11 +111,17 @@ parse_flow_mod_args(char *str, struct ofl_msg_flow_mod *req); static void parse_group_mod_args(char *str, struct ofl_msg_group_mod *req); +static void +parse_meter_mod_args(char *str, struct ofl_msg_meter_mod *req); + static void parse_bucket(char *str, struct ofl_bucket *b); static void -parse_flow_stat_args(char *str, struct ofl_msg_stats_request_flow *req); +parse_state_stat_args(char *str, struct ofl_exp_msg_multipart_request_state *req); + +static void +parse_flow_stat_args(char *str, struct ofl_msg_multipart_request_flow *req); static void parse_match(char *str, struct ofl_match_header **match); @@ -132,6 +141,8 @@ parse_port_mod(char *str, struct ofl_msg_port_mod *msg); static void parse_table_mod(char *str, struct ofl_msg_table_mod *msg); +static void +parse_band(char *str, struct ofl_msg_meter_mod *m, struct ofl_meter_band_header **b); static void make_all_match(struct ofl_match_header **match); @@ -148,18 +159,23 @@ parse_queue(char *str, uint32_t *port); static int parse_group(char *str, uint32_t *group); +static int +parse_meter(char *str, uint32_t *meter); + static int parse_table(char *str, uint8_t *table); static int -parse_dl_addr(char *str, uint8_t *addr); +parse_dl_addr(char *str, uint8_t *addr, uint8_t **mask); static int -parse_nw_addr(char *str, uint32_t *addr); +parse_nw_addr(char *str, uint32_t *addr, uint32_t **mask); static int parse_vlan_vid(char *str, uint16_t *vid); +static int +parse_ext_hdr(char *str, uint16_t *ext_hdr); static int parse8(char *str, struct names8 *names, size_t names_num, uint8_t max, uint8_t *val); @@ -167,9 +183,17 @@ parse8(char *str, struct names8 *names, size_t names_num, uint8_t max, uint8_t * static int parse16(char *str, struct names16 *names, size_t names_num, uint16_t max, uint16_t *val); +static int +parse16m(char *str, struct names16 *names, size_t names_num, uint16_t max, uint16_t *val, uint16_t *mask); + static int parse32(char *str, struct names32 *names, size_t names_num, uint32_t max, uint32_t *val); +static int +parse32m(char *str, struct names32 *names, size_t names_num, uint32_t max, uint32_t *val, uint32_t **mask); + +static void +set_table_features_match(struct vconn *vconn, int argc, char *argv[]); static struct ofl_exp_msg dpctl_exp_msg = {.pack = ofl_exp_msg_pack, @@ -184,7 +208,7 @@ static struct ofl_exp_act dpctl_exp_act = .ofp_len = ofl_exp_act_ofp_len, .to_string = ofl_exp_act_to_string}; -static struct ofl_exp_stats ofl_exp_stats = +static struct ofl_exp_stats dpctl_exp_stats = {.req_pack = ofl_exp_stats_req_pack, .req_unpack = ofl_exp_stats_req_unpack, .req_free = ofl_exp_stats_req_free, @@ -194,23 +218,27 @@ static struct ofl_exp_stats ofl_exp_stats = .reply_free = ofl_exp_stats_reply_free, .reply_to_string = ofl_exp_stats_reply_to_string}; -static struct ofl_exp ofl_exp = - {.act = &ofl_exp_act, +static struct ofl_exp_field dpctl_exp_match_field = + {.unpack = ofl_exp_field_unpack, + .pack = ofl_exp_field_pack}; + +static struct ofl_exp dpctl_exp = + {.act = &dpctl_exp_act, .inst = NULL, .match = NULL, - .stats = &ofl_exp_stats, - .msg = &ofl_exp_msg}; + .stats = &dpctl_exp_stats, + .msg = &dpctl_exp_msg, + .field = &dpctl_exp_field}; static void dpctl_transact(struct vconn *vconn, struct ofl_msg_header *req, - struct ofl_msg_header **repl) { + struct ofl_msg_header **repl, uint32_t *repl_xid_p) { struct ofpbuf *ofpbufreq, *ofpbufrepl; uint8_t *bufreq; size_t bufreq_size; int error; - - error = ofl_msg_pack(req, XID, &bufreq, &bufreq_size, &dpctl_exp); + error = ofl_msg_pack(req, global_xid, &bufreq, &bufreq_size, &dpctl_exp); if (error) { ofp_fatal(0, "Error packing request."); } @@ -218,13 +246,12 @@ dpctl_transact(struct vconn *vconn, struct ofl_msg_header *req, ofpbufreq = ofpbuf_new(0); ofpbuf_use(ofpbufreq, bufreq, bufreq_size); ofpbuf_put_uninit(ofpbufreq, bufreq_size); - error = vconn_transact(vconn, ofpbufreq, &ofpbufrepl); if (error) { ofp_fatal(0, "Error during transaction."); } - - error = ofl_msg_unpack(ofpbufrepl->data, ofpbufrepl->size, repl, NULL /*xid_ptr*/, &dpctl_exp); + error = ofl_msg_unpack(ofpbufrepl->data, ofpbufrepl->size, repl, repl_xid_p, &dpctl_exp); + //ofp_fatal(0, "error = %d", error); if (error) { ofp_fatal(0, "Error unpacking reply."); } @@ -241,16 +268,14 @@ static void dpctl_transact_and_print(struct vconn *vconn, struct ofl_msg_header *req, struct ofl_msg_header **repl) { struct ofl_msg_header *reply; + uint32_t repl_xid; char *str; - str = ofl_msg_to_string(req, &dpctl_exp); - printf("\nSENDING:\n%s\n\n", str); + printf("\nSENDING (xid=0x%X):\n%s\n\n", global_xid, str); free(str); - - dpctl_transact(vconn, req, &reply); - + dpctl_transact(vconn, req, &reply, &repl_xid); str = ofl_msg_to_string(reply, &dpctl_exp); - printf("\nRECEIVED:\n%s\n\n", str); + printf("\nRECEIVED (xid=0x%X):\n%s\n\n", repl_xid, str); free(str); if (repl != NULL) { @@ -263,12 +288,13 @@ dpctl_transact_and_print(struct vconn *vconn, struct ofl_msg_header *req, static void dpctl_barrier(struct vconn *vconn) { struct ofl_msg_header *reply; + uint32_t repl_xid; char *str; struct ofl_msg_header req = {.type = OFPT_BARRIER_REQUEST}; - dpctl_transact(vconn, &req, &reply); + dpctl_transact(vconn, &req, &reply, &repl_xid); if (reply->type == OFPT_BARRIER_REPLY) { str = ofl_msg_to_string(reply, &dpctl_exp); @@ -276,7 +302,7 @@ dpctl_barrier(struct vconn *vconn) { free(str); } else { str = ofl_msg_to_string(reply, &dpctl_exp); - printf("\nRECEIVED:\n%s\n\n", str); + printf("\nRECEIVED (xid=0x%X):\n%s\n\n", repl_xid, str); free(str); } @@ -289,7 +315,7 @@ dpctl_send(struct vconn *vconn, struct ofl_msg_header *msg) { size_t buf_size; int error; - error = ofl_msg_pack(msg, XID, &buf, &buf_size, &dpctl_exp); + error = ofl_msg_pack(msg, global_xid, &buf, &buf_size, &dpctl_exp); if (error) { ofp_fatal(0, "Error packing request."); } @@ -309,9 +335,8 @@ dpctl_send(struct vconn *vconn, struct ofl_msg_header *msg) { static void dpctl_send_and_print(struct vconn *vconn, struct ofl_msg_header *msg) { char *str; - str = ofl_msg_to_string(msg, &dpctl_exp); - printf("\nSENDING:\n%s\n\n", str); + printf("\nSENDING (xid=0x%X):\n%s\n\n", global_xid, str); free(str); dpctl_send(vconn, msg); @@ -322,6 +347,7 @@ ping(struct vconn *vconn, int argc, char *argv[]) { uint16_t payload_size = 0; size_t times = 0, i; struct ofl_msg_echo *reply; + uint32_t repl_xid; struct ofl_msg_echo req = {{.type = OFPT_ECHO_REQUEST}, @@ -352,7 +378,7 @@ ping(struct vconn *vconn, int argc, char *argv[]) { random_bytes(req.data, payload_size); gettimeofday(&start, NULL); - dpctl_transact(vconn, (struct ofl_msg_header *)&req, (struct ofl_msg_header **)&reply); + dpctl_transact(vconn, (struct ofl_msg_header *)&req, (struct ofl_msg_header **)&reply, &repl_xid); gettimeofday(&end, NULL); if ((req.data_length != reply->data_length) || @@ -404,6 +430,19 @@ monitor(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { } } +static void +table_features(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { + struct ofl_msg_multipart_request_table_features req = + {{{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_TABLE_FEATURES, .flags = 0x0000}, + .tables_num = 0, + .table_features = NULL, + }; + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); +} + + static void features(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { struct ofl_msg_header req = @@ -412,8 +451,6 @@ features(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); } - - static void get_config(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { struct ofl_msg_header req = @@ -426,16 +463,25 @@ get_config(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { static void stats_desc(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { - struct ofl_msg_stats_request_header req = + struct ofl_msg_multipart_request_header req = {{.type = OFPT_MULTIPART_REQUEST}, .type = OFPMP_DESC, .flags = 0x0000}; dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); } +static void +port_desc(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { + struct ofl_msg_multipart_request_header req = + {{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_PORT_DESC, .flags = 0x0000}; + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); +} + static void stats_flow(struct vconn *vconn, int argc, char *argv[]) { - struct ofl_msg_stats_request_flow req = + struct ofl_msg_multipart_request_flow req = {{{.type = OFPT_MULTIPART_REQUEST}, .type = OFPMP_FLOW, .flags = 0x0000}, .cookie = 0x0000000000000000ULL, @@ -444,7 +490,6 @@ stats_flow(struct vconn *vconn, int argc, char *argv[]) { .out_port = OFPP_ANY, .out_group = OFPG_ANY, .match = NULL}; - if (argc > 0) { parse_flow_stat_args(argv[0], &req); } @@ -457,9 +502,40 @@ stats_flow(struct vconn *vconn, int argc, char *argv[]) { dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); } +static void +stats_state(struct vconn *vconn, int argc, char *argv[]) { + struct ofl_exp_msg_multipart_request_state req = + {{{{{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_EXPERIMENTER, .flags = 0x0000}, + .experimenter_id = OPENSTATE_VENDOR_ID}, + .type = OFPMP_EXP_STATE_STATS}, + .table_id = 0xff, + .match = NULL}; + if (argc > 0) { + parse_state_stat_args(argv[0], &req); + } + if (argc > 1) { + parse_match(argv[1], &(req.match)); + } else { + make_all_match(&(req.match)); + } + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); +} + +static void +stats_global_state(struct vconn *vconn, int argc, char *argv[]) { + struct ofl_exp_msg_multipart_request_global_state req = + {{{{{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_EXPERIMENTER, .flags = 0x0000}, + .experimenter_id = OPENSTATE_VENDOR_ID}, + .type = OFPMP_EXP_FLAGS_STATS}}; + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); +} + static void stats_aggr(struct vconn *vconn, int argc, char *argv[]) { - struct ofl_msg_stats_request_flow req = + struct ofl_msg_multipart_request_flow req = {{{.type = OFPT_MULTIPART_REQUEST}, .type = OFPMP_AGGREGATE, .flags = 0x0000}, .cookie = 0x0000000000000000ULL, @@ -483,7 +559,7 @@ stats_aggr(struct vconn *vconn, int argc, char *argv[]) { static void stats_table(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { - struct ofl_msg_stats_request_header req = + struct ofl_msg_multipart_request_header req = {{.type = OFPT_MULTIPART_REQUEST}, .type = OFPMP_TABLE, .flags = 0x0000}; @@ -494,7 +570,7 @@ stats_table(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED) { static void stats_port(struct vconn *vconn, int argc, char *argv[]) { - struct ofl_msg_stats_request_port req = + struct ofl_msg_multipart_request_port req = {{{.type = OFPT_MULTIPART_REQUEST}, .type = OFPMP_PORT_STATS, .flags = 0x0000}, .port_no = OFPP_ANY}; @@ -510,7 +586,7 @@ stats_port(struct vconn *vconn, int argc, char *argv[]) { static void stats_queue(struct vconn *vconn, int argc, char *argv[]) { - struct ofl_msg_stats_request_queue req = + struct ofl_msg_multipart_request_queue req = {{{.type = OFPT_MULTIPART_REQUEST}, .type = OFPMP_QUEUE, .flags = 0x0000}, .port_no = OFPP_ANY, @@ -530,7 +606,7 @@ stats_queue(struct vconn *vconn, int argc, char *argv[]) { static void stats_group(struct vconn *vconn, int argc, char *argv[]) { - struct ofl_msg_stats_request_group req = + struct ofl_msg_multipart_request_group req = {{{.type = OFPT_MULTIPART_REQUEST}, .type = OFPMP_GROUP, .flags = 0x0000}, .group_id = OFPG_ALL}; @@ -546,7 +622,7 @@ stats_group(struct vconn *vconn, int argc, char *argv[]) { static void stats_group_desc(struct vconn *vconn, int argc, char *argv[]) { - struct ofl_msg_stats_request_group req = + struct ofl_msg_multipart_request_group req = {{{.type = OFPT_MULTIPART_REQUEST}, .type = OFPMP_GROUP_DESC, .flags = 0x0000}, .group_id = OFPG_ALL}; @@ -558,10 +634,6 @@ stats_group_desc(struct vconn *vconn, int argc, char *argv[]) { dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); } - - - - static void set_config(struct vconn *vconn, int argc UNUSED, char *argv[]) { struct ofl_msg_set_config msg = @@ -599,17 +671,38 @@ flow_mod(struct vconn *vconn, int argc, char *argv[]) { .instructions = NULL}; parse_flow_mod_args(argv[0], &msg); - if (argc > 1) { - size_t i; - size_t inst_num = argc - 2; - parse_match(argv[1], &(msg.match)); - - msg.instructions_num = inst_num; - msg.instructions = xmalloc(sizeof(struct ofl_instrcution_header *) * inst_num); + size_t i, j; + size_t inst_num = 0; + if (argc > 2){ + inst_num = argc - 2; + j = 2; + parse_match(argv[1], &(msg.match)); + } + else { + if(msg.command == OFPFC_DELETE) { + inst_num = 0; + parse_match(argv[1], &(msg.match)); + } else { + /*We copy the value because we don't know if + it is an instruction or match. + If the match is empty, the argv is modified + causing errors to instructions parsing*/ + char *cpy = malloc(strlen(argv[1])); + memcpy(cpy, argv[1], strlen(argv[1])); + parse_match(cpy, &(msg.match)); + free(cpy); + if(msg.match->length <= 4){ + inst_num = argc - 1; + j = 1; + } + } + } - for (i=0; i < inst_num; i++) { - parse_inst(argv[2+i], &(msg.instructions[i])); + msg.instructions_num = inst_num; + msg.instructions = xmalloc(sizeof(struct ofl_instruction_header *) * inst_num); + for (i=0; i < inst_num; i++) { + parse_inst(argv[j+i], &(msg.instructions[i])); } } else { make_all_match(&(msg.match)); @@ -618,7 +711,6 @@ flow_mod(struct vconn *vconn, int argc, char *argv[]) { } - static void group_mod(struct vconn *vconn, int argc, char *argv[]) { struct ofl_msg_group_mod msg = @@ -654,7 +746,81 @@ group_mod(struct vconn *vconn, int argc, char *argv[]) { dpctl_send_and_print(vconn, (struct ofl_msg_header *)&msg); } +static void +group_features(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED){ + + struct ofl_msg_multipart_request_header req = + {{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_GROUP_FEATURES, .flags = 0x0000}; + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); +} + +static void meter_mod(struct vconn *vconn, int argc, char *argv[]){ + + struct ofl_msg_meter_mod msg = + {{.type = OFPT_METER_MOD}, + .command = OFPMC_ADD, + .flags = OFPMF_KBPS, + .meter_id = 0, + .meter_bands_num = 0, + .bands = NULL}; + + parse_meter_mod_args(argv[0], &msg); + + if (argc > 1){ + size_t i; + size_t bands_num = argc - 1; + msg.meter_bands_num = bands_num; + msg.bands = xmalloc(sizeof(struct ofl_meter_band_header *) * bands_num); + for (i=0; i < bands_num; i++) { + parse_band(argv[i+1], &msg, &msg.bands[i]); + } + } + dpctl_send_and_print(vconn, (struct ofl_msg_header *)&msg); + +} + +static void +stats_meter(struct vconn *vconn, int argc UNUSED, char *argv[]){ + + struct ofl_msg_multipart_meter_request req = + {{{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_METER, .flags = 0x0000}, + .meter_id = OFPM_ALL}; + + if (argc > 0 && parse_meter(argv[0], &req.meter_id)) { + ofp_fatal(0, "Error parsing meter: %s.", argv[0]); + } + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); +} + +static void +meter_config(struct vconn *vconn, int argc UNUSED, char *argv[]){ + + struct ofl_msg_multipart_meter_request req = + {{{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_METER_CONFIG, .flags = 0x0000}, + .meter_id = OFPM_ALL}; + + if (argc > 0 && parse_meter(argv[0], &req.meter_id)) { + ofp_fatal(0, "Error parsing meter: %s.", argv[0]); + } + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); +} + +static void +meter_features(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED){ + + struct ofl_msg_multipart_request_header req = + {{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_METER_FEATURES, .flags = 0x0000}; + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&req, NULL); +} static void port_mod(struct vconn *vconn, int argc UNUSED, char *argv[]) { @@ -698,7 +864,7 @@ queue_get_config(struct vconn *vconn, int argc UNUSED, char *argv[]) { ofp_fatal(0, "Error parsing queue_get_config port: %s.", argv[0]); } - dpctl_send_and_print(vconn, (struct ofl_msg_header *)&msg); + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&msg, NULL); } @@ -782,29 +948,49 @@ queue_del(struct vconn *vconn, int argc UNUSED, char *argv[]) { dpctl_send_and_print(vconn, (struct ofl_msg_header *)&msg); } +static void +get_async(struct vconn *vconn, int argc UNUSED, char *argv[] UNUSED){ + + struct ofl_msg_async_config msg = + {{.type = OFPT_GET_ASYNC_REQUEST}, + .config = NULL}; + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)&msg, NULL); +} + static struct command all_commands[] = { {"ping", 0, 2, ping}, {"monitor", 0, 0, monitor}, {"features", 0, 0, features }, {"get-config", 0, 0, get_config}, + {"table-features", 0, 0, table_features}, + {"group-features", 0, 0, group_features}, + {"meter-features", 0, 0, meter_features}, {"stats-desc", 0, 0, stats_desc }, {"stats-flow", 0, 2, stats_flow}, + {"stats-state", 0, 2, stats_state}, + {"stats-global-state", 0, 0, stats_global_state}, {"stats-aggr", 0, 2, stats_aggr}, {"stats-table", 0, 0, stats_table }, {"stats-port", 0, 1, stats_port }, {"stats-queue", 0, 2, stats_queue }, {"stats-group", 0, 1, stats_group }, {"stats-group-desc", 0, 1, stats_group_desc }, - + {"stats-meter", 0, 1, stats_meter}, + {"meter-config", 0, 1, meter_config}, + {"port-desc", 0, 0, port_desc}, {"set-config", 1, 1, set_config}, - {"flow-mod", 1, 7/*+1 for each inst type*/, flow_mod }, + {"flow-mod", 1, 8/*+1 for each inst type*/, flow_mod }, {"group-mod", 1, UINT8_MAX, group_mod }, + {"meter-mod", 1, UINT8_MAX, meter_mod}, + {"get-async",0,0, get_async}, {"port-mod", 1, 1, port_mod }, {"table-mod", 1, 1, table_mod }, {"queue-get-config", 1, 1, queue_get_config}, - {"set-desc", 1, 1, set_desc}, + {"set-table-match", 0, 2, set_table_features_match}, + {"queue-mod", 3, 3, queue_mod}, {"queue-del", 2, 2, queue_del} }; @@ -878,6 +1064,8 @@ parse_options(int argc, char *argv[]) {"strict", no_argument, 0, OPT_STRICT}, {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, + {"colors", no_argument, 0, 'c'}, + {"xid", required_argument, 0, 'x'}, VCONN_SSL_LONG_OPTIONS {0, 0, 0, 0}, }; @@ -915,6 +1103,14 @@ parse_options(int argc, char *argv[]) vlog_set_verbosity(optarg); break; + case 'c': + ofl_enable_colors(); + break; + + case 'x': + global_xid = strtoul(optarg, NULL, 0); + break; + VCONN_SSL_OPTION_HANDLERS case '?': @@ -939,6 +1135,8 @@ usage(void) "\n" " SWITCH features show basic information\n" " SWITCH get-config get switch configuration\n" + " SWITCH port-desc print port description and status\n" + " SWITCH meter-config [METER] get meter configuration\n" " SWITCH stats-desc print switch description\n" " SWITCH stats-flow [ARG [MATCH]] print flow stats\n" " SWITCH stats-aggr [ARG [MATCH]] print flow aggregate stats\n" @@ -946,11 +1144,13 @@ usage(void) " SWITCH stats-port [PORT] print port statistics\n" " SWITCH stats-queue [PORT [QUEUE]] print queue statistics\n" " SWITCH stats-group [GROUP] print group statistics\n" + " SWITCH stats-meter [METER] print meter statistics\n" " SWITCH stats-group-desc [GROUP] print group desc statistics\n" "\n" " SWITCH set-config ARG set switch configuration\n" " SWITCH flow-mod ARG [MATCH [INST...]] send flow_mod message\n" " SWITCH group-mod ARG [BUCARG ACT...] send group_mod message\n" + " SWITCH meter-mod ARG [BANDARG ...] send meter_mod message\n" " SWITCH port-mod ARG send port_mod message\n" " SWITCH table-mod ARG send table_mod message\n" " SWITCH queue-get-config PORT send queue_get_config message\n" @@ -967,7 +1167,8 @@ usage(void) " --strict use strict match for flow commands\n" " -t, --timeout=SECS give up after SECS seconds\n" " -h, --help display this help message\n" - " -V, --version display version information\n"); + " -V, --version display version information\n" + " -c, --colors display indented and colored output\n"); exit(EXIT_SUCCESS); } @@ -977,11 +1178,11 @@ parse_match(char *str, struct ofl_match_header **match) { char *token, *saveptr = NULL; struct ofl_match *m = xmalloc(sizeof(struct ofl_match)); ofl_structs_match_init(m); - + for (token = strtok_r(str, KEY_SEP, &saveptr); token != NULL; token = strtok_r(NULL, KEY_SEP, &saveptr)) { - if (strncmp(token, "apply", strlen("apply")) == 0 ) { + if (strncmp(token, "apply", strlen("apply")) == 0 || strncmp(token, "write", strlen("write")) == 0 ) { break; - } + } /* In_port */ if (strncmp(token, MATCH_IN_PORT KEY_VAL, strlen(MATCH_IN_PORT KEY_VAL)) == 0) { uint32_t in_port; @@ -991,96 +1192,155 @@ parse_match(char *str, struct ofl_match_header **match) { else ofl_structs_match_put32(m,OXM_OF_IN_PORT,in_port); continue; } - + /* Ethernet Address*/ if (strncmp(token, MATCH_DL_SRC KEY_VAL, strlen(MATCH_DL_SRC KEY_VAL)) == 0) { uint8_t eth_src[6]; - if (parse_dl_addr(token + strlen(MATCH_DL_SRC KEY_VAL), eth_src)) { + uint8_t *mask; + if (parse_dl_addr(token + strlen(MATCH_DL_SRC KEY_VAL), eth_src, &mask)) { ofp_fatal(0, "Error parsing dl_src: %s.", token); } - else ofl_structs_match_put_eth(m,OXM_OF_ETH_SRC,eth_src); + else { + if (mask == NULL) + ofl_structs_match_put_eth(m,OXM_OF_ETH_SRC,eth_src); + else + ofl_structs_match_put_eth_m(m,OXM_OF_ETH_SRC_W,eth_src,mask); + } continue; } if (strncmp(token, MATCH_DL_DST KEY_VAL, strlen(MATCH_DL_DST KEY_VAL)) == 0) { uint8_t eth_dst[6]; - if (parse_dl_addr(token + strlen(MATCH_DL_DST KEY_VAL), eth_dst)) { + uint8_t *mask; + if (parse_dl_addr(token + strlen(MATCH_DL_DST KEY_VAL), eth_dst, &mask)) { ofp_fatal(0, "Error parsing dl_dst: %s.", token); } - else ofl_structs_match_put_eth(m,OXM_OF_ETH_DST,eth_dst); + else { + if (mask == NULL) + ofl_structs_match_put_eth(m,OXM_OF_ETH_DST,eth_dst); + else + ofl_structs_match_put_eth_m(m,OXM_OF_ETH_DST_W,eth_dst, mask); + } continue; } - /* ARP */ if (strncmp(token, MATCH_ARP_SHA KEY_VAL, strlen(MATCH_ARP_SHA KEY_VAL)) == 0) { uint8_t arp_sha[6]; - if (parse_dl_addr(token + strlen(MATCH_DL_SRC KEY_VAL), arp_sha)) { + uint8_t *mask; + if (parse_dl_addr(token + strlen(MATCH_ARP_SHA KEY_VAL), arp_sha, &mask)) { ofp_fatal(0, "Error parsing arp_sha: %s.", token); } - else ofl_structs_match_put_eth(m, OXM_OF_ARP_SHA, arp_sha); + else { + if (mask == NULL) + ofl_structs_match_put_eth(m, OXM_OF_ARP_SHA, arp_sha); + else + ofl_structs_match_put_eth_m(m, OXM_OF_ARP_SHA_W, arp_sha, mask); + } continue; } if (strncmp(token, MATCH_ARP_THA KEY_VAL, strlen(MATCH_ARP_THA KEY_VAL)) == 0) { uint8_t arp_tha[6]; - if (parse_dl_addr(token + strlen(MATCH_ARP_THA KEY_VAL), arp_tha)) { + uint8_t *mask; + if (parse_dl_addr(token + strlen(MATCH_ARP_THA KEY_VAL), arp_tha, &mask)) { ofp_fatal(0, "Error parsing arp_tha %s.", token); } - else ofl_structs_match_put_eth(m,OXM_OF_ARP_THA, arp_tha); + else { + if (mask == NULL) + ofl_structs_match_put_eth(m,OXM_OF_ARP_THA, arp_tha); + else + ofl_structs_match_put_eth_m(m,OXM_OF_ARP_THA_W, arp_tha, mask); + } + continue; + } + if (strncmp(token, MATCH_ARP_SPA KEY_VAL, strlen(MATCH_ARP_SPA KEY_VAL)) == 0) { + uint32_t arp_src; + uint32_t *mask; + if (parse_nw_addr(token + strlen(MATCH_ARP_SPA KEY_VAL), &(arp_src), &mask)) { + ofp_fatal(0, "Error parsing arp_src: %s.", token); + } + else { + if (mask == NULL) + ofl_structs_match_put32(m, OXM_OF_ARP_SPA,arp_src); + else + ofl_structs_match_put32m(m, OXM_OF_ARP_SPA_W, arp_src, *mask); + } + continue; + } + if (strncmp(token, MATCH_ARP_TPA KEY_VAL, strlen(MATCH_ARP_TPA KEY_VAL)) == 0) { + uint32_t arp_target; + uint32_t *mask; + if (parse_nw_addr(token + strlen(MATCH_ARP_TPA KEY_VAL), &(arp_target), &mask)) { + ofp_fatal(0, "Error parsing arp_target: %s.", token); + } + else { + if (mask == NULL) + ofl_structs_match_put32(m, OXM_OF_ARP_TPA, arp_target); + else + ofl_structs_match_put32m(m, OXM_OF_ARP_TPA_W, arp_target, *mask); + } continue; } if (strncmp(token, MATCH_ARP_OP KEY_VAL, strlen(MATCH_ARP_OP KEY_VAL)) == 0) { - uint8_t arp_op; - if (parse8(token + strlen(MATCH_DL_VLAN_PCP KEY_VAL), NULL, 0, 0x7, &arp_op)) { + uint16_t arp_op; + if (parse16(token + strlen(MATCH_ARP_OP KEY_VAL), NULL, 0, 0x7, &arp_op)){ ofp_fatal(0, "Error parsing arp_op: %s.", token); - } else - ofl_structs_match_put8(m, OXM_OF_ARP_OP, arp_op); + } else { + ofl_structs_match_put16(m, OXM_OF_ARP_OP, arp_op); + } continue; } - + /* VLAN */ if (strncmp(token, MATCH_DL_VLAN KEY_VAL, strlen(MATCH_DL_VLAN KEY_VAL)) == 0) { uint16_t dl_vlan; - if (parse_vlan_vid(token + strlen(MATCH_DL_VLAN KEY_VAL), &dl_vlan)) { - ofp_fatal(0, "Error parsing vlan label: %s.", token); - } - else ofl_structs_match_put16(m,OXM_OF_VLAN_VID, dl_vlan); + char *str = token + strlen(MATCH_DL_VLAN KEY_VAL); + + if (strcmp(str, "any") == 0) + ofl_structs_match_put16m(m,OXM_OF_VLAN_VID_W, OFPVID_PRESENT, OFPVID_PRESENT); + else if (strcmp(str, "none") == 0) + ofl_structs_match_put16(m,OXM_OF_VLAN_VID, OFPVID_NONE); + else if (parse16(str, NULL, 0, 0xfff, &dl_vlan)) + ofp_fatal(0, "Error parsing vlan label: %s.", token); + else + ofl_structs_match_put16(m,OXM_OF_VLAN_VID, dl_vlan | OFPVID_PRESENT); + continue; } if (strncmp(token, MATCH_DL_VLAN_PCP KEY_VAL, strlen(MATCH_DL_VLAN_PCP KEY_VAL)) == 0) { uint8_t pcp; if (parse8(token + strlen(MATCH_DL_VLAN_PCP KEY_VAL), NULL, 0, 0x7, &pcp)) { ofp_fatal(0, "Error parsing vlan pcp: %s.", token); - } else + } else ofl_structs_match_put8(m, OXM_OF_VLAN_PCP, pcp); continue; } - + /* Eth Type */ if (strncmp(token, MATCH_DL_TYPE KEY_VAL, strlen(MATCH_DL_TYPE KEY_VAL)) == 0) { uint16_t dl_type; if (parse16(token + strlen(MATCH_DL_TYPE KEY_VAL), NULL, 0, 0xffff, &dl_type)) { ofp_fatal(0, "Error parsing eth_type: %s.", token); } - else + else ofl_structs_match_put16(m, OXM_OF_ETH_TYPE,dl_type); continue; } - + /* IP */ - if (strncmp(token, MATCH_IP_ECN, strlen(MATCH_IP_ECN KEY_VAL)) == 0) { + if (strncmp(token, MATCH_IP_ECN KEY_VAL, strlen(MATCH_IP_ECN KEY_VAL)) == 0) { uint8_t ip_ecn; if (parse8(token + strlen(MATCH_IP_ECN KEY_VAL), NULL, 0, 0x3f, &ip_ecn)) { ofp_fatal(0, "Error parsing nw_tos: %s.", token); } - else + else ofl_structs_match_put8(m, OXM_OF_IP_ECN, ip_ecn); continue; } - if (strncmp(token, MATCH_IP_DSCP, strlen(MATCH_IP_DSCP KEY_VAL)) == 0) { + if (strncmp(token, MATCH_IP_DSCP KEY_VAL, strlen(MATCH_IP_DSCP KEY_VAL)) == 0) { uint8_t ip_dscp; if (parse8(token + strlen(MATCH_IP_DSCP KEY_VAL), NULL, 0, 0x3f, &ip_dscp)) { ofp_fatal(0, "Error parsing nw_tos: %s.", token); } - else + else ofl_structs_match_put8(m, OXM_OF_IP_DSCP, ip_dscp); continue; } @@ -1089,46 +1349,58 @@ parse_match(char *str, struct ofl_match_header **match) { if (parse8(token + strlen(MATCH_NW_PROTO KEY_VAL), NULL, 0, 0xff, &nw_proto)) { ofp_fatal(0, "Error parsing ip_proto: %s.", token); } - else ofl_structs_match_put8(m,OXM_OF_IP_PROTO, nw_proto); + else ofl_structs_match_put8(m,OXM_OF_IP_PROTO, nw_proto); continue; } if (strncmp(token, MATCH_NW_SRC KEY_VAL, strlen(MATCH_NW_SRC KEY_VAL)) == 0) { uint32_t nw_src; - if (parse_nw_addr(token + strlen(MATCH_NW_SRC KEY_VAL), &(nw_src))) { + uint32_t *mask; + if (parse_nw_addr(token + strlen(MATCH_NW_SRC KEY_VAL), &(nw_src), &mask)) { ofp_fatal(0, "Error parsing ip_src: %s.", token); } - else ofl_structs_match_put32(m, OXM_OF_IPV4_SRC,nw_src); + else { + if (mask == NULL) + ofl_structs_match_put32(m, OXM_OF_IPV4_SRC,nw_src); + else + ofl_structs_match_put32m(m, OXM_OF_IPV4_SRC_W, nw_src, *mask); + } continue; } if (strncmp(token, MATCH_NW_DST KEY_VAL, strlen(MATCH_NW_DST KEY_VAL)) == 0) { uint32_t nw_dst; - if (parse_nw_addr(token + strlen(MATCH_NW_DST KEY_VAL), &nw_dst)) { + uint32_t *mask; + if (parse_nw_addr(token + strlen(MATCH_NW_DST KEY_VAL), &nw_dst, &mask)) { ofp_fatal(0, "Error parsing ip_dst: %s.", token); } - else ofl_structs_match_put32(m, OXM_OF_IPV4_DST,nw_dst); + else { + if (mask == NULL) + ofl_structs_match_put32(m, OXM_OF_IPV4_DST,nw_dst); + else + ofl_structs_match_put32m(m, OXM_OF_IPV4_DST_W,nw_dst, *mask); + } continue; } - + /* ICMP */ - if (strncmp(token, MATCH_ICMPV4_CODE, strlen(MATCH_ICMPV4_CODE KEY_VAL)) == 0) { + if (strncmp(token, MATCH_ICMPV4_CODE KEY_VAL, strlen(MATCH_ICMPV4_CODE KEY_VAL)) == 0) { uint8_t icmpv4_code; if (parse8(token + strlen(MATCH_ICMPV4_CODE KEY_VAL), NULL, 0, 0x3f, &icmpv4_code)) { ofp_fatal(0, "Error parsing icmpv4_code: %s.", token); } - else + else ofl_structs_match_put8(m, OXM_OF_ICMPV4_CODE, icmpv4_code); continue; - } - if (strncmp(token, MATCH_ICMPV4_TYPE, strlen(MATCH_ICMPV4_TYPE KEY_VAL)) == 0) { + } + if (strncmp(token, MATCH_ICMPV4_TYPE KEY_VAL, strlen(MATCH_ICMPV4_TYPE KEY_VAL)) == 0) { uint8_t icmpv4_type; if (parse8(token + strlen(MATCH_ICMPV4_TYPE KEY_VAL), NULL, 0, 0x3f, &icmpv4_type)) { ofp_fatal(0, "Error parsing icmpv4_type: %s.", token); } - else - ofl_structs_match_put8(m, OXM_OF_ICMPV4_CODE, icmpv4_type); + else + ofl_structs_match_put8(m, OXM_OF_ICMPV4_TYPE, icmpv4_type); continue; - } - + } + /* TCP */ if (strncmp(token, MATCH_TP_SRC KEY_VAL, strlen(MATCH_TP_SRC KEY_VAL)) == 0) { uint16_t tp_src; @@ -1146,7 +1418,7 @@ parse_match(char *str, struct ofl_match_header **match) { else ofl_structs_match_put16(m, OXM_OF_TCP_DST,tp_dst); continue; } - + /*UDP */ if (strncmp(token, MATCH_UDP_SRC KEY_VAL, strlen(MATCH_UDP_SRC KEY_VAL)) == 0) { uint16_t udp_src; @@ -1164,7 +1436,7 @@ parse_match(char *str, struct ofl_match_header **match) { else ofl_structs_match_put16(m, OXM_OF_UDP_DST,udp_dst); continue; } - + /*SCTP*/ if (strncmp(token, MATCH_SCTP_SRC KEY_VAL, strlen(MATCH_SCTP_SRC KEY_VAL)) == 0) { uint16_t sctp_src; @@ -1182,71 +1454,97 @@ parse_match(char *str, struct ofl_match_header **match) { else ofl_structs_match_put16(m, OXM_OF_SCTP_DST,sctp_dst); continue; } - - /* MPLS */ + /* MPLS */ if (strncmp(token, MATCH_MPLS_LABEL KEY_VAL, strlen(MATCH_MPLS_LABEL KEY_VAL)) == 0) { uint32_t mpls_label; if (parse32(token + strlen(MATCH_MPLS_LABEL KEY_VAL), NULL, 0, 0xfffff, &mpls_label)) { ofp_fatal(0, "Error parsing mpls_label: %s.", token); } else ofl_structs_match_put32(m,OXM_OF_MPLS_LABEL,mpls_label); + continue; } if (strncmp(token, MATCH_MPLS_TC KEY_VAL, strlen(MATCH_MPLS_TC KEY_VAL)) == 0) { uint8_t mpls_tc; - if (parse8(token + strlen(MATCH_MPLS_TC KEY_VAL), NULL, 0, 0x07, &mpls_tc)) { - ofp_fatal(0, "Error parsing mpls_tc: %s.", token); - } - else - ofl_structs_match_put8(m, OXM_OF_MPLS_TC, mpls_tc); + if (parse8(token + strlen(MATCH_MPLS_TC KEY_VAL), NULL, 0, 0x07, &mpls_tc)) { + ofp_fatal(0, "Error parsing mpls_tc: %s.", token); + } + else + ofl_structs_match_put8(m, OXM_OF_MPLS_TC, mpls_tc); + continue; + } + if (strncmp(token, MATCH_MPLS_BOS KEY_VAL, strlen(MATCH_MPLS_BOS KEY_VAL)) == 0) { + uint8_t mpls_bos; + if (parse8(token + strlen(MATCH_MPLS_BOS KEY_VAL), NULL, 0, 0x1, &mpls_bos)) { + ofp_fatal(0, "Error parsing mpls_tc: %s.", token); + } + else + ofl_structs_match_put8(m, OXM_OF_MPLS_BOS, mpls_bos); continue; } - /* IPv6 */ if (strncmp(token, MATCH_NW_SRC_IPV6 KEY_VAL , strlen(MATCH_NW_SRC_IPV6 KEY_VAL)) == 0) { struct in6_addr addr, mask; + struct in6_addr in6addr_zero = IN6ADDR_ZERO_INIT; if (str_to_ipv6(token + strlen(MATCH_NW_DST_IPV6)+1, &addr, &mask) < 0) { ofp_fatal(0, "Error parsing nw_src_ipv6: %s.", token); } else { - ofl_structs_match_put_ipv6(m, OXM_OF_IPV6_SRC, addr.s6_addr); + if(ipv6_addr_equals(&mask, &in6addr_zero)){ + ofl_structs_match_put_ipv6(m, OXM_OF_IPV6_SRC, addr.s6_addr); + } + else { + ofl_structs_match_put_ipv6m(m, OXM_OF_IPV6_SRC_W,addr.s6_addr, mask.s6_addr); + } } continue; } if (strncmp(token, MATCH_NW_DST_IPV6 KEY_VAL , strlen(MATCH_NW_DST_IPV6 KEY_VAL)) == 0) { struct in6_addr addr, mask; + struct in6_addr in6addr_zero = IN6ADDR_ZERO_INIT; if (str_to_ipv6(token + strlen(MATCH_NW_DST_IPV6)+1, &addr, &mask) < 0) { ofp_fatal(0, "Error parsing nw_src_ipv6: %s.", token); } else { - ofl_structs_match_put_ipv6(m, OXM_OF_IPV6_DST, addr.s6_addr); + if(ipv6_addr_equals(&mask, &in6addr_zero)){ + ofl_structs_match_put_ipv6(m, OXM_OF_IPV6_DST, addr.s6_addr); + } + else { + ofl_structs_match_put_ipv6m(m, OXM_OF_IPV6_DST_W, addr.s6_addr, mask.s6_addr); + } } continue; } if (strncmp(token, MATCH_IPV6_FLABEL KEY_VAL, strlen(MATCH_IPV6_FLABEL KEY_VAL)) == 0) { uint32_t ipv6_label; - if (parse32(token + strlen(MATCH_IPV6_FLABEL KEY_VAL), NULL, 0, 0xfffff, &ipv6_label)) { + uint32_t *mask; + if (parse32m(token + strlen(MATCH_IPV6_FLABEL KEY_VAL), NULL, 0, 0xfffff, &ipv6_label, &mask)) { ofp_fatal(0, "Error parsing ipv6_label: %s.", token); } - else ofl_structs_match_put32(m,OXM_OF_IPV6_FLABEL, ipv6_label); - } - + else + if(mask == NULL) + ofl_structs_match_put32(m, OXM_OF_IPV6_FLABEL, ipv6_label); + else + ofl_structs_match_put32m(m, OXM_OF_IPV6_FLABEL_W, ipv6_label, *mask); + continue; + } + /* ICMPv6 */ - if (strncmp(token, MATCH_ICMPV6_CODE, strlen(MATCH_ICMPV6_CODE KEY_VAL)) == 0) { + if (strncmp(token, MATCH_ICMPV6_CODE KEY_VAL, strlen(MATCH_ICMPV6_CODE KEY_VAL)) == 0) { uint8_t icmpv6_code; if (parse8(token + strlen(MATCH_ICMPV6_CODE KEY_VAL), NULL, 0, 0x3f, &icmpv6_code)) { ofp_fatal(0, "Error parsing icmpv6_code: %s.", token); } - else + else ofl_structs_match_put8(m, OXM_OF_ICMPV6_CODE, icmpv6_code); continue; - } - if (strncmp(token, MATCH_ICMPV6_TYPE, strlen(MATCH_ICMPV6_TYPE KEY_VAL)) == 0) { + } + if (strncmp(token, MATCH_ICMPV6_TYPE KEY_VAL, strlen(MATCH_ICMPV6_TYPE KEY_VAL)) == 0) { uint8_t icmpv6_type; if (parse8(token + strlen(MATCH_ICMPV6_TYPE KEY_VAL), NULL, 0, 0x3f, &icmpv6_type)) { ofp_fatal(0, "Error parsing icmpv6_type: %s.", token); } - else - ofl_structs_match_put8(m, OXM_OF_ICMPV6_CODE, icmpv6_type); + else + ofl_structs_match_put8(m, OXM_OF_ICMPV6_TYPE, icmpv6_type); continue; } @@ -1257,150 +1555,391 @@ parse_match(char *str, struct ofl_match_header **match) { ofp_fatal(0, "Error parsing ipv6_nd_target %s.", token); } else { - ofl_structs_match_put_ipv6(m, OXM_OF_IPV6_ND_TARGET, addr.s6_addr); + ofl_structs_match_put_ipv6(m, OXM_OF_IPV6_ND_TARGET, addr.s6_addr); } continue; - } + } if (strncmp(token, MATCH_IPV6_ND_SLL KEY_VAL, strlen(MATCH_IPV6_ND_SLL KEY_VAL)) == 0) { uint8_t eth_src[6]; - if (parse_dl_addr(token + strlen(MATCH_IPV6_ND_SLL KEY_VAL), eth_src)) { + uint8_t *mask; + if (parse_dl_addr(token + strlen(MATCH_IPV6_ND_SLL KEY_VAL), eth_src, &mask)) { ofp_fatal(0, "Error parsing ipv6_nd_sll: %s.", token); } - else ofl_structs_match_put_eth(m,OXM_OF_IPV6_ND_SLL, eth_src); + else { + ofl_structs_match_put_eth(m,OXM_OF_IPV6_ND_SLL, eth_src); + } continue; } if (strncmp(token, MATCH_IPV6_ND_TLL KEY_VAL, strlen(MATCH_IPV6_ND_TLL KEY_VAL)) == 0) { uint8_t eth_dst[6]; - if (parse_dl_addr(token + strlen(MATCH_IPV6_ND_TLL KEY_VAL), eth_dst)) { + uint8_t *mask; + if (parse_dl_addr(token + strlen(MATCH_IPV6_ND_TLL KEY_VAL), eth_dst, &mask)) { ofp_fatal(0, "Error parsing ipv_nd_tll: %s.", token); } - else ofl_structs_match_put_eth(m, OXM_OF_IPV6_ND_TLL,eth_dst); + else { + ofl_structs_match_put_eth(m, OXM_OF_IPV6_ND_TLL,eth_dst); + } continue; } - + /* Metadata */ if (strncmp(token, MATCH_METADATA KEY_VAL, strlen(MATCH_METADATA KEY_VAL)) == 0) { uint64_t metadata; - if (sscanf(token, MATCH_METADATA KEY_VAL "0x%"SCNx64"", (&metadata))) { + if (sscanf(token, MATCH_METADATA KEY_VAL "0x%"SCNx64"", (&metadata)) != 1) { ofp_fatal(0, "Error parsing %s: %s.", MATCH_METADATA, token); } else ofl_structs_match_put64(m, OXM_OF_METADATA, metadata); continue; } + /*PBB ISID*/ + if (strncmp(token, MATCH_PBB_ISID KEY_VAL, strlen(MATCH_PBB_ISID KEY_VAL)) == 0) { + uint32_t pbb_isid; + if (parse32(token + strlen(MATCH_PBB_ISID KEY_VAL), NULL, 0, 0x1000000, &pbb_isid)) { + ofp_fatal(0, "Error parsing pbb_isid: %s.", token); + } + else ofl_structs_match_put32(m, OXM_OF_PBB_ISID, pbb_isid); + continue; + } + /* Tunnel ID */ + if (strncmp(token, MATCH_TUNNEL_ID KEY_VAL, strlen(MATCH_TUNNEL_ID KEY_VAL)) == 0) { + uint64_t tunn_id; + if (sscanf(token, MATCH_TUNNEL_ID KEY_VAL "0x%"SCNx64"", (&tunn_id)) != 1) { + ofp_fatal(0, "Error parsing %s: %s.", MATCH_TUNNEL_ID, token); + } + else ofl_structs_match_put64(m, OXM_OF_TUNNEL_ID, tunn_id); + continue; + } + /*Extension Headers */ + if (strncmp(token, MATCH_EXT_HDR KEY_VAL, strlen(MATCH_EXT_HDR KEY_VAL)) == 0) { + uint16_t ext_hdr; + if (parse_ext_hdr(token + strlen(MATCH_EXT_HDR KEY_VAL), &ext_hdr)) { + ofp_fatal(0, "Error parsing ext_hdr %s.", token); + } + else ofl_structs_match_put16(m, OXM_OF_IPV6_EXTHDR, ext_hdr); + continue; + } ofp_fatal(0, "Error parsing match arg: %s.", token); } - + (*match) = (struct ofl_match_header *)m; } static int parse_set_field(char *token, struct ofl_action_set_field *act) { - - - if (strncmp(token, MATCH_DL_SRC KEY_VAL, strlen(MATCH_DL_SRC KEY_VAL)) == 0) { - uint8_t* dl_src = xmalloc(6); - if (parse_dl_addr(token + strlen(MATCH_DL_SRC KEY_VAL), dl_src)) { + + + if (strncmp(token, MATCH_DL_SRC KEY_VAL2, strlen(MATCH_DL_SRC KEY_VAL2)) == 0) { + uint8_t* dl_src = xmalloc(6); + uint8_t *mask = NULL; + if (parse_dl_addr(token + strlen(MATCH_DL_SRC KEY_VAL2), dl_src, &mask)) { ofp_fatal(0, "Error parsing dl_src: %s.", token); - }else{ + }else{ act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); - act->field->header = OXM_OF_ETH_SRC; + act->field->header = OXM_OF_ETH_SRC; act->field->value = (uint8_t*) dl_src; - } + } return 0; } - if (strncmp(token, MATCH_DL_DST KEY_VAL, strlen(MATCH_DL_DST KEY_VAL)) == 0) { - uint8_t* dl_dst = xmalloc(6); - if (parse_dl_addr(token + strlen(MATCH_DL_SRC KEY_VAL), dl_dst)) { - ofp_fatal(0, "Error parsing dl_dst: %s.", token); - }else{ + if (strncmp(token, MATCH_DL_DST KEY_VAL2, strlen(MATCH_DL_DST KEY_VAL2)) == 0) { + uint8_t* dl_dst = xmalloc(6); + uint8_t *mask = NULL; + if (parse_dl_addr(token + strlen(MATCH_DL_DST KEY_VAL2), dl_dst, &mask)) { + ofp_fatal(0, "Error parsing dl_src: %s.", token); + }else{ act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); - act->field->header = OXM_OF_ETH_DST; + act->field->header = OXM_OF_ETH_DST; act->field->value = (uint8_t*) dl_dst; - } + } + return 0; + } + if (strncmp(token, MATCH_DL_TYPE KEY_VAL2, strlen(MATCH_DL_TYPE KEY_VAL2)) == 0) { + uint16_t* dl_type = xmalloc(sizeof(uint16_t)); + if (parse16(token + strlen(MATCH_DL_TYPE KEY_VAL2), NULL, 0, 0xffff, dl_type)) { + ofp_fatal(0, "Error parsing dl_type: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_ETH_TYPE; + act->field->value = (uint8_t*) dl_type; + } + return 0; } - if (strncmp(token, MATCH_DL_VLAN KEY_VAL, strlen(MATCH_DL_VLAN KEY_VAL)) == 0) { + + /* ARP */ + if (strncmp(token, MATCH_ARP_SHA KEY_VAL2, strlen(MATCH_ARP_SHA KEY_VAL2)) == 0) { + uint8_t arp_sha[6]; + uint8_t *mask; + if (parse_dl_addr(token + strlen(MATCH_ARP_SHA KEY_VAL2), arp_sha, &mask)) { + ofp_fatal(0, "Error parsing arp_sha: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_ARP_SHA; + act->field->value = (uint8_t*) arp_sha; + } + return 0; + } + if (strncmp(token, MATCH_ARP_THA KEY_VAL2, strlen(MATCH_ARP_THA KEY_VAL2)) == 0) { + uint8_t arp_tha[6]; + uint8_t *mask; + if (parse_dl_addr(token + strlen(MATCH_ARP_THA KEY_VAL2), arp_tha, &mask)) { + ofp_fatal(0, "Error parsing arp_tha %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_ARP_THA; + act->field->value = (uint8_t*) arp_tha; + } + return 0; + } + if (strncmp(token, MATCH_ARP_SPA KEY_VAL2, strlen(MATCH_ARP_SPA KEY_VAL2)) == 0) { + uint32_t *arp_src = malloc(sizeof(uint32_t)); + uint32_t *mask; + if (parse_nw_addr(token + strlen(MATCH_ARP_SPA KEY_VAL2), arp_src, &mask)) { + ofp_fatal(0, "Error parsing arp_src: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_ARP_SPA; + act->field->value = (uint8_t*) arp_src; + } + return 0; + } + if (strncmp(token, MATCH_ARP_TPA KEY_VAL2, strlen(MATCH_ARP_TPA KEY_VAL2)) == 0) { + uint32_t *arp_target = malloc(sizeof(uint32_t)); + uint32_t *mask; + if (parse_nw_addr(token + strlen(MATCH_ARP_TPA KEY_VAL2), arp_target, &mask)) { + ofp_fatal(0, "Error parsing arp_target: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_ARP_TPA; + act->field->value = (uint8_t*) arp_target; + } + return 0; + } + if (strncmp(token, MATCH_ARP_OP KEY_VAL2, strlen(MATCH_ARP_OP KEY_VAL2)) == 0) { + uint16_t *arp_op = xmalloc(sizeof(uint16_t)); + if (parse16(token + strlen(MATCH_ARP_OP KEY_VAL2), NULL, 0, 0x7, arp_op)){ + ofp_fatal(0, "Error parsing arp_op: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_ARP_OP; + act->field->value = (uint8_t*) arp_op; + } + return 0; + } + if (strncmp(token, MATCH_DL_VLAN KEY_VAL2, strlen(MATCH_DL_VLAN KEY_VAL2)) == 0) { uint16_t *dl_vlan = malloc(sizeof(uint16_t)); - if (parse_vlan_vid(token + strlen(MATCH_DL_VLAN KEY_VAL), dl_vlan)) { + if (parse_vlan_vid(token + strlen(MATCH_DL_VLAN KEY_VAL2), dl_vlan)) { ofp_fatal(0, "Error parsing vlan label: %s.", token); } - else { + else { act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); - act->field->header = OXM_OF_VLAN_VID; - act->field->value = (uint8_t*) dl_vlan; + act->field->header = OXM_OF_VLAN_VID; + *dl_vlan = *dl_vlan | OFPVID_PRESENT; + act->field->value = (uint8_t*) dl_vlan; } return 0; } - if (strncmp(token, MATCH_DL_VLAN_PCP KEY_VAL, strlen(MATCH_DL_VLAN_PCP KEY_VAL)) == 0) { + if (strncmp(token, MATCH_DL_VLAN_PCP KEY_VAL2, strlen(MATCH_DL_VLAN_PCP KEY_VAL2)) == 0) { + uint8_t *pcp = malloc(sizeof(uint8_t)); + if (parse8(token + strlen(MATCH_DL_VLAN_PCP KEY_VAL2), NULL, 0, 0x7, pcp)) { + ofp_fatal(0, "Error parsing vlan pcp: %s.", token); + } else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_VLAN_PCP; + act->field->value = (uint8_t*) pcp; + } + return 0; + } + if (strncmp(token, MATCH_PBB_ISID KEY_VAL2, strlen(MATCH_PBB_ISID KEY_VAL2)) == 0) { + uint32_t *pbb_isid = malloc(sizeof(uint32_t)); + if (parse32(token + strlen(MATCH_PBB_ISID KEY_VAL2), NULL, 0, 0x1000000, pbb_isid)) { + ofp_fatal(0, "Error parsing pbb service id: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_PBB_ISID; + act->field->value = (uint8_t*) pbb_isid; + } + return 0; + } + if (strncmp(token, MATCH_MPLS_LABEL KEY_VAL2, strlen(MATCH_MPLS_LABEL KEY_VAL2)) == 0) { + uint32_t *mpls_label = malloc(sizeof(uint32_t)); + if (parse32(token + strlen(MATCH_MPLS_LABEL KEY_VAL2), NULL, 0, 0x1000000, mpls_label)) { + ofp_fatal(0, "Error parsing mpls label id: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_MPLS_LABEL; + act->field->value = (uint8_t*) mpls_label; + } + return 0; + } + if (strncmp(token, MATCH_MPLS_TC KEY_VAL2, strlen(MATCH_MPLS_TC KEY_VAL2)) == 0) { + uint8_t *mpls_tc = (uint8_t*) malloc(sizeof(uint8_t)); + if (parse8(token + strlen(MATCH_MPLS_TC KEY_VAL2), NULL, 0, 0x07, mpls_tc)) { + ofp_fatal(0, "Error parsing mpls_tc: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_MPLS_TC; + act->field->value = mpls_tc; + } + return 0; + } + if (strncmp(token, MATCH_MPLS_BOS KEY_VAL2, strlen(MATCH_MPLS_BOS KEY_VAL2)) == 0) { + uint8_t *mpls_bos = (uint8_t*) malloc(sizeof(uint8_t)); + if (parse8(token + strlen(MATCH_MPLS_BOS KEY_VAL2), NULL, 0, 0x01, mpls_bos)) { + ofp_fatal(0, "Error parsing mpls_bos: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_MPLS_BOS; + act->field->value = mpls_bos; + } + return 0; + } + if (strncmp(token, MATCH_DL_VLAN_PCP KEY_VAL2, strlen(MATCH_DL_VLAN_PCP KEY_VAL2)) == 0) { uint8_t* vlan_pcp = malloc(sizeof(uint8_t)); - if (parse8(token + strlen(MATCH_DL_VLAN_PCP KEY_VAL), NULL, 0, 0x7, vlan_pcp)) { + if (parse8(token + strlen(MATCH_DL_VLAN_PCP KEY_VAL2), NULL, 0, 0x7, vlan_pcp)) { ofp_fatal(0, "Error parsing vlan pcp: %s.", token); } else{ act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); - act->field->header = OXM_OF_VLAN_PCP; - act->field->value = (uint8_t*) vlan_pcp; + act->field->header = OXM_OF_VLAN_PCP; + act->field->value = (uint8_t*) vlan_pcp; } return 0; } - if (strncmp(token, MATCH_DL_TYPE KEY_VAL, strlen(MATCH_DL_TYPE KEY_VAL)) == 0) { - uint16_t* dl_type = xmalloc(sizeof(uint16_t)); - if (parse16(token + strlen(MATCH_DL_TYPE KEY_VAL), NULL, 0, 0xffff, dl_type)) { - ofp_fatal(0, "Error parsing dl_type: %s.", token); - } - else { - act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); - act->field->header = OXM_OF_ETH_TYPE; - act->field->value = (uint8_t*) dl_type; - } - return 0; - } - if (strncmp(token, MATCH_NW_SRC KEY_VAL, strlen(MATCH_NW_SRC KEY_VAL)) == 0) { + if (strncmp(token, MATCH_NW_SRC KEY_VAL2, strlen(MATCH_NW_SRC KEY_VAL2)) == 0) { uint32_t* nw_src = malloc(sizeof(uint32_t)); - if (parse_nw_addr(token + strlen(MATCH_NW_SRC KEY_VAL), nw_src)) { + uint32_t *mask; + + if (parse_nw_addr(token + strlen(MATCH_NW_SRC KEY_VAL2), nw_src, &mask)) { ofp_fatal(0, "Error parsing ip_src: %s.", token); } else { act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); - act->field->header = OXM_OF_IPV4_SRC; - act->field->value = (uint8_t*) nw_src; + act->field->header = OXM_OF_IPV4_SRC; + act->field->value = (uint8_t*) nw_src; } return 0; } - if (strncmp(token, MATCH_NW_DST KEY_VAL, strlen(MATCH_NW_DST KEY_VAL)) == 0) { + if (strncmp(token, MATCH_NW_DST KEY_VAL2, strlen(MATCH_NW_DST KEY_VAL2)) == 0) { uint32_t * nw_dst = malloc(sizeof(uint32_t)); - if (parse_nw_addr(token + strlen(MATCH_NW_DST KEY_VAL), nw_dst)) { + uint32_t *mask; + + if (parse_nw_addr(token + strlen(MATCH_NW_DST KEY_VAL2), nw_dst, &mask)) { ofp_fatal(0, "Error parsing ip_dst: %s.", token); } else { act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); - act->field->header = OXM_OF_IPV4_DST; - act->field->value = (uint8_t*) nw_dst; + act->field->header = OXM_OF_IPV4_DST; + act->field->value = (uint8_t*) nw_dst; + } + return 0; + } + if (strncmp(token, MATCH_IP_ECN KEY_VAL2, strlen(MATCH_NW_DST KEY_VAL2)) == 0) { + uint8_t *ip_ecn = malloc(sizeof(uint8_t)); + if (parse8(token + strlen(MATCH_IP_ECN KEY_VAL2), NULL, 0, 0x3, ip_ecn)) { + ofp_fatal(0, "Error parsing nw_tos: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_IP_ECN; + act->field->value = (uint8_t*) ip_ecn; } return 0; } - if (strncmp(token, MATCH_TP_SRC KEY_VAL, strlen(MATCH_TP_SRC KEY_VAL)) == 0) { + if (strncmp(token, MATCH_IP_DSCP KEY_VAL2, strlen(MATCH_NW_DST KEY_VAL2)) == 0) { + uint8_t * dscp = malloc(sizeof(uint8_t)); + + if (parse8(token + strlen(MATCH_IP_DSCP KEY_VAL2), NULL, 0, 0x40, dscp)) { + ofp_fatal(0, "Error parsing nw_tos: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_IP_DSCP; + act->field->value = (uint8_t*) dscp; + } + return 0; + } + if (strncmp(token, MATCH_NW_PROTO KEY_VAL2, strlen(MATCH_NW_PROTO KEY_VAL2)) == 0) { + uint8_t *nw_proto = malloc(sizeof(uint8_t)); + if (parse8(token + strlen(MATCH_NW_PROTO KEY_VAL2), NULL, 0, 0xff, nw_proto)) { + ofp_fatal(0, "Error parsing ip_proto: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_IP_PROTO; + act->field->value = (uint8_t*) nw_proto; + } + return 0; + } + if (strncmp(token, MATCH_TP_SRC KEY_VAL2, strlen(MATCH_TP_SRC KEY_VAL2)) == 0) { uint16_t* tp_src = xmalloc(2); - if (parse16(token+ strlen(MATCH_TP_SRC KEY_VAL), NULL, 0, 0xffff, tp_src)) { + if (parse16(token+ strlen(MATCH_TP_SRC KEY_VAL2), NULL, 0, 0xffff, tp_src)) { ofp_fatal(0, "Error parsing tcp_src: %s.", token); - }else{ + }else{ act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); act->field->header = OXM_OF_TCP_SRC; act->field->value = (uint8_t*) tp_src; - } + } return 0; } - if (strncmp(token, MATCH_TP_DST KEY_VAL, strlen(MATCH_TP_DST KEY_VAL)) == 0) { + if (strncmp(token, MATCH_TP_DST KEY_VAL2, strlen(MATCH_TP_DST KEY_VAL2)) == 0) { uint16_t* tp_dst = xmalloc(2); - if (parse16(token + strlen(MATCH_TP_SRC KEY_VAL), NULL, 0, 0xffff, tp_dst)) { + if (parse16(token + strlen(MATCH_TP_DST KEY_VAL2), NULL, 0, 0xffff, tp_dst)) { ofp_fatal(0, "Error parsing tcp_src: %s.", token); - }else{ + }else{ act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); act->field->header = OXM_OF_TCP_DST; act->field->value = (uint8_t*) tp_dst; - } + } + return 0; + } + if (strncmp(token, MATCH_NW_SRC_IPV6 KEY_VAL2 , strlen(MATCH_NW_SRC_IPV6 KEY_VAL2)) == 0) { + struct in6_addr *addr = (struct in6_addr*) malloc(sizeof(struct in6_addr)); + struct in6_addr mask; + if (str_to_ipv6(token + strlen(MATCH_NW_SRC_IPV6)+1, addr, &mask) < 0) { + ofp_fatal(0, "Error parsing nw_src_ipv6: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_IPV6_SRC; + act->field->value = (uint8_t*) addr->s6_addr; + } + return 0; + } + if (strncmp(token, MATCH_NW_DST_IPV6 KEY_VAL2 , strlen(MATCH_NW_DST_IPV6 KEY_VAL2)) == 0) { + struct in6_addr *addr = (struct in6_addr*) malloc(sizeof(struct in6_addr)); + struct in6_addr mask; + if (str_to_ipv6(token + strlen(MATCH_NW_DST_IPV6)+1, addr, &mask) < 0) { + ofp_fatal(0, "Error parsing nw_src_ipv6: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_IPV6_DST; + act->field->value = (uint8_t*) addr->s6_addr; + } + return 0; + } + if (strncmp(token, MATCH_IPV6_FLABEL KEY_VAL2, strlen(MATCH_IPV6_FLABEL KEY_VAL2)) == 0) { + uint32_t *ipv6_label = malloc(sizeof(uint32_t)); + if (parse32(token + strlen(MATCH_IPV6_FLABEL KEY_VAL2), NULL, 0, 0x000fffff, ipv6_label)) { + ofp_fatal(0, "Error parsing ipv6_label: %s.", token); + } + else { + act->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); + act->field->header = OXM_OF_IPV6_FLABEL; + act->field->value = (uint8_t*) ipv6_label; + } return 0; } - ofp_fatal(0, "Error parsing set_field arg: %s.", token); + ofp_fatal(0, "Error parsing set_field arg: %s.", token); } static void @@ -1439,7 +1978,7 @@ parse_action(uint16_t type, char *str, struct ofl_action_header **act) { struct ofl_action_set_field *a = xmalloc(sizeof (struct ofl_action_set_field)); if (parse_set_field(str, a)) { ofp_fatal(0, "Error parsing field in set_field action: %s.", str); - } + } (*act) = (struct ofl_action_header *)a; break; } @@ -1463,15 +2002,17 @@ parse_action(uint16_t type, char *str, struct ofl_action_header **act) { break; } case (OFPAT_PUSH_VLAN): + case (OFPAT_PUSH_PBB): case (OFPAT_PUSH_MPLS): { struct ofl_action_push *a = xmalloc(sizeof(struct ofl_action_push)); if (sscanf(str, "0x%"SCNx16"", &(a->ethertype)) != 1) { - ofp_fatal(0, "Error parsing ethertype in push_mpls/vlan action: %s.", str); + ofp_fatal(0, "Error parsing ethertype in push_mpls/vlan/pbb action: %s.", str); } (*act) = (struct ofl_action_header *)a; break; } - case (OFPAT_POP_VLAN): { + case (OFPAT_POP_VLAN): + case (OFPAT_POP_PBB): { struct ofl_action_header *a = xmalloc(sizeof(struct ofl_action_header)); (*act) = a; break; @@ -1527,9 +2068,10 @@ parse_actions(char *str, size_t *acts_num, struct ofl_action_header ***acts) { size_t i; bool found; struct ofl_action_header *act = NULL; - + for (token = strtok_r(str, KEY_SEP, &saveptr); token != NULL; token = strtok_r(NULL, KEY_SEP, &saveptr)) { found = false; + for (i=0; iheader.type = OFPIT_METER; + if(parse32(s, NULL, 0, OFPM_MAX ,&i->meter_id)){ + ofp_fatal(0, "Error parsing meter instruction: %s.", s); + } + (*inst) = (struct ofl_instruction_header *)i; + return; + } case (OFPIT_CLEAR_ACTIONS): { struct ofl_instruction_header *i = xmalloc(sizeof(struct ofl_instruction_header)); i->type = OFPIT_CLEAR_ACTIONS; @@ -1627,9 +2176,22 @@ parse_inst(char *str, struct ofl_instruction_header **inst) { ofp_fatal(0, "Error parsing instruction: %s.", str); } +static void +parse_state_stat_args(char *str, struct ofl_exp_msg_multipart_request_state *req) { + char *token, *saveptr = NULL; + for (token = strtok_r(str, KEY_SEP, &saveptr); token != NULL; token = strtok_r(NULL, KEY_SEP, &saveptr)) { + if (strncmp(token, FLOW_MOD_TABLE_ID KEY_VAL, strlen(FLOW_MOD_TABLE_ID KEY_VAL)) == 0) { + if (parse8(token + strlen(FLOW_MOD_TABLE_ID KEY_VAL), table_names, NUM_ELEMS(table_names), 254, &req->table_id)) { + ofp_fatal(0, "Error parsing state_stat table: %s.", token); + } + continue; + } + ofp_fatal(0, "Error parsing state_stat arg: %s.", token); + } +} static void -parse_flow_stat_args(char *str, struct ofl_msg_stats_request_flow *req) { +parse_flow_stat_args(char *str, struct ofl_msg_multipart_request_flow *req) { char *token, *saveptr = NULL; for (token = strtok_r(str, KEY_SEP, &saveptr); token != NULL; token = strtok_r(NULL, KEY_SEP, &saveptr)) { @@ -1640,7 +2202,7 @@ parse_flow_stat_args(char *str, struct ofl_msg_stats_request_flow *req) { continue; } if (strncmp(token, FLOW_MOD_COOKIE_MASK KEY_VAL, strlen(FLOW_MOD_COOKIE_MASK KEY_VAL)) == 0) { - if (sscanf(token, FLOW_MOD_COOKIE KEY_VAL "0x%"SCNx64"", &(req->cookie)) != 1) { + if (sscanf(token, FLOW_MOD_COOKIE_MASK KEY_VAL "0x%"SCNx64"", &(req->cookie_mask)) != 1) { ofp_fatal(0, "Error parsing flow_stat cookie mask: %s.", token); } continue; @@ -1689,7 +2251,7 @@ parse_flow_mod_args(char *str, struct ofl_msg_flow_mod *req) { continue; } if (strncmp(token, FLOW_MOD_COOKIE_MASK KEY_VAL, strlen(FLOW_MOD_COOKIE_MASK KEY_VAL)) == 0) { - if (sscanf(token, FLOW_MOD_COOKIE KEY_VAL "0x%"SCNx64"", &(req->cookie)) != 1) { + if (sscanf(token, FLOW_MOD_COOKIE_MASK KEY_VAL "0x%"SCNx64"", &(req->cookie_mask)) != 1) { ofp_fatal(0, "Error parsing flow_mod cookie mask: %s.", token); } continue; @@ -1804,6 +2366,108 @@ parse_bucket(char *str, struct ofl_bucket *b) { } } +static void +parse_meter_mod_args(char *str, struct ofl_msg_meter_mod *req){ + char *token, *saveptr = NULL; + + for (token = strtok_r(str, KEY_SEP, &saveptr); token != NULL; token = strtok_r(NULL, KEY_SEP, &saveptr)) { + if (strncmp(token, METER_MOD_COMMAND KEY_VAL, strlen(METER_MOD_COMMAND KEY_VAL)) == 0) { + uint16_t command; + if (parse16(token + strlen(METER_MOD_COMMAND KEY_VAL), meter_mod_cmd_names, NUM_ELEMS(meter_mod_cmd_names),0, &command)) { + ofp_fatal(0, "Error parsing meter_mod command: %s.", token); + } + req->command = command; + continue; + } + if (strncmp(token, METER_MOD_FLAGS KEY_VAL, strlen(METER_MOD_FLAGS KEY_VAL)) == 0) { + if (parse16(token + strlen(METER_MOD_FLAGS KEY_VAL), NULL, 0, 0xffff, &req->flags)) { + ofp_fatal(0, "Error parsing meter_mod flags: %s.", token); + } + continue; + } + if (strncmp(token, METER_MOD_METER KEY_VAL, strlen(METER_MOD_METER KEY_VAL)) == 0) { + uint32_t meter_id; + if (parse32(token + strlen(METER_MOD_METER KEY_VAL), NULL, 0, 1024, &meter_id)) { + ofp_fatal(0, "Error parsing meter_mod id: %s.", token); + } + req->meter_id = meter_id; + continue; + } + ofp_fatal(0, "Error parsing group_mod arg: %s.", token); + } + +} + +static void +parse_band_args(char *str, struct ofl_msg_meter_mod *m, struct ofl_meter_band_header *b){ + char *token, *saveptr = NULL; + for (token = strtok_r(str, KEY_SEP, &saveptr); token != NULL; token = strtok_r(NULL, KEY_SEP, &saveptr)) { + if (strncmp(token, BAND_RATE KEY_VAL, strlen(BAND_RATE KEY_VAL)) == 0) { + if (parse32(token + strlen(BAND_RATE KEY_VAL), NULL, 0, UINT32_MAX, &b->rate)) { + ofp_fatal(0, "Error parsing band rate: %s.", token); + } + continue; + } + if (strncmp(token, BAND_BURST_SIZE KEY_VAL, strlen(BAND_BURST_SIZE KEY_VAL)) == 0) { + if(m->flags & OFPMF_BURST){ + if (parse32(token + strlen(BAND_BURST_SIZE KEY_VAL), NULL, 0, UINT32_MAX, &b->burst_size)) { + ofp_fatal(0, "Error parsing band burst_size: %s.", token); + } + continue; + } + else ofp_fatal(0, "Error parsing burst size. Meter flags should contain %x.", OFPMF_BURST); + } + if (strncmp(token, BAND_PREC_LEVEL KEY_VAL, strlen(BAND_PREC_LEVEL KEY_VAL)) == 0) { + struct ofl_meter_band_dscp_remark *d = (struct ofl_meter_band_dscp_remark*) b; + if (parse8(token + strlen(BAND_PREC_LEVEL KEY_VAL), NULL, 0, UINT8_MAX, &d->prec_level)) { + ofp_fatal(0, "Error parsing band rate: %s.", token); + } + continue; + } + ofp_fatal(0, "Error parsing band arg: %s.", token); + } +} + +static void +parse_band(char *str, struct ofl_msg_meter_mod *m, struct ofl_meter_band_header **b){ + char *s; + size_t i; + for (i=0; itype = OFPMBT_DROP; + d->rate = 0; + d->burst_size = 0; + parse_band_args(s, m, (struct ofl_meter_band_header*)d); + *b = (struct ofl_meter_band_header*) d; + break; + } + case(OFPMBT_DSCP_REMARK):{ + struct ofl_meter_band_dscp_remark *d = (struct ofl_meter_band_dscp_remark*) xmalloc(sizeof(struct ofl_meter_band_dscp_remark)); + d->type = OFPMBT_DSCP_REMARK; + d->rate = 0; + d->burst_size = 0; + d->prec_level = 0; + parse_band_args(s, m, (struct ofl_meter_band_header*)d); + *b = (struct ofl_meter_band_header*) d; + break; + } + } + } + } +} + + static void parse_config(char *str, struct ofl_config *c) { char *token, *saveptr = NULL; @@ -1837,7 +2501,8 @@ parse_port_mod(char *str, struct ofl_msg_port_mod *msg) { continue; } if (strncmp(token, PORT_MOD_HW_ADDR KEY_VAL, strlen(PORT_MOD_HW_ADDR KEY_VAL)) == 0) { - if (parse_dl_addr(token + strlen(PORT_MOD_HW_ADDR KEY_VAL), msg->hw_addr)) { + uint8_t *mask = NULL; + if (parse_dl_addr(token + strlen(PORT_MOD_HW_ADDR KEY_VAL), msg->hw_addr, &mask)) { ofp_fatal(0, "Error parsing port_mod hw_addr: %s.", token); } continue; @@ -1902,29 +2567,84 @@ parse_group(char *str, uint32_t *group) { return parse32(str, group_names, NUM_ELEMS(group_names), OFPG_MAX, group); } +static int +parse_meter(char *str, uint32_t *meter) { + return parse32(str, NULL, 0, OFPM_MAX, meter); +} + static int parse_table(char *str, uint8_t *table) { return parse8(str, table_names, NUM_ELEMS(table_names), 0xfe, table); } static int -parse_dl_addr(char *str, uint8_t *addr) { - return (sscanf(str, "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8, - addr, addr+1, addr+2, addr+3, addr+4, addr+5) != 6); +parse_dl_addr(char *str, uint8_t *addr, uint8_t **mask) { + char *saveptr = NULL; + if (sscanf(str, "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8, + addr, addr+1, addr+2, addr+3, addr+4, addr+5) != 6){ + return -1; + } + strtok_r(str, MASK_SEP, &saveptr); + + if(strcmp(saveptr,"") == 0){ + *mask = NULL; + return 0; + } + else { + *mask = (uint8_t*) malloc (sizeof(OFP_ETH_ALEN)); + if (sscanf(saveptr, "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8, + *mask, *mask+1, *mask+2, *mask+3, *mask+4, *mask+5) != 6){ + return -1; + } + } + return 0; } static int -parse_nw_addr(char *str, uint32_t *addr) { - // TODO Zoltan: netmask ? +parse_nw_addr(char *str, uint32_t *addr, uint32_t **mask) { // TODO Zoltan: DNS lookup ? - uint8_t a[4]; + uint8_t a[4],b[4]; + uint32_t netmask; + char *saveptr = NULL; if (sscanf(str, "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8, &a[0], &a[1], &a[2], &a[3]) == 4) { *addr = (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]; + } + else { + return -1; + } + strtok_r(str, MASK_SEP, &saveptr); + if(strcmp(saveptr,"") == 0){ + *mask = NULL; return 0; } - return -1; + *mask = (uint32_t*) malloc(sizeof(uint32_t)); + netmask = 0xffffffff; + if(strlen(saveptr) <= 2){ + /* Subnet mask*/ + uint8_t subnet_mask; + sscanf(saveptr, "%"SCNu8"", + &subnet_mask); + if (subnet_mask > 32) + return -1; + if (subnet_mask == 0) + netmask = 0x00000000; + else netmask = netmask << (32 - subnet_mask); + **mask = htonl(netmask); + } + else { + /*Arbitrary mask*/ + if (sscanf(saveptr, "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8, + &b[0], &b[1], &b[2], &b[3]) == 4) { + **mask = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0]; + } + else { + return -1; + } + } + + return 0; } static int @@ -1932,9 +2652,23 @@ parse_vlan_vid(char *str, uint16_t *vid) { return parse16(str, vlan_vid_names, NUM_ELEMS(vlan_vid_names), 0xfff, vid); } - - - +static int +parse_ext_hdr(char *str, uint16_t *ext_hdr){ + char *token, *saveptr = NULL; + size_t i; + memset(ext_hdr, 0x0, sizeof(uint16_t)); + for (token = strtok_r(str, ADD, &saveptr); token != NULL; token = strtok_r(NULL, ADD, &saveptr)) { + for (i=0; i < 9; i++) { + if (strcmp(token, ext_header_names[i].name) == 0) { + *ext_hdr = *ext_hdr ^ ext_header_names[i].code; + break; + } + } + if(i == 9) + return -1; + } + return 0; +} static int parse8(char *str, struct names8 *names, size_t names_num, uint8_t max, uint8_t *val) { @@ -1947,7 +2681,7 @@ parse8(char *str, struct names8 *names, size_t names_num, uint8_t max, uint8_t * } } - if ((max > 0) && (sscanf(str, "%"SCNu8"", val)) == 1 && (*val <= max)) { + if ((max > 0) && (sscanf(str, "%"SCNu8"", val)) == 1 && ((*val) <= max)) { return 0; } return -1; @@ -1956,7 +2690,7 @@ parse8(char *str, struct names8 *names, size_t names_num, uint8_t max, uint8_t * static int parse16(char *str, struct names16 *names, size_t names_num, uint16_t max, uint16_t *val) { size_t i; - + for (i=0; i 0) && (sscanf(str, "%"SCNu16"", val)) == 1 && (*val <= max)) { return 0; } - } + } return -1; } +static int +parse16m(char *str, struct names16 *names, size_t names_num, uint16_t max, uint16_t *val, uint16_t *mask){ + + size_t i; + char *token, *saveptr = NULL; + + for (i=0; i 0) && (*val <= max)) { + if (!sscanf(str, "%"SCNu16"", val)) + return -1; + } + + token = strtok_r(str, MASK_SEP, &saveptr); + if(token == NULL) + mask = NULL; + else { + mask = (uint16_t*) malloc(sizeof(uint16_t)); + sscanf(token, "%"SCNu16"", mask); + } + return 0; + +} + static int parse32(char *str, struct names32 *names, size_t names_num, uint32_t max, uint32_t *val) { size_t i; @@ -1995,3 +2757,233 @@ parse32(char *str, struct names32 *names, size_t names_num, uint32_t max, uint32 return -1; } +static int +parse32m(char *str, struct names32 *names, size_t names_num, uint32_t max, uint32_t *val, uint32_t **mask){ + + size_t i; + char *saveptr = NULL; + + for (i=0; i 0) && (*val <= max)) { + if (!sscanf(str, "%"SCNu32"", val)) + return -1; + } + + strtok_r(str, MASK_SEP, &saveptr); + + if(saveptr == NULL) + *mask = NULL; + else { + *mask = (uint32_t*) malloc(sizeof(uint32_t)); + sscanf(saveptr, "%"SCNu32"", *mask); + } + return 0; +} + +struct oxm_str_mapping { + char * name; + uint32_t oxm_id; +}; +struct oxm_str_mapping oxm_str_map[] = + { { .name=MATCH_IN_PORT, .oxm_id=OXM_OF_IN_PORT }, + { .name=MATCH_DL_SRC, .oxm_id=OXM_OF_ETH_SRC }, + { .name=MATCH_DL_DST, .oxm_id=OXM_OF_ETH_DST }, + { .name=MATCH_ARP_SHA, .oxm_id=OXM_OF_ARP_SHA }, + { .name=MATCH_ARP_THA, .oxm_id=OXM_OF_ARP_THA }, + { .name=MATCH_ARP_SPA, .oxm_id=OXM_OF_ARP_SPA }, + { .name=MATCH_ARP_TPA, .oxm_id=OXM_OF_ARP_TPA }, + { .name=MATCH_ARP_OP, .oxm_id=OXM_OF_ARP_OP }, + { .name=MATCH_DL_VLAN, .oxm_id=OXM_OF_VLAN_VID }, + { .name=MATCH_DL_VLAN_PCP, .oxm_id=OXM_OF_VLAN_PCP }, + { .name=MATCH_DL_TYPE, .oxm_id=OXM_OF_ETH_TYPE }, + { .name=MATCH_IP_ECN, .oxm_id=OXM_OF_IP_ECN }, + { .name=MATCH_IP_DSCP, .oxm_id=OXM_OF_IP_DSCP }, + { .name=MATCH_NW_PROTO, .oxm_id=OXM_OF_IP_PROTO }, + { .name=MATCH_NW_SRC, .oxm_id=OXM_OF_IPV4_SRC }, + { .name=MATCH_NW_DST, .oxm_id=OXM_OF_IPV4_DST }, + { .name=MATCH_ICMPV4_CODE, .oxm_id=OXM_OF_ICMPV4_CODE }, + { .name=MATCH_ICMPV4_TYPE, .oxm_id=OXM_OF_ICMPV4_TYPE }, + { .name=MATCH_TP_SRC, .oxm_id=OXM_OF_TCP_SRC }, + { .name=MATCH_TP_DST, .oxm_id=OXM_OF_TCP_DST }, + { .name=MATCH_UDP_SRC, .oxm_id=OXM_OF_UDP_SRC }, + { .name=MATCH_UDP_DST, .oxm_id=OXM_OF_UDP_DST }, + { .name=MATCH_SCTP_SRC, .oxm_id=OXM_OF_SCTP_SRC }, + { .name=MATCH_SCTP_DST, .oxm_id=OXM_OF_SCTP_DST }, + { .name=MATCH_MPLS_LABEL, .oxm_id=OXM_OF_MPLS_LABEL }, + { .name=MATCH_MPLS_TC, .oxm_id=OXM_OF_MPLS_TC }, + { .name=MATCH_MPLS_BOS, .oxm_id=OXM_OF_MPLS_BOS }, + { .name=MATCH_NW_SRC_IPV6, .oxm_id=OXM_OF_IPV6_SRC }, + { .name=MATCH_NW_DST_IPV6, .oxm_id=OXM_OF_IPV6_DST }, + { .name=MATCH_IPV6_FLABEL, .oxm_id=OXM_OF_IPV6_FLABEL }, + { .name=MATCH_ICMPV6_CODE, .oxm_id=OXM_OF_ICMPV6_CODE }, + { .name=MATCH_ICMPV6_TYPE, .oxm_id=OXM_OF_ICMPV6_TYPE }, + { .name=MATCH_IPV6_ND_TARGET, .oxm_id=OXM_OF_IPV6_ND_TARGET }, + { .name=MATCH_IPV6_ND_SLL, .oxm_id=OXM_OF_IPV6_ND_SLL }, + { .name=MATCH_IPV6_ND_TLL, .oxm_id=OXM_OF_IPV6_ND_TLL }, + { .name=MATCH_METADATA, .oxm_id=OXM_OF_METADATA }, + { .name=MATCH_PBB_ISID, .oxm_id=OXM_OF_PBB_ISID }, + { .name=MATCH_TUNNEL_ID, .oxm_id=OXM_OF_TUNNEL_ID }, + { .name=MATCH_EXT_HDR, .oxm_id=OXM_OF_IPV6_EXTHDR }, + }; + +static void +parse_feature_prop_match(char *str, struct ofl_table_feature_prop_oxm **prop_addr) { + char *token, *saveptr = NULL; + const int oxm_max = sizeof(oxm_str_map) / sizeof(oxm_str_map[0]); + uint32_t *oxm_array = (uint32_t *) xmalloc(sizeof(uint32_t) * 80); + struct ofl_table_feature_prop_oxm *property; + int oxm_num = 0; + int id; + + for (token = strtok_r(str, KEY_SEP, &saveptr); token != NULL; token = strtok_r(NULL, KEY_SEP, &saveptr)) { + if (strncmp(token, "apply", strlen("apply")) == 0 || strncmp(token, "write", strlen("write")) == 0 ) { + break; + } + if (oxm_num >= oxm_max) { + break; + } + for (id = 0; id < oxm_max; id++) { + + if (strncmp(token, oxm_str_map[id].name, strlen(oxm_str_map[id].name)) == 0) { + oxm_array[oxm_num++] = oxm_str_map[id].oxm_id; + break; + } + } + } + + property = (struct ofl_table_feature_prop_oxm *) xmalloc(sizeof(struct ofl_table_feature_prop_oxm)); + property->header.type = OFPTFPT_MATCH; + property->header.length = (sizeof(struct ofp_table_feature_prop_oxm) + oxm_num * sizeof(uint32_t)); + property->oxm_num = oxm_num; + property->oxm_ids = oxm_array; + (*prop_addr) = property; +} + +static void +set_table_features_match(struct vconn *vconn, int argc, char *argv[]) { + struct ofl_msg_multipart_request_table_features req_init = + {{{.type = OFPT_MULTIPART_REQUEST}, + .type = OFPMP_TABLE_FEATURES, .flags = 0x0000}, + .tables_num = 0, + .table_features = NULL, + }; + struct ofl_msg_header *reply; + struct ofl_msg_multipart_request_table_features *table_feat; + int t; + int last_table; + int batch_table; + uint32_t repl_xid; + + /* Extract current table features */ + dpctl_transact(vconn, (struct ofl_msg_header *)&req_init, &reply, &repl_xid); + table_feat = (struct ofl_msg_multipart_request_table_features *) reply; + + if (argc > 0) { + struct ofl_table_feature_prop_oxm *new_match; + struct ofl_table_feature_prop_header **properties; + int properties_num; + int i; + + /* New match features */ + parse_feature_prop_match(argv[0], &new_match); + { + char *str; + str = ofl_structs_table_properties_to_string((struct ofl_table_feature_prop_header *) new_match); + printf("New match property:%s\n\n", str); + free(str); + } + + /* Set them in all the table features */ + for(t = 0; t < table_feat->tables_num; t++) { + properties = table_feat->table_features[t]->properties; + properties_num = table_feat->table_features[t]->properties_num; + for (i = 0; i < properties_num; i++) { + if(properties[i]->type == OFPTFPT_MATCH) { + struct ofl_table_feature_prop_oxm *clone_match; + clone_match = (struct ofl_table_feature_prop_oxm *) xmalloc(sizeof(struct ofl_table_feature_prop_oxm)); + memcpy((char *) clone_match, (char *) new_match, sizeof(struct ofl_table_feature_prop_oxm)); + clone_match->oxm_ids = (uint32_t *) xmalloc(clone_match->oxm_num * sizeof(uint32_t)); + memcpy((char *) clone_match->oxm_ids, new_match->oxm_ids, clone_match->oxm_num * sizeof(uint32_t)); + + ofl_structs_free_table_properties(properties[i], &dpctl_exp); + properties[i] = (struct ofl_table_feature_prop_header *) clone_match; + } + } + } + + ofl_structs_free_table_properties((struct ofl_table_feature_prop_header *) new_match, &dpctl_exp); + + } + + { + int features_len; + printf("\nJII table-num:%zu\n", table_feat->tables_num); + features_len = ofl_structs_table_features_ofp_total_len(table_feat->table_features, table_feat->tables_num, NULL); + printf("\nJII features_len:%d\n", features_len); + } + + /* Turn the reply into a request */ + table_feat->header.header.type = OFPT_MULTIPART_REQUEST; + + /* Renumber tables to form multipart request */ + last_table = table_feat->table_features[table_feat->tables_num - 1]->table_id; + t = 0; + batch_table = table_feat->tables_num; + while(t <= last_table) { + int i; + int prev_t = t; + for(i = 0; i < batch_table; i++) { + table_feat->table_features[i]->table_id = t; + table_feat->table_features[i]->name[0] = '\0'; + t++; + if(t > last_table) + break; + } + + /* Set the request parameters. */ + table_feat->tables_num = t - prev_t; + +#if 0 + { + char *str; + str = ofl_msg_to_string(reply, &dpctl_exp); + printf("\nNew table request (t=%d/%d, num=%d):\n%s\n\n", t, last_table, table_feat->tables_num, str); + free(str); + } +#endif + + /* Intermediate and last segment are not treated the same. Jean II */ + if(t <= last_table) { + struct ofpbuf *ofpbufreq; + uint8_t *bufreq; + size_t bufreq_size; + int error; + + table_feat->header.flags = OFPMPF_REQ_MORE; + + error = ofl_msg_pack((struct ofl_msg_header *)table_feat, XID, &bufreq, &bufreq_size, NULL); + if (error) { + ofp_fatal(0, "Error packing request."); + } + printf("\nJII-req-pack:%zu\n", bufreq_size); + + ofpbufreq = ofpbuf_new(0); + ofpbuf_use(ofpbufreq, bufreq, bufreq_size); + ofpbuf_put_uninit(ofpbufreq, bufreq_size); + error = vconn_send_block(vconn, ofpbufreq); + if (error) { + ofp_fatal(0, "Error during transaction."); + } + /* No reply. */ + } else { + table_feat->header.flags = 0; + + dpctl_transact_and_print(vconn, (struct ofl_msg_header *)table_feat, NULL); + } + } +}