size_t ofl_structs_bucket_pack(struct ofl_bucket *src, struct ofp_bucket *dst, struct ofl_exp *exp) { size_t total_len, rem, align, len; uint8_t *data; size_t i; total_len = sizeof(struct ofp_bucket) + ofl_actions_ofp_total_len(src->actions, src->actions_num, exp); /* Note: buckets are 64 bit aligned according to spec 1.1 draft 3 */ rem = total_len % 8; align = rem == 0 ? 0 : (8-rem); total_len += align; dst->len = htons(total_len); dst->weight = htons(src->weight); dst->watch_port = htonl(src->watch_port); dst->watch_group = htonl(src->watch_group); memset(dst->pad, 0x00, 4); data = (uint8_t *)dst + sizeof(struct ofp_bucket); for (i=0; i<src->actions_num; i++) { len = ofl_actions_pack(src->actions[i], (struct ofp_action_header *)data, data, exp); data += len; } memset(data, 0x00, align); return total_len; }
static int ofl_msg_pack_packet_out(struct ofl_msg_packet_out *msg, uint8_t **buf, size_t *buf_len, struct ofl_exp *exp) { struct ofp_packet_out *packet_out; size_t act_len; uint8_t *ptr; int i; act_len = ofl_actions_ofp_total_len(msg->actions, msg->actions_num, exp); *buf_len = sizeof(struct ofp_packet_out) + act_len + msg->data_length; *buf = (uint8_t *)malloc(*buf_len); packet_out = (struct ofp_packet_out *)(*buf); packet_out->buffer_id = htonl(msg->buffer_id); packet_out->in_port = htonl(msg->in_port); packet_out->actions_len = htons(act_len); memset(packet_out->pad, 0x00, 6); ptr = (*buf) + sizeof(struct ofp_packet_out); for (i=0; i<msg->actions_num; i++) { ptr += ofl_actions_pack(msg->actions[i], (struct ofp_action_header *)ptr,*buf, exp); } if (msg->data_length > 0) { memcpy(ptr, msg->data, msg->data_length); } return 0; }
size_t ofl_structs_instructions_pack(struct ofl_instruction_header *src, struct ofp_instruction *dst, struct ofl_exp *exp) { dst->type = htons(src->type); memset(dst->pad, 0x00, 4); switch (src->type) { case OFPIT_GOTO_TABLE: { struct ofl_instruction_goto_table *si = (struct ofl_instruction_goto_table *)src; struct ofp_instruction_goto_table *di = (struct ofp_instruction_goto_table *)dst; di->len = htons(sizeof(struct ofp_instruction_goto_table)); di->table_id = si->table_id; memset(di->pad, 0x00, 3); return sizeof(struct ofp_instruction_goto_table); } case OFPIT_WRITE_METADATA: { struct ofl_instruction_write_metadata *si = (struct ofl_instruction_write_metadata *)src; struct ofp_instruction_write_metadata *di = (struct ofp_instruction_write_metadata *)dst; di->len = htons(sizeof(struct ofp_instruction_write_metadata)); memset(di->pad, 0x00, 4); di->metadata = hton64(si->metadata); di->metadata_mask = hton64(si->metadata_mask); return sizeof(struct ofp_instruction_write_metadata); } case OFPIT_WRITE_ACTIONS: case OFPIT_APPLY_ACTIONS: { size_t total_len, len; uint8_t *data; size_t i; struct ofl_instruction_actions *si = (struct ofl_instruction_actions *)src; struct ofp_instruction_actions *di = (struct ofp_instruction_actions *)dst; total_len = sizeof(struct ofp_instruction_actions) + ofl_actions_ofp_total_len(si->actions, si->actions_num, exp); di->len = htons(total_len); memset(di->pad, 0x00, 4); data = (uint8_t *)dst + sizeof(struct ofp_instruction_actions); for (i=0; i<si->actions_num; i++) { len = ofl_actions_pack(si->actions[i], (struct ofp_action_header *)data, data, exp); data += len; } return total_len; } case OFPIT_CLEAR_ACTIONS: { size_t total_len; struct ofp_instruction_actions *di = (struct ofp_instruction_actions *)dst; total_len = sizeof(struct ofp_instruction_actions); di->len = htons(total_len); memset(di->pad, 0x00, 4); return total_len; } case OFPIT_EXPERIMENTER: { if (exp == NULL || exp->inst == NULL || exp->inst->pack == NULL) { OFL_LOG_WARN(LOG_MODULE, "Trying to pack experimenter instruction, but no callback was given."); return -1; } return exp->inst->pack((struct ofl_instruction_header *)src, dst); } default: OFL_LOG_WARN(LOG_MODULE, "Trying to pack unknown instruction type."); return 0; } }