lagopus_result_t
ofp_barrier_request_handle_wrap(struct channel *channel,
                                struct pbuf *pbuf,
                                struct ofp_header *xid_header,
                                struct ofp_error *error) {
  /* Copy request data for ofp_error. */
  if (pbuf_copy_with_length(req_pbuf, pbuf, OFP_ERROR_MAX_SIZE) !=
      LAGOPUS_RESULT_OK) {
    TEST_FAIL_MESSAGE("pbuf_copy_with_length error.");
  }
  error->req = req_pbuf;

  return ofp_barrier_request_handle(channel, pbuf, xid_header, error);
}
예제 #2
0
/* SEND */
STATIC lagopus_result_t
ofp_packet_in_create(struct packet_in *packet_in,
                     struct pbuf **pbuf) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  uint16_t miss_send_len;
  uint16_t length = 0;
  uint16_t remain_length = 0;
  uint16_t match_total_len = 0;
  uint8_t tmp_version = 0x00;
  uint32_t tmp_xid = 0x00;
  uint16_t tmp_length = 0;

  if (packet_in != NULL && packet_in->data != NULL &&
      pbuf != NULL) {

    /* alloc */
    *pbuf = pbuf_alloc(OFP_PACKET_MAX_SIZE);

    if (*pbuf != NULL) {
      pbuf_plen_set(*pbuf, OFP_PACKET_MAX_SIZE);

      /* set total_len. */
      ret = pbuf_length_get(packet_in->data, &length);
      if (ret == LAGOPUS_RESULT_OK) {
        packet_in->ofp_packet_in.total_len = length;

        /* Fill in header. */
        /* tmp_* is replaced later. */
        ofp_header_set(&packet_in->ofp_packet_in.header, tmp_version,
                       OFPT_PACKET_IN, tmp_length, tmp_xid);

        ret = ofp_packet_in_encode(*pbuf, &packet_in->ofp_packet_in);

        if (ret == LAGOPUS_RESULT_OK) {
          ret = ofp_match_list_encode(NULL, *pbuf, &packet_in->match_list,
                                      &match_total_len);

          if (ret == LAGOPUS_RESULT_OK) {
            /* Cut packet. */
            remain_length = (uint16_t) pbuf_plen_get(*pbuf);
            if (packet_in->ofp_packet_in.buffer_id == OFP_NO_BUFFER) {
              miss_send_len = remain_length;
            } else {
              miss_send_len = packet_in->miss_send_len;
            }
            if (length < miss_send_len) {
              miss_send_len = length;
            }

            /* exist data */
            if (miss_send_len != 0) {
              /* add padding */
              ret = ofp_padding_add(*pbuf, OFP_PACKET_IN_PAD);

              if (ret == LAGOPUS_RESULT_OK) {
                /* Cut packet. (remain_length) */
                if (miss_send_len + OFP_PACKET_IN_PAD > remain_length) {
                  miss_send_len = remain_length;
                }

                if (pbuf_plen_check(*pbuf, miss_send_len) !=
                    LAGOPUS_RESULT_OK) {
                  lagopus_msg_warning("FAILED : over data length.\n");
                  ret = LAGOPUS_RESULT_OUT_OF_RANGE;
                } else {
                  /* copy data. */
                  ret = pbuf_copy_with_length(*pbuf, packet_in->data,
                                              miss_send_len);
                  if (ret == LAGOPUS_RESULT_OK) {
                    pbuf_plen_reset(*pbuf);
                  } else {
                    lagopus_msg_warning("FAILED (%s).\n",
                                        lagopus_error_get_string(ret));
                  }
                }
              } else {
                lagopus_msg_warning("FAILED : over padding length.\n");
              }
            } else {
              ret = LAGOPUS_RESULT_OK;
            }
          } else {
            lagopus_msg_warning("FAILED (%s).\n",
                                lagopus_error_get_string(ret));
          }
        } else {
          lagopus_msg_warning("FAILED (%s).\n",
                              lagopus_error_get_string(ret));
        }
      } else {
        lagopus_msg_warning("FAILED (%s).\n",
                            lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("Can't allocate pbuf.\n");
      ret = LAGOPUS_RESULT_NO_MEMORY;
    }

    /* free. */
    if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) {
      pbuf_free(*pbuf);
      *pbuf = NULL;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
예제 #3
0
/* Packetout packet receive. */
lagopus_result_t
ofp_packet_out_handle(struct channel *channel, struct pbuf *pbuf,
                      struct ofp_header *xid_header,
                      struct ofp_error *error) {
  lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES;
  struct eventq_data *eventq_data = NULL;
  struct pbuf *data_pbuf = NULL;
  struct pbuf *req_pbuf = NULL;
  uint64_t dpid;
  uint16_t data_len = 0;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && error != NULL) {
    dpid = channel_dpid_get(channel);

    /* create packet_out */
    eventq_data = malloc(sizeof(*eventq_data));
    if (eventq_data != NULL) {
      memset(eventq_data, 0, sizeof(*eventq_data));

      /* Init action-list. */
      TAILQ_INIT(&eventq_data->packet_out.action_list);
      eventq_data->packet_out.data = NULL;
      eventq_data->packet_out.req = NULL;

      /* decode. */
      if ((res = ofp_packet_out_decode(
                   pbuf, &(eventq_data->packet_out.ofp_packet_out))) !=
          LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("packet_out decode error.\n");
        ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
        res = LAGOPUS_RESULT_OFP_ERROR;
      } else if ((res = ofp_action_parse(
                          pbuf,
                          eventq_data->packet_out.ofp_packet_out.actions_len,
                          &(eventq_data->packet_out.action_list), error)) !=
                 LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("action_list decode error.\n");
      } else {                  /* decode success */
        /* set eventq_data members */
        eventq_data->type = LAGOPUS_EVENTQ_PACKET_OUT;
        eventq_data->free = ofp_packet_out_free;
        eventq_data->packet_out.channel_id = channel_id_get(channel);

        /* copy packet_out.data if needed */
        res = pbuf_length_get(pbuf, &data_len);
        if (res == LAGOPUS_RESULT_OK) {
          if (data_len != 0) {
            if (eventq_data->packet_out.ofp_packet_out.buffer_id ==
                OFP_NO_BUFFER) {
              /* alloc packet_out.data */
              data_pbuf = pbuf_alloc(data_len);
              if (data_pbuf != NULL) {
                res = pbuf_copy_with_length(data_pbuf, pbuf, data_len);

                if (res == LAGOPUS_RESULT_OK) {
                  eventq_data->packet_out.data = data_pbuf;
                } else {
                  lagopus_msg_warning("FAILED (%s).\n",
                                      lagopus_error_get_string(res));
                }
              } else {
                lagopus_msg_warning("Can't allocate data_pbuf.\n");
                res = LAGOPUS_RESULT_NO_MEMORY;
              }
            } else {
              lagopus_msg_warning("Not empty data filed in request(buffer_id = %x).\n",
                                  eventq_data->packet_out.ofp_packet_out.buffer_id);
              ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BUFFER_UNKNOWN);
              res = LAGOPUS_RESULT_OFP_ERROR;
            }
          } else {
            res = LAGOPUS_RESULT_OK;
          }

          /* Copy request for ofp_error. */
          if (res == LAGOPUS_RESULT_OK && error->req != NULL) {
            req_pbuf = pbuf_alloc(OFP_ERROR_MAX_SIZE);
            if (req_pbuf != NULL) {
              res = pbuf_copy(req_pbuf, error->req);

              if (res == LAGOPUS_RESULT_OK) {
                eventq_data->packet_out.req = req_pbuf;
              } else {
                lagopus_msg_warning("FAILED (%s).\n",
                                    lagopus_error_get_string(res));
              }
            } else {
              lagopus_msg_warning("Can't allocate data_pbuf.\n");
              res = LAGOPUS_RESULT_NO_MEMORY;
            }
          }

          if (res == LAGOPUS_RESULT_OK) {
            /* dump trace.*/
            packet_out_trace(&eventq_data->packet_out.ofp_packet_out,
                             &eventq_data->packet_out.action_list);

            /* send to DataPlane */
            res = ofp_handler_event_dataq_put(dpid, eventq_data);
            if (res != LAGOPUS_RESULT_OK) {
              lagopus_msg_warning("FAILED (%s).\n",
                                  lagopus_error_get_string(res));
            }
          }
        } else {
          lagopus_msg_warning("FAILED (%s).\n",
                              lagopus_error_get_string(res));
        }
      }

      if (res != LAGOPUS_RESULT_OK && eventq_data != NULL) {
        ofp_packet_out_free(eventq_data);
      }
    } else {
      /* channel_pbuf_list_get returns NULL */
      res = LAGOPUS_RESULT_NO_MEMORY;
    }
  } else {
    /* params are NULL */
    res = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return res;
}