size_t ofl_actions_pack(struct ofl_action_header *src, struct ofp_action_header *dst, uint8_t* data, struct ofl_exp *exp) { dst->type = htons(src->type); memset(dst->pad, 0x00, 4); switch (src->type) { case OFPAT_OUTPUT: { struct ofl_action_output *sa = (struct ofl_action_output *)src; struct ofp_action_output *da = (struct ofp_action_output *)dst; da->len = htons(sizeof(struct ofp_action_output)); da->port = htonl(sa->port); da->max_len = htons(sa->max_len); memset(da->pad, 0x00, 6); return sizeof(struct ofp_action_output); } case OFPAT_COPY_TTL_OUT: case OFPAT_COPY_TTL_IN: { dst->len = htons(sizeof(struct ofp_action_header)); return sizeof(struct ofp_action_header); } case OFPAT_SET_MPLS_TTL: { struct ofl_action_mpls_ttl *sa = (struct ofl_action_mpls_ttl *)src; struct ofp_action_mpls_ttl *da = (struct ofp_action_mpls_ttl *)dst; da->len = htons(sizeof(struct ofp_action_mpls_ttl)); da->mpls_ttl = sa->mpls_ttl; memset(da->pad, 0x00, 3); return sizeof(struct ofp_action_mpls_ttl); } case OFPAT_DEC_MPLS_TTL: { dst->len = htons(sizeof(struct ofp_action_header)); return sizeof(struct ofp_action_header); } case OFPAT_PUSH_VLAN: case OFPAT_PUSH_MPLS: case OFPAT_PUSH_PBB:{ struct ofl_action_push *sa = (struct ofl_action_push *)src; struct ofp_action_push *da = (struct ofp_action_push *)dst; da->len = htons(sizeof(struct ofp_action_push)); da->ethertype = htons(sa->ethertype); memset(da->pad, 0x00, 2); return sizeof(struct ofp_action_push); } case OFPAT_POP_VLAN: case OFPAT_POP_PBB: { struct ofp_action_header *da = (struct ofp_action_header *)dst; da->len = htons(sizeof(struct ofp_action_header)); return sizeof (struct ofp_action_header); } case OFPAT_POP_MPLS: { struct ofl_action_pop_mpls *sa = (struct ofl_action_pop_mpls *)src; struct ofp_action_pop_mpls *da = (struct ofp_action_pop_mpls *)dst; da->len = htons(sizeof(struct ofp_action_pop_mpls)); da->ethertype = htons(sa->ethertype); memset(da->pad, 0x00, 2); return sizeof(struct ofp_action_pop_mpls); } case OFPAT_SET_QUEUE: { struct ofl_action_set_queue *sa = (struct ofl_action_set_queue *)src; struct ofp_action_set_queue *da = (struct ofp_action_set_queue *)dst; da->len = htons(sizeof(struct ofp_action_set_queue)); da->queue_id = htonl(sa->queue_id); return sizeof(struct ofp_action_set_queue); } case OFPAT_GROUP: { struct ofl_action_group *sa = (struct ofl_action_group *)src; struct ofp_action_group *da = (struct ofp_action_group *)dst; da->len = htons(sizeof(struct ofp_action_group)); da->group_id = htonl(sa->group_id); return sizeof(struct ofp_action_group); } case OFPAT_SET_NW_TTL: { struct ofl_action_set_nw_ttl *sa = (struct ofl_action_set_nw_ttl *)src; struct ofp_action_nw_ttl *da = (struct ofp_action_nw_ttl *)dst; da->len = htons(sizeof(struct ofp_action_nw_ttl)); da->nw_ttl = sa->nw_ttl; memset(da->pad, 0x00, 3); return sizeof(struct ofp_action_nw_ttl); } case OFPAT_DEC_NW_TTL: { dst->len = htons(sizeof(struct ofp_action_header)); return sizeof(struct ofp_action_header); } case OFPAT_SET_FIELD: { struct ofl_action_set_field *sa = (struct ofl_action_set_field *) src; struct ofp_action_set_field *da = (struct ofp_action_set_field *) dst; uint32_t header; uint8_t padding_size; da->len = htons(sizeof(struct ofp_action_set_field) + ROUND_UP(OXM_LENGTH(sa->field->header),8)); /*Put OXM header in the field*/ header = htonl(sa->field->header); memcpy(&da->field, &header, 4); /* For OFDPA2.0 */ if(0xFFFF == OXM_VENDOR(sa->field->header)) /* exp */ { struct OFDPA_ofl_match_exp_tlv* ofdpa_exp_tlv_p = (struct OFDPA_ofl_match_exp_tlv*)sa->field; uint32_t experimenter_v = htonl(ofdpa_exp_tlv_p->experimenter); uint16_t exp_type_v = htons(ofdpa_exp_tlv_p->exp_type); uint8_t length = OXM_LENGTH(sa->field->header); uint8_t offset_len = sizeof(struct ofp_action_set_field); length -= sizeof(experimenter_v); length -= sizeof(exp_type_v); memcpy(data + offset_len, &experimenter_v, sizeof(experimenter_v)); offset_len += sizeof(experimenter_v); memcpy(data + offset_len, &exp_type_v, sizeof(exp_type_v)); offset_len += sizeof(exp_type_v); switch(length) { case (sizeof(uint8_t)): memcpy(data + offset_len, ofdpa_exp_tlv_p->exp_data_p, sizeof(uint8_t)); break; case (sizeof(uint16_t)): { uint16_t value = htons(*((uint16_t*) ofdpa_exp_tlv_p->exp_data_p)); memcpy(data + offset_len, &value, sizeof(value)); break; } case (sizeof(uint32_t)): { uint32_t value = htonl(*((uint32_t*) ofdpa_exp_tlv_p->exp_data_p)); memcpy(data + offset_len, &value, sizeof(value)); break; } case (sizeof(uint64_t)): { uint64_t value = hton64(*((uint64_t*) ofdpa_exp_tlv_p->exp_data_p)); memcpy(data + offset_len, &value, sizeof(value)); break; } } /*padding*/ padding_size = ROUND_UP(OXM_LENGTH(sa->field->header),8) - OXM_LENGTH(sa->field->header); memset(data + (sizeof(struct ofp_action_set_field) + OXM_LENGTH(sa->field->header)), 0, padding_size); return ntohs((da->len)); } /* End of OFDPA2.0 */ switch (OXM_LENGTH(sa->field->header)){ case 1: case 6: case 12: case 16: memcpy(data + sizeof(struct ofp_action_set_field), sa->field->value,OXM_LENGTH(sa->field->header)); break; case 2:{ uint16_t value = htons(*((uint16_t*) sa->field->value)); memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header)); break; } case 4:{ uint16_t value1,value2; uint32_t value; uint8_t field = OXM_FIELD(sa->field->header); if( field != 11 && field != 12 && field != 22 && field != 23) value = htonl(*((uint32_t*) sa->field->value)); else value = *((uint32_t*) sa->field->value); if(field == 6){ value1 = value >> 16; value2 = value & 0xffff; value = (((uint32_t)value2) << 16)+(uint32_t)value1; } memcpy(data + (sizeof(struct ofp_action_set_field)), &value, OXM_LENGTH(sa->field->header)); break; } case 8:{ uint64_t value; uint8_t field = OXM_FIELD(sa->field->header); if(field == 38) /* This is for tunnel_id */ value = hton64(*((uint64_t *) sa->field->value)); else value = htons(*((uint64_t *) sa->field->value)); memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header)); break; } } /*padding*/ padding_size = ROUND_UP(OXM_LENGTH(sa->field->header),8) - OXM_LENGTH(sa->field->header); memset(data + (sizeof(struct ofp_action_set_field) + OXM_LENGTH(sa->field->header)), 0, padding_size); return ntohs((da->len)); } case OFPAT_EXPERIMENTER: { if (exp == NULL || exp->act == NULL || exp->act->pack == NULL) { OFL_LOG_WARN(LOG_MODULE, "Trying to pack experimenter, but no callback was given."); return 0; } return exp->act->pack(src, dst); } default: return 0; };
/* Two matches strictly match if their wildcard fields are the same, and all the * non-wildcarded fields match on the same exact values. * NOTE: Handling of bitmasked fields is not specified. In this implementation * masked fields are checked for equality, and only unmasked bits are compared * in the field. */ bool match_std_strict(struct ofl_match *a, struct ofl_match *b, struct ofl_exp *exp) { struct ofl_match_tlv *flow_mod_match; struct ofl_match_tlv *flow_entry_match; int field_len; uint8_t *flow_mod_val, *flow_mod_mask=0; uint8_t *flow_entry_val, *flow_entry_mask=0; uint8_t oxm_field; bool has_mask; /* Both matches all wildcarded */ if(!a->header.length && !b->header.length ) return true; /* If the matches differ in length, there is no reason to compare */ if (a->header.length != b->header.length) return false; /* Loop through the flow_mod match fields */ HMAP_FOR_EACH(flow_mod_match, struct ofl_match_tlv, hmap_node, &a->match_fields) { /* Check presence of match field in flow entry */ flow_entry_match = oxm_match_lookup(flow_mod_match->header, b); if (!flow_entry_match) { return false; } /* At this point match length and has_mask are equal */ oxm_field = OXM_FIELD(flow_mod_match->header); has_mask = OXM_HASMASK(flow_mod_match->header); flow_mod_val = flow_mod_match->value; flow_entry_val = flow_entry_match->value; switch (OXM_VENDOR(flow_mod_match->header)) { case (OFPXMC_OPENFLOW_BASIC): field_len = OXM_LENGTH(flow_mod_match->header); if (has_mask) { field_len /= 2; flow_mod_mask = flow_mod_val + field_len; flow_entry_mask = flow_entry_val + field_len; } break; case (OFPXMC_EXPERIMENTER): if (exp == NULL || exp->field == NULL || exp->field->match_std == NULL) { VLOG_WARN(LOG_MODULE,"Received match is experimental, but no callback was given."); ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE); } exp->field->match_std(flow_mod_match, flow_entry_match, &field_len, &flow_mod_val, &flow_entry_val, &flow_mod_mask, &flow_entry_mask); break; default: break; } switch (field_len) { case 1: if (has_mask) { if (!strict_mask8(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){ return false; } } else { if (!match_8(flow_mod_val, flow_entry_val)){ return false; } } break; case 2: if (has_mask) { if (!strict_mask16(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){ return false; } } else { if (!match_16(flow_mod_val, flow_entry_val)){ return false; } } break; case 3: if (has_mask) { if (!strict_mask24(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)) return false; } else { if (!match_24(flow_mod_val, flow_entry_val)){ return false; } } break; case 4: if (has_mask) { /* Quick and dirty fix for IP addresses matching TODO: Matching needs a huge refactoring */ if (oxm_field == OFPXMT_OFB_IPV4_SRC || oxm_field == OFPXMT_OFB_IPV4_DST || oxm_field == OFPXMT_OFB_ARP_SPA || oxm_field == OFPXMT_OFB_ARP_TPA) { if (!strict_mask_ip(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){ return false; } } if (!strict_mask32(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){ return false; } } else { if (!match_32(flow_mod_val, flow_entry_val)){ return false; } } break; case 6: if (has_mask) { if (!strict_mask48(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){ return false; } } else { if (!match_48(flow_mod_val, flow_entry_val)){ return false; } } break; case 8: if (has_mask) { if (!strict_mask64(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){ return false; } } else { if (!match_64(flow_mod_val, flow_entry_val)){ return false; } } break; case 16: if (has_mask) { if (!strict_mask128(flow_mod_val, flow_entry_val, flow_mod_mask, flow_entry_mask)){ return false; } } else { if (!match_128(flow_mod_val, flow_entry_val)){ return false; } } break; default: /* Should never happen */ break; } /* switch (field_len) */ } /* HMAP_FOR_EACH */ /* If we get here, all match fields in flow_mod were equal to the ones in flow entry */ /* There can't be more fields in the flow entry as the lengths are the same */ return true; }
ofl_err ofl_actions_unpack(struct ofp_action_header *src, size_t *len, struct ofl_action_header **dst, struct ofl_exp *exp) { if (*len < sizeof(struct ofp_action_header)) { OFL_LOG_WARN(LOG_MODULE, "Received action is too short (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } if (*len < ntohs(src->len)) { OFL_LOG_WARN(LOG_MODULE, "Received action has invalid length (set to %u, but only %zu received).", ntohs(src->len), *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } if ((ntohs(src->len) % 8) != 0) { OFL_LOG_WARN(LOG_MODULE, "Received action length is not a multiple of 64 bits (%u).", ntohs(src->len)); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } switch (ntohs(src->type)) { case OFPAT_OUTPUT: { struct ofp_action_output *sa; struct ofl_action_output *da; if (*len < sizeof(struct ofp_action_output)) { OFL_LOG_WARN(LOG_MODULE, "Received OUTPUT action has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } sa = (struct ofp_action_output *)src; if (ntohl(sa->port) == 0 || (ntohl(sa->port) > OFPP_MAX && ntohl(sa->port) < OFPP_IN_PORT) || ntohl(sa->port) == OFPP_ANY) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *ps = ofl_port_to_string(ntohl(sa->port)); OFL_LOG_WARN(LOG_MODULE, "Received OUTPUT action has invalid port (%s).", ps); free(ps); } return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_PORT); } da = (struct ofl_action_output *)malloc(sizeof(struct ofl_action_output)); da->port = ntohl(sa->port); da->max_len = ntohs(sa->max_len); *len -= sizeof(struct ofp_action_output); *dst = (struct ofl_action_header *)da; break; } case OFPAT_COPY_TTL_OUT: { //ofp_action_header length was already checked *len -= sizeof(struct ofp_action_header); *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header)); break; } case OFPAT_COPY_TTL_IN: { //ofp_action_header length was already checked *len -= sizeof(struct ofp_action_header); *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header)); break; } case OFPAT_SET_MPLS_TTL: { struct ofp_action_mpls_ttl *sa; struct ofl_action_mpls_ttl *da; if (*len < sizeof(struct ofp_action_mpls_ttl)) { OFL_LOG_WARN(LOG_MODULE, "Received SET_MPLS_TTL action has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } sa = (struct ofp_action_mpls_ttl *)src; da = (struct ofl_action_mpls_ttl *)malloc(sizeof(struct ofl_action_mpls_ttl)); da->mpls_ttl = sa->mpls_ttl; *len -= sizeof(struct ofp_action_mpls_ttl); *dst = (struct ofl_action_header *)da; break; } case OFPAT_DEC_MPLS_TTL: { //ofp_action_header length was already checked *len -= sizeof(struct ofp_action_mpls_ttl); *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header)); break; } case OFPAT_PUSH_VLAN: case OFPAT_PUSH_PBB: case OFPAT_PUSH_MPLS: { struct ofp_action_push *sa; struct ofl_action_push *da; if (*len < sizeof(struct ofp_action_push)) { OFL_LOG_WARN(LOG_MODULE, "Received PUSH_VLAN/MPLS/PBB action has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } sa = (struct ofp_action_push *)src; if (((ntohs(src->type) == OFPAT_PUSH_VLAN) && (ntohs(sa->ethertype) != ETH_TYPE_VLAN && ntohs(sa->ethertype) != ETH_TYPE_VLAN_PBB)) || ((ntohs(src->type) == OFPAT_PUSH_MPLS) && (ntohs(sa->ethertype) != ETH_TYPE_MPLS && ntohs(sa->ethertype) != ETH_TYPE_MPLS_MCAST)) || ((ntohs(src->type) == OFPAT_PUSH_PBB) && (ntohs(sa->ethertype) != ETH_TYPE_PBB))) { OFL_LOG_WARN(LOG_MODULE, "Received PUSH_VLAN/MPLS/PBB has invalid eth type. (%u)", ntohs(sa->ethertype)); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_ARGUMENT); } da = (struct ofl_action_push *)malloc(sizeof(struct ofl_action_push)); da->ethertype = ntohs(sa->ethertype); *len -= sizeof(struct ofp_action_push); *dst = (struct ofl_action_header *)da; break; } case OFPAT_POP_VLAN: case OFPAT_POP_PBB: { //ofp_action_header length was already checked *len -= sizeof(struct ofp_action_header); *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header)); break; } case OFPAT_POP_MPLS: { struct ofp_action_pop_mpls *sa; struct ofl_action_pop_mpls *da; if (*len < sizeof(struct ofp_action_pop_mpls)) { OFL_LOG_WARN(LOG_MODULE, "Received POP_MPLS action has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } sa = (struct ofp_action_pop_mpls *)src; da = (struct ofl_action_pop_mpls *)malloc(sizeof(struct ofl_action_pop_mpls)); da->ethertype = ntohs(sa->ethertype); *len -= sizeof(struct ofp_action_pop_mpls); *dst = (struct ofl_action_header *)da; break; } case OFPAT_SET_QUEUE: { struct ofp_action_set_queue *sa; struct ofl_action_set_queue *da; if (*len < sizeof(struct ofp_action_set_queue)) { OFL_LOG_WARN(LOG_MODULE, "Received SET_QUEUE action has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } sa = (struct ofp_action_set_queue *)src; da = (struct ofl_action_set_queue *)malloc(sizeof(struct ofl_action_set_queue)); da->queue_id = ntohl(sa->queue_id); *len -= sizeof(struct ofp_action_set_queue); *dst = (struct ofl_action_header *)da; break; } case OFPAT_GROUP: { struct ofp_action_group *sa; struct ofl_action_group *da; if (*len < sizeof(struct ofp_action_group)) { OFL_LOG_WARN(LOG_MODULE, "Received GROUP action has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } sa = (struct ofp_action_group *)src; if (ntohl(sa->group_id) > OFPG_MAX) { if (OFL_LOG_IS_WARN_ENABLED(LOG_MODULE)) { char *gs = ofl_group_to_string(ntohl(sa->group_id)); OFL_LOG_WARN(LOG_MODULE, "Received GROUP action has invalid group id (%s).", gs); free(gs); } return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_OUT_GROUP); } da = (struct ofl_action_group *)malloc(sizeof(struct ofl_action_group)); da->group_id = ntohl(sa->group_id); *len -= sizeof(struct ofp_action_group); *dst = (struct ofl_action_header *)da; break; } case OFPAT_SET_NW_TTL: { struct ofp_action_nw_ttl *sa; struct ofl_action_set_nw_ttl *da; if (*len < sizeof(struct ofp_action_nw_ttl)) { OFL_LOG_WARN(LOG_MODULE, "Received SET_NW_TTL action has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } sa = (struct ofp_action_nw_ttl *)src; da = (struct ofl_action_set_nw_ttl *)malloc(sizeof(struct ofl_action_set_nw_ttl)); da->nw_ttl = sa->nw_ttl; *len -= sizeof(struct ofp_action_nw_ttl); *dst = (struct ofl_action_header *)da; break; } case OFPAT_DEC_NW_TTL: { //ofp_action_header length was already checked *len -= sizeof(struct ofp_action_header); *dst = (struct ofl_action_header *)malloc(sizeof(struct ofl_action_header)); break; } case OFPAT_SET_FIELD: { struct ofp_action_set_field *sa; struct ofl_action_set_field *da; uint8_t *value; sa = (struct ofp_action_set_field*) src; da = (struct ofl_action_set_field *)malloc(sizeof(struct ofl_action_set_field)); da->field = (struct ofl_match_tlv*) malloc(sizeof(struct ofl_match_tlv)); memcpy(&da->field->header,sa->field,4); da->field->header = ntohl(da->field->header); value = (uint8_t *) src + sizeof (struct ofp_action_set_field); da->field->value = malloc(OXM_LENGTH(da->field->header)); /*TODO: need to check if other fields are valid */ if(da->field->header == OXM_OF_IN_PORT || da->field->header == OXM_OF_IN_PHY_PORT || da->field->header == OXM_OF_METADATA || da->field->header == OXM_OF_IPV6_EXTHDR){ return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_SET_TYPE); } switch(OXM_LENGTH(da->field->header)){ case 1: case 6: case 16: memcpy(da->field->value , value, OXM_LENGTH(da->field->header)); break; case 2:{ uint16_t v = ntohs(*((uint16_t*) value)); memcpy(da->field->value , &v, OXM_LENGTH(da->field->header)); break; } case 4:{ uint32_t v; uint8_t field = OXM_FIELD(da->field->header); if( field != 11 && field != 12 && field != 22 && field != 23) v = htonl(*((uint32_t*) value)); else v = *((uint32_t*) value); memcpy(da->field->value , &v, OXM_LENGTH(da->field->header)); break; } case 8:{ uint64_t v = hton64(*((uint64_t*) value)); memcpy(da->field->value , &v, OXM_LENGTH(da->field->header)); break; } } *len -= ROUND_UP(ntohs(src->len),8); *dst = (struct ofl_action_header *)da; break; } case OFPAT_EXPERIMENTER: { ofl_err error; if (*len < sizeof(struct ofp_action_experimenter_header)) { OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER action has invalid length (%zu).", *len); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_LEN); } if (exp == NULL || exp->act == NULL || exp->act->unpack == NULL) { OFL_LOG_WARN(LOG_MODULE, "Received EXPERIMENTER action, but no callback is given."); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_EXPERIMENTER); } error = exp->act->unpack(src, len, dst); if (error) { return error; } break; } default: { OFL_LOG_WARN(LOG_MODULE, "Received unknown action type (%u).", ntohs(src->type)); return ofl_error(OFPET_BAD_ACTION, OFPBAC_BAD_TYPE); } } (*dst)->type = (enum ofp_action_type)ntohs(src->type); return 0; }
void ofl_structs_oxm_tlv_print(FILE *stream, struct ofl_match_tlv *f) { uint8_t field = OXM_FIELD(f->header); switch (field) { case OFPXMT_OFB_IN_PORT: fprintf(stream, "in_port=\"%d\"", *((uint32_t*) f->value)); break; case OFPXMT_OFB_IN_PHY_PORT: fprintf(stream, "in_phy_port=\"%d\"", *((uint32_t*) f->value)); break; case OFPXMT_OFB_VLAN_VID: { uint16_t v = *((uint16_t *) f->value); if (v == OFPVID_NONE) fprintf(stream, "vlan_vid= none"); else if (v == OFPVID_PRESENT && OXM_HASMASK(f->header)) fprintf(stream, "vlan_vid= any"); else fprintf(stream, "vlan_vid=\"%d\"",v & VLAN_VID_MASK); break; } case OFPXMT_OFB_VLAN_PCP: fprintf(stream, "vlan_pcp=\"%d\"", *f->value & 0x7); break; case OFPXMT_OFB_ETH_TYPE: fprintf(stream, "eth_type=\"0x%x\"", *((uint16_t *) f->value)); break; case OFPXMT_OFB_TCP_SRC: fprintf(stream, "tcp_src=\"%d\"", *((uint16_t*) f->value)); break; case OFPXMT_OFB_TCP_DST: fprintf(stream, "tcp_dst=\"%d\"", *((uint16_t*) f->value)); break; case OFPXMT_OFB_UDP_SRC: fprintf(stream, "udp_src=\"%d\"", *((uint16_t*) f->value)); break; case OFPXMT_OFB_UDP_DST: fprintf(stream, "udp_dst=\"%d\"", *((uint16_t*) f->value)); break; case OFPXMT_OFB_SCTP_SRC: fprintf(stream, "sctp_src=\"%d\"", *((uint16_t*) f->value)); break; case OFPXMT_OFB_SCTP_DST: fprintf(stream, "sctp_dst=\"%d\"", *((uint16_t*) f->value)); break; case OFPXMT_OFB_ETH_SRC: fprintf(stream, "eth_src=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", eth_src_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6)); } break; case OFPXMT_OFB_ETH_DST: fprintf(stream, "eth_dst=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", eth_dst_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6)); } break; case OFPXMT_OFB_IPV4_DST: fprintf(stream, "ipv4_dst=\""IP_FMT"\"", IP_ARGS(f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", ipv4_dst_mask=\""IP_FMT"\"", IP_ARGS(f->value + 4)); } break; case OFPXMT_OFB_IPV4_SRC: fprintf(stream, "ipv4_src=\""IP_FMT"\"", IP_ARGS(f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", ipv4_src_mask=\""IP_FMT"\"", IP_ARGS(f->value + 4)); } break; case OFPXMT_OFB_IP_PROTO: fprintf(stream, "ip_proto=\"%d\"", *f->value); break; case OFPXMT_OFB_IP_DSCP: fprintf(stream, "ip_dscp=\"%d\"", *f->value & 0x3f); break; case OFPXMT_OFB_IP_ECN: fprintf(stream, "ip_ecn=\"%d\"", *f->value & 0x3); break; case OFPXMT_OFB_ICMPV4_TYPE: fprintf(stream, "icmpv4_type= \"%d\"", *f->value); break; case OFPXMT_OFB_ICMPV4_CODE: fprintf(stream, "icmpv4_code=\"%d\"", *f->value); break; case OFPXMT_OFB_ARP_SHA: fprintf(stream, "arp_sha=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", arp_sha_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6)); } break; case OFPXMT_OFB_ARP_THA: fprintf(stream, "arp_tha=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", arp_tha_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6)); } break; case OFPXMT_OFB_ARP_SPA: fprintf(stream, "arp_spa=\""IP_FMT"\"", IP_ARGS(f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", arp_sha_mask=\""IP_FMT"\"", IP_ARGS(f->value + 4)); } break; case OFPXMT_OFB_ARP_TPA: fprintf(stream, "arp_tpa=\""IP_FMT"\"", IP_ARGS(f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", arp_tpa_mask=\""IP_FMT"\"", IP_ARGS(f->value + 4)); } break; case OFPXMT_OFB_ARP_OP: fprintf(stream, "arp_op=\"0x%x\"", *((uint16_t*) f->value)); break; case OFPXMT_OFB_IPV6_SRC: { char addr_str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN); fprintf(stream, "nw_src_ipv6=\"%s\"", addr_str); if (OXM_HASMASK(f->header)) { inet_ntop(AF_INET6, f->value + 16, addr_str, INET6_ADDRSTRLEN); fprintf(stream, ", nw_src_ipv6_mask=\"%s\"", addr_str); } break; } case OFPXMT_OFB_IPV6_DST: { char addr_str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN); fprintf(stream, "nw_dst_ipv6=\"%s\"", addr_str); if (OXM_HASMASK(f->header)) { inet_ntop(AF_INET6, f->value + 16, addr_str, INET6_ADDRSTRLEN); fprintf(stream, ", nw_dst_ipv6_mask=\"%s\"", addr_str); } break; } case OFPXMT_OFB_IPV6_ND_TARGET: { char addr_str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN); fprintf(stream, "ipv6_nd_target=\"%s\"", addr_str); break; } case OFPXMT_OFB_IPV6_ND_SLL: fprintf(stream, "ipv6_nd_sll=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); break; case OFPXMT_OFB_IPV6_ND_TLL: fprintf(stream, "ipv6_nd_tll=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); break; case OFPXMT_OFB_IPV6_FLABEL: fprintf(stream, "ipv6_flow_label=\"%d\"", *((uint32_t*) f->value) & 0x000fffff); if (OXM_HASMASK(f->header)) { fprintf(stream, ", ipv6_flow_label_mask=\"%d\"", *((uint32_t*) (f->value+4))); } break; case OFPXMT_OFB_ICMPV6_TYPE: fprintf(stream, "icmpv6_type=\"%d\"", *f->value); break; case OFPXMT_OFB_ICMPV6_CODE: fprintf(stream, "icmpv6_code=\"%d\"", *f->value); break; case OFPXMT_OFB_MPLS_LABEL: fprintf(stream, "mpls_label=\"%d\"",((uint32_t) *f->value) & 0x000fffff); break; case OFPXMT_OFB_MPLS_TC: fprintf(stream, "mpls_tc=\"%d\"", *f->value & 0x3); break; case OFPXMT_OFB_MPLS_BOS: fprintf(stream, "mpls_bos=\"%d\"", *f->value & 0xfe); break; case OFPXMT_OFB_METADATA: fprintf(stream, "metadata=\"0x%llx\"", *((uint64_t*) f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", metadata_mask=\"0x%llx\"", *((uint64_t*)(f->value+8))); } break; case OFPXMT_OFB_PBB_ISID : fprintf(stream, "pbb_isid=\"%d\"", *((uint32_t*) f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", pbb_isid_mask=\"%d\"", *((uint32_t*)(f->value+4))); } break; case OFPXMT_OFB_TUNNEL_ID: fprintf(stream, "tunnel_id=\"%lld\"", *((uint64_t*) f->value)); if (OXM_HASMASK(f->header)) { fprintf(stream, ", tunnel_id_mask=\"%lld\"", *((uint64_t*)(f->value+8))); } break; case OFPXMT_OFB_IPV6_EXTHDR: fprintf(stream, "ext_hdr=\""); ofl_ipv6_ext_hdr_print(stream, *((uint16_t*) f->value)); fprintf(stream, "\""); if (OXM_HASMASK(f->header)) { fprintf(stream, ", ext_hdr_mask=\"0x%x\"", *((uint16_t*)(f->value+4))); } break; default: fprintf(stream, "unknown type %d", field); } }
size_t ofl_actions_pack(struct ofl_action_header *src, struct ofp_action_header *dst, uint8_t* data, struct ofl_exp *exp) { dst->type = htons(src->type); memset(dst->pad, 0x00, 4); switch (src->type) { case OFPAT_OUTPUT: { struct ofl_action_output *sa = (struct ofl_action_output *)src; struct ofp_action_output *da = (struct ofp_action_output *)dst; da->len = htons(sizeof(struct ofp_action_output)); da->port = htonl(sa->port); da->max_len = htons(sa->max_len); memset(da->pad, 0x00, 6); return sizeof(struct ofp_action_output); } case OFPAT_COPY_TTL_OUT: case OFPAT_COPY_TTL_IN: { dst->len = htons(sizeof(struct ofp_action_header)); return sizeof(struct ofp_action_header); } case OFPAT_SET_MPLS_TTL: { struct ofl_action_mpls_ttl *sa = (struct ofl_action_mpls_ttl *)src; struct ofp_action_mpls_ttl *da = (struct ofp_action_mpls_ttl *)dst; da->len = htons(sizeof(struct ofp_action_mpls_ttl)); da->mpls_ttl = sa->mpls_ttl; memset(da->pad, 0x00, 3); return sizeof(struct ofp_action_mpls_ttl); } case OFPAT_DEC_MPLS_TTL: { dst->len = htons(sizeof(struct ofp_action_header)); return sizeof(struct ofp_action_header); } case OFPAT_PUSH_VLAN: case OFPAT_PUSH_MPLS: case OFPAT_PUSH_PBB:{ struct ofl_action_push *sa = (struct ofl_action_push *)src; struct ofp_action_push *da = (struct ofp_action_push *)dst; da->len = htons(sizeof(struct ofp_action_push)); da->ethertype = htons(sa->ethertype); memset(da->pad, 0x00, 2); return sizeof(struct ofp_action_push); } case OFPAT_POP_VLAN: case OFPAT_POP_PBB: { struct ofp_action_header *da = (struct ofp_action_header *)dst; da->len = htons(sizeof(struct ofp_action_header)); return sizeof (struct ofp_action_header); } case OFPAT_POP_MPLS: { struct ofl_action_pop_mpls *sa = (struct ofl_action_pop_mpls *)src; struct ofp_action_pop_mpls *da = (struct ofp_action_pop_mpls *)dst; da->len = htons(sizeof(struct ofp_action_pop_mpls)); da->ethertype = htons(sa->ethertype); memset(da->pad, 0x00, 2); return sizeof(struct ofp_action_pop_mpls); } case OFPAT_SET_QUEUE: { struct ofl_action_set_queue *sa = (struct ofl_action_set_queue *)src; struct ofp_action_set_queue *da = (struct ofp_action_set_queue *)dst; da->len = htons(sizeof(struct ofp_action_set_queue)); da->queue_id = htonl(sa->queue_id); return sizeof(struct ofp_action_set_queue); } case OFPAT_GROUP: { struct ofl_action_group *sa = (struct ofl_action_group *)src; struct ofp_action_group *da = (struct ofp_action_group *)dst; da->len = htons(sizeof(struct ofp_action_group)); da->group_id = htonl(sa->group_id); return sizeof(struct ofp_action_group); } case OFPAT_SET_NW_TTL: { struct ofl_action_set_nw_ttl *sa = (struct ofl_action_set_nw_ttl *)src; struct ofp_action_nw_ttl *da = (struct ofp_action_nw_ttl *)dst; da->len = htons(sizeof(struct ofp_action_nw_ttl)); da->nw_ttl = sa->nw_ttl; memset(da->pad, 0x00, 3); return sizeof(struct ofp_action_nw_ttl); } case OFPAT_DEC_NW_TTL: { dst->len = htons(sizeof(struct ofp_action_header)); return sizeof(struct ofp_action_header); } case OFPAT_SET_FIELD: { struct ofl_action_set_field *sa = (struct ofl_action_set_field *) src; struct ofp_action_set_field *da = (struct ofp_action_set_field *) dst; uint32_t header; uint8_t padding_size; da->len = htons(sizeof(struct ofp_action_set_field) + ROUND_UP(OXM_LENGTH(sa->field->header),8)); /*Put OXM header in the field*/ header = htonl(sa->field->header); memcpy(&da->field, &header, 4); switch (OXM_LENGTH(sa->field->header)){ case 1: case 6: case 16: memcpy(data + (sizeof(struct ofp_action_set_field)), sa->field->value, OXM_LENGTH(sa->field->header)); break; case 2:{ uint16_t value = htons(*((uint16_t*) sa->field->value)); memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header)); break; } case 4:{ uint32_t value; uint8_t field = OXM_FIELD(sa->field->header); if( field != 11 && field != 12 && field != 22 && field != 23) value = htonl(*((uint32_t*) sa->field->value)); else value = *((uint32_t*) sa->field->value); memcpy(data + (sizeof(struct ofp_action_set_field)), &value, OXM_LENGTH(sa->field->header)); break; } case 8:{ uint64_t value = htons(*((uint64_t*) sa->field->value)); memcpy(data + (sizeof(struct ofp_action_set_field)),&value,OXM_LENGTH(sa->field->header)); break; } } /*padding*/ padding_size = ROUND_UP(OXM_LENGTH(sa->field->header),8) - OXM_LENGTH(sa->field->header); memset(data + (sizeof(struct ofp_action_set_field) + OXM_LENGTH(sa->field->header)), 0, padding_size); return ntohs((da->len)); } case OFPAT_EXPERIMENTER: { if (exp == NULL || exp->act == NULL || exp->act->pack == NULL) { OFL_LOG_WARN(LOG_MODULE, "Trying to pack experimenter, but no callback was given."); return 0; } return exp->act->pack(src, dst); } default: return 0; }; }
void print_oxm_tlv(FILE *stream, struct ofl_match_tlv *f, size_t *size){ uint8_t field = OXM_FIELD(f->header); if (field == OFPXMT_OFB_IN_PORT){ fprintf(stream, "in_port=\"%d\"",*((uint32_t*) f->value)); *size -= 8; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IN_PHY_PORT){ fprintf(stream, "in_phy_port=\"%d\"",*((uint32_t*) f->value)); *size -= 8; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_VLAN_VID){ uint16_t *v = (uint16_t *) f->value; if (*v == OFPVID_NONE) fprintf(stream, "vlan_vid= none"); else if (*v == OFPVID_PRESENT && OXM_HASMASK(f->header)) fprintf(stream, "vlan_vid= any"); else fprintf(stream, "vlan_vid=\"%d\"",*v & VLAN_VID_MASK); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_VLAN_PCP){ fprintf(stream, "vlan_pcp=\"%d\"", *f->value & 0x7); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ETH_TYPE){ uint16_t *v = (uint16_t *) f->value; fprintf(stream, "eth_type="); fprintf(stream,"\"0x%x\"", *v); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_TCP_SRC){ fprintf(stream, "tcp_src=\"%d\"",*((uint16_t*) f->value)); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_TCP_DST){ fprintf(stream, "tcp_dst=\"%d\"",*((uint16_t*) f->value)); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_UDP_SRC){ fprintf(stream, "udp_src=\"%d\"",*((uint16_t*) f->value)); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_UDP_DST){ fprintf(stream, "udp_dst=\"%d\"",*((uint16_t*) f->value)); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_SCTP_SRC){ fprintf(stream, "sctp_src=\"%d\"",*((uint16_t*) f->value)); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_SCTP_DST){ fprintf(stream, "sctp_dst=\"%d\"",*((uint16_t*) f->value)); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ETH_SRC){ fprintf(stream, "eth_src=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); *size -= 10; if (OXM_HASMASK(f->header)){ *size -= 6; fprintf(stream, ", eth_src_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ETH_DST){ fprintf(stream, "eth_dst=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); *size -= 10; if (OXM_HASMASK(f->header)){ *size -= 6; fprintf(stream, ", eth_dst_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV4_DST){ fprintf(stream, "ipv4_dst=\""IP_FMT"\"",IP_ARGS(f->value)); *size -= 8; if (OXM_HASMASK(f->header)){ *size -= 4; fprintf(stream, ", ipv4_dst_mask=\""IP_FMT"\"",IP_ARGS(f->value + 4)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV4_SRC){ fprintf(stream, "ipv4_src=\""IP_FMT"\"",IP_ARGS(f->value)); *size -= 8; if (OXM_HASMASK(f->header)){ *size -= 4; fprintf(stream, ", ipv4_src_mask=\""IP_FMT"\"",IP_ARGS(f->value + 4)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IP_PROTO){ fprintf(stream, "ip_proto=\"%d\"", *f->value); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IP_DSCP){ fprintf(stream, "ip_dscp=\"%d\"", *f->value & 0x3f); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IP_ECN){ fprintf(stream, "ip_ecn=\"%d\"", *f->value & 0x3); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ICMPV4_TYPE){ fprintf(stream, "icmpv4_type= \"%d\"", *f->value); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ICMPV4_CODE){ fprintf(stream, "icmpv4_code=\"%d\"", *f->value); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ARP_SHA){ fprintf(stream, "arp_sha=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); *size -= 10; if (OXM_HASMASK(f->header)){ *size -= 6; fprintf(stream, ", arp_sha_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ARP_THA){ fprintf(stream, "arp_tha=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); *size -= 10; if (OXM_HASMASK(f->header)){ *size -= 6; fprintf(stream, ", arp_tha_mask=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value + 6)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ARP_SPA){ fprintf(stream, "arp_spa=\""IP_FMT"\"",IP_ARGS(f->value)); *size -= 8; if (OXM_HASMASK(f->header)){ *size -= 4; fprintf(stream, ", arp_sha_mask=\""IP_FMT"\"",IP_ARGS(f->value + 4)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ARP_TPA){ fprintf(stream, "arp_tpa=\""IP_FMT"\"",IP_ARGS(f->value)); *size -= 8; if (OXM_HASMASK(f->header)){ *size -= 4; fprintf(stream, ", arp_tpa_mask=\""IP_FMT"\"",IP_ARGS(f->value + 4)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ARP_OP){ uint16_t *v = (uint16_t *) f->value; fprintf(stream, "arp_op=\"0x"); fprintf(stream,"%x\"", *v); *size -= 6; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV6_SRC){ char addr_str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN); *size -= 20; fprintf(stream, "nw_src_ipv6=\"%s\"", addr_str); if (OXM_HASMASK(f->header)){ *size -= 16; inet_ntop(AF_INET6, f->value + 16, addr_str, INET6_ADDRSTRLEN); fprintf(stream, ", nw_src_ipv6_mask=\"%s\"", addr_str); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV6_DST){ char addr_str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN); *size -= 20; fprintf(stream, "nw_dst_ipv6=\"%s\"", addr_str); if (OXM_HASMASK(f->header)){ *size -= 16; inet_ntop(AF_INET6, f->value + 16, addr_str, INET6_ADDRSTRLEN); fprintf(stream, ", nw_dst_ipv6_mask=\"%s\"", addr_str); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV6_ND_TARGET){ char addr_str[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, f->value, addr_str, INET6_ADDRSTRLEN); *size -= 20; fprintf(stream, "ipv6_nd_target=\"%s\"", addr_str); if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV6_ND_SLL){ fprintf(stream, "ipv6_nd_sll=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); *size -= 10; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV6_ND_TLL){ fprintf(stream, "ipv6_nd_tll=\""ETH_ADDR_FMT"\"", ETH_ADDR_ARGS(f->value)); *size -= 10; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV6_FLABEL){ uint32_t mask = 0x000fffff; *size -= 8; fprintf(stream, "ipv6_flow_label=\"%d\"",*((uint32_t*) f->value) & mask ); if (OXM_HASMASK(f->header)){ uint8_t *flabel_mask = (uint8_t*) f->value + 4; *size -= 4; fprintf(stream, ", ipv6_flow_label_mask=\"%d\"",*((uint32_t*)flabel_mask)); } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ICMPV6_TYPE){ fprintf(stream, "icmpv6_type=\"%d\"", *f->value); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_ICMPV6_CODE){ fprintf(stream, "icmpv6_code=\"%d\"", *f->value); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_MPLS_LABEL){ uint32_t mask = 0xfffff; fprintf(stream, "mpls_label=\"%d\"",((uint32_t) *f->value) & mask ); *size -= 8; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_MPLS_TC){ fprintf(stream, "mpls_tc=\"%d\"", *f->value & 0x3); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_MPLS_BOS){ fprintf(stream, "mpls_bos=\"%d\"", *f->value & 0xfe); *size -= 5; if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_METADATA){ fprintf(stream, "metadata=\"%lld\"", *((uint64_t*) f->value)); *size -= 12; if (OXM_HASMASK(f->header)){ fprintf(stream, ", metadata_mask=\"%lld\"", *((uint64_t*) f->value+ 8 )); *size -= 8; } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_PBB_ISID ){ fprintf(stream, "pbb_isid=\"%d\"",*((uint32_t*) f->value)); *size -= 8; if (OXM_HASMASK(f->header)){ fprintf(stream, ", pbb_isid_mask=\"%d\"", *((uint32_t*) f->value +4)); *size -= 4; } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_TUNNEL_ID){ fprintf(stream, "tunnel_id=\"%lld\"", *((uint64_t*) f->value)); *size -= 12; if (OXM_HASMASK(f->header)){ fprintf(stream, ", tunnel_id_mask=\"%lld\"", *((uint64_t*) f->value+ 8 )); *size -= 8; } if (*size > 4) fprintf(stream, ", "); } else if (field == OFPXMT_OFB_IPV6_EXTHDR){ fprintf(stream, "ext_hdr=\\"); ofl_ipv6_ext_hdr_print(stream, *((uint16_t*) f->value) ); *size -= 6; if (OXM_HASMASK(f->header)){ *size -= 2; fprintf(stream, ", ext_hdr_mask=\"0x%x\"",*((uint16_t*) f->value + 4)); } if (*size > 4) fprintf(stream, ", "); } }