コード例 #1
0
static lagopus_result_t
s_parse_bucket_list(struct pbuf *pbuf,
                    struct bucket_list *bucket_list,
                    struct ofp_error *error) {
  lagopus_result_t res = LAGOPUS_RESULT_OK;
  if (TAILQ_EMPTY(bucket_list) == true && pbuf_plen_get(pbuf) == 0) {
    res = LAGOPUS_RESULT_OK;    /* bucket_list is empty */
  } else {
    /* decode buckets. */
    while (pbuf_plen_get(pbuf) > 0) {
      res = ofp_bucket_parse(pbuf, bucket_list, error);
      if (res != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("FAILED : ofp_bucket_parse (%s).\n",
                            lagopus_error_get_string(res));
        break;
      }
    }
    /* check plen. */
    if (res == LAGOPUS_RESULT_OK && pbuf_plen_get(pbuf) > 0) {
      lagopus_msg_warning("packet decode failed. (size over).\n");
      ofp_error_set(error, OFPET_GROUP_MOD_FAILED,
                    OFPGMFC_BAD_BUCKET);
      res = LAGOPUS_RESULT_OFP_ERROR;
    }
  }
  return res;
}
コード例 #2
0
ファイル: ofp_header_handler.c プロジェクト: tidatida/lagopus
/* header only packet. */
lagopus_result_t
ofp_header_create(struct channel *channel, uint8_t type,
                  struct ofp_header *xid_header,
                  struct ofp_header *header,
                  struct pbuf *pbuf) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  uint32_t xid;

  if (channel != NULL && header != NULL &&
      pbuf != NULL) {
    if (xid_header != NULL) {
      xid = xid_header->xid;
    } else {
      xid = channel_xid_get(channel);
    }

    ofp_header_set(header, channel_version_get(channel), type,
                   (uint16_t) pbuf_plen_get(pbuf), xid);

    ret = ofp_header_encode(pbuf, header);
    if (ret != LAGOPUS_RESULT_OK) {
      lagopus_msg_warning("FAILED (%s).\n",
                          lagopus_error_get_string(ret));
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #3
0
ファイル: pbuf_test.c プロジェクト: 1514louluo/lagopus
void
test_pbuf_info_store_load_normal(void) {
  struct pbuf *pbuf = pbuf_alloc(PBUF_LENGTH);
  pbuf_info_t pbuf_info;

  /* create test data */
  pbuf->getp = pbuf->data + 1;
  pbuf->putp = pbuf->data + 3;
  pbuf->plen = 2;

  /* call store func. */
  pbuf_info_store(pbuf, &pbuf_info);

  TEST_ASSERT_EQUAL_MESSAGE(pbuf->data + 1, pbuf_getp_get(&pbuf_info),
                            "getp error.");
  TEST_ASSERT_EQUAL_MESSAGE(pbuf->data + 3, pbuf_putp_get(&pbuf_info),
                            "putp error.");
  TEST_ASSERT_EQUAL_MESSAGE(2, pbuf_plen_get(&pbuf_info),
                            "plen error.");

  /* create test data */
  pbuf_reset(pbuf);
  /* check reset. */
  TEST_ASSERT_EQUAL_MESSAGE(pbuf->data, pbuf_getp_get(pbuf),
                            "getp error.");
  TEST_ASSERT_EQUAL_MESSAGE(pbuf->data, pbuf_putp_get(pbuf),
                            "putp error.");
  TEST_ASSERT_EQUAL_MESSAGE(0, pbuf_plen_get(pbuf),
                            "plen error.");

  /* call load func. */
  pbuf_info_load(pbuf, &pbuf_info);

  TEST_ASSERT_EQUAL_MESSAGE(pbuf->data + 1, pbuf_getp_get(pbuf),
                            "getp error.");
  TEST_ASSERT_EQUAL_MESSAGE(pbuf->data + 3, pbuf_putp_get(pbuf),
                            "putp error.");
  TEST_ASSERT_EQUAL_MESSAGE(2, pbuf_plen_get(pbuf),
                            "plen error.");

  /* after. */
  pbuf_free(pbuf);
}
コード例 #4
0
ファイル: ofp_header_handler.c プロジェクト: tidatida/lagopus
/* Header only packet receive. */
lagopus_result_t
ofp_header_handle(struct channel *channel, struct pbuf *pbuf,
                  struct ofp_error *error) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  struct ofp_header msg;

  if (channel != NULL && pbuf != NULL &&
      error != NULL) {
    /* Parse ofp_header. */
    ret = ofp_header_decode(pbuf, &msg);
    if (ret == LAGOPUS_RESULT_OK) {
      /* Skip payload if it exists. */
      if (pbuf_plen_get(pbuf) > 0) {
        ret = pbuf_forward(pbuf, pbuf_plen_get(pbuf));
        if (ret != LAGOPUS_RESULT_OK) {
          lagopus_msg_warning("FAILED (%s).\n",
                              lagopus_error_get_string(ret));
          if (ret == LAGOPUS_RESULT_OUT_OF_RANGE) {
            ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
            ret = LAGOPUS_RESULT_OFP_ERROR;
          }
        }
      }

      if (ret == LAGOPUS_RESULT_OK &&
          channel_version_get(channel) != msg.version) {
        lagopus_msg_warning("Unsupported vetsion.\n");
        ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_VERSION);
        ret = LAGOPUS_RESULT_OFP_ERROR;
      }
    } else {
      lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret));
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      return LAGOPUS_RESULT_OFP_ERROR;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #5
0
/* Port mod received. */
lagopus_result_t
ofp_port_mod_handle(struct channel *channel, struct pbuf *pbuf,
                    struct ofp_header *xid_header,
                    struct ofp_error *error) {
  lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES;
  uint64_t dpid;
  struct ofp_port_mod port_mod;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && error != NULL) {
    /* Parse port_mod header. */
    res = ofp_port_mod_decode(pbuf, &(port_mod));
    if (res != LAGOPUS_RESULT_OK) {
      lagopus_msg_warning("port_mod decode error.\n");
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      res = LAGOPUS_RESULT_OFP_ERROR;
    } else if (pbuf_plen_get(pbuf) > 0) {
      lagopus_msg_warning("packet decode failed. (size over).\n");
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
      res = LAGOPUS_RESULT_OFP_ERROR;
    } else {                    /* decode success */
      /* dump trace. */
      port_mod_trace(&port_mod);

      /* check config. */
      res = ofp_port_config_check(port_mod.config, error);
      if (res == LAGOPUS_RESULT_OK) {
        /* check mask. */
        res = ofp_port_config_check(port_mod.mask, error);
        if (res == LAGOPUS_RESULT_OK) {
          /* check advertise. */
          res = ofp_port_features_check(port_mod.advertise, error);
          if (res == LAGOPUS_RESULT_OK) {
            dpid = channel_dpid_get(channel);
            /* call API */
            res = ofp_port_mod_modify(dpid, &port_mod, error);
            if (res != LAGOPUS_RESULT_OK) {
              lagopus_msg_warning("FAILED (%s).\n",
                                  lagopus_error_get_string(res));
            }
          }
        }
      }
    }
  } else {
    res = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return res;
}
コード例 #6
0
STATIC lagopus_result_t
ofp_role_reply_create(struct channel *channel,
                      struct pbuf **pbuf,
                      struct ofp_header *xid_header,
                      struct ofp_role_request *role_request) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  /* reply is ofp_role_request structure. */
  struct ofp_role_request role_reply;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && role_request != NULL) {
    /* alloc */
    *pbuf = channel_pbuf_list_get(channel,
                                  sizeof(struct ofp_role_request));
    if (*pbuf != NULL) {
      pbuf_plen_set(*pbuf, sizeof(struct ofp_role_request));

      /* Fill in header. */
      ofp_header_set(&role_reply.header,
                     channel_version_get(channel),
                     OFPT_ROLE_REPLY,
                     (uint16_t) pbuf_plen_get(*pbuf),
                     xid_header->xid);

      role_reply.role = role_request->role;
      memset(role_reply.pad, 0, sizeof(role_request->pad));
      role_reply.generation_id = role_request->generation_id;

      /* Encode message. */
      ret = ofp_role_request_encode(*pbuf, &role_reply);
      if (ret != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("FAILED (%s).\n",
                            lagopus_error_get_string(ret));
      }

      if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) {
        channel_pbuf_list_unget(channel, *pbuf);
        *pbuf = NULL;
      }
    } else {
      lagopus_msg_warning("Can't allocate pbuf.\n");
      ret = LAGOPUS_RESULT_NO_MEMORY;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #7
0
STATIC lagopus_result_t
ofp_get_async_reply_create(struct channel *channel,
                           struct pbuf **pbuf,
                           struct ofp_header *xid_header) {
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  struct ofp_async_config async_config;

  /* check params */
  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL) {
    /* alloc */
    *pbuf = channel_pbuf_list_get(channel,
                                  sizeof(struct ofp_async_config));
    if (*pbuf != NULL) {
      pbuf_plen_set(*pbuf, sizeof(struct ofp_async_config));

      /* Copy packet_in_mask, port_status_mask, flow_removed_mask. */
      channel_role_mask_get(channel, &async_config);

      /* Fill in header. */
      ofp_header_set(&async_config.header,
                     channel_version_get(channel),
                     OFPT_GET_ASYNC_REPLY,
                     (uint16_t) pbuf_plen_get(*pbuf),
                     xid_header->xid);

      /* Encode message. */
      ret = ofp_async_config_encode(*pbuf, &async_config);

      if (ret != LAGOPUS_RESULT_OK) {
        lagopus_msg_warning("FAILED : ofp_async_config_encode (%s).\n",
                            lagopus_error_get_string(ret));
      }
    } else {
      lagopus_msg_warning("Can't allocate pbuf.\n");
      ret = LAGOPUS_RESULT_NO_MEMORY;
    }

    if (ret != LAGOPUS_RESULT_OK &&  *pbuf != NULL) {
      channel_pbuf_list_unget(channel, *pbuf);
      *pbuf = NULL;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #8
0
/* Send switch features reply. */
STATIC lagopus_result_t
ofp_features_reply_create(struct channel *channel,
                          struct pbuf **pbuf,
                          struct ofp_header *xid_header) {
  struct ofp_switch_features features;
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (channel != NULL && pbuf != NULL && xid_header != NULL) {
    /* alloc */
    *pbuf = channel_pbuf_list_get(channel,
                                  sizeof(struct ofp_switch_features));
    if (*pbuf != NULL) {
      pbuf_plen_set(*pbuf, sizeof(struct ofp_switch_features));

      ret = features_reply_features_get(channel, &features);
      if (ret == LAGOPUS_RESULT_OK) {
        /* Fill in header. */
        ofp_header_set(&features.header, channel_version_get(channel),
                       OFPT_FEATURES_REPLY, (uint16_t) pbuf_plen_get(*pbuf),
                       xid_header->xid);

        /* Encode message. */
        ret = ofp_switch_features_encode(*pbuf, &features);
        if (ret != LAGOPUS_RESULT_OK) {
          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;
    }

    if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) {
      channel_pbuf_list_unget(channel, *pbuf);
      *pbuf = NULL;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #9
0
/* Send experimenter reply. */
STATIC lagopus_result_t
ofp_experimenter_reply_create(struct channel *channel,
                              struct pbuf **pbuf,
                              struct ofp_header *xid_header,
                              struct ofp_experimenter_header *exper_req) {
  struct ofp_experimenter_header exper_reply;
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;

  if (channel != NULL && pbuf != NULL &&
      xid_header != NULL && exper_req != NULL) {
    *pbuf = NULL;
    /* alloc */
    *pbuf = channel_pbuf_list_get(channel,
                                  sizeof(struct ofp_experimenter_header));
    if (*pbuf != NULL) {
      pbuf_plen_set(*pbuf, sizeof(struct ofp_experimenter_header));

      exper_reply.experimenter = exper_req->experimenter;
      exper_reply.exp_type = exper_req->exp_type;

      /* Fill in header. */
      ofp_header_set(&exper_reply.header, channel_version_get(channel),
                     OFPT_EXPERIMENTER, (uint16_t) pbuf_plen_get(*pbuf),
                     xid_header->xid);

      /* Encode message. */
      ret = ofp_experimenter_header_encode(*pbuf, &exper_reply);
      if (ret != LAGOPUS_RESULT_OK) {
        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;
    }

    if (ret != LAGOPUS_RESULT_OK && *pbuf != NULL) {
      channel_pbuf_list_unget(channel, *pbuf);
      *pbuf = NULL;
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #10
0
static lagopus_result_t
s_ofpgc_delete(struct pbuf *pbuf,
               uint64_t dpid,
               struct ofp_group_mod *group_mod,
               struct ofp_error *error) {
  lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES;

  /* dump trace. */
  group_mod_trace(group_mod, NULL);

  /* check plen. */
  if (pbuf_plen_get(pbuf) == 0) {
    res = ofp_group_mod_delete(dpid, group_mod, error);
  } else {
    lagopus_msg_warning("packet decode failed. (size over).\n");
    ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    res = LAGOPUS_RESULT_OFP_ERROR;
  }
  return res;
}
コード例 #11
0
ファイル: ofp_role.c プロジェクト: D-TOKIOKA/lagopus
static lagopus_result_t
ofp_write_channel(struct channel *channel,
                  struct pbuf *pbuf) {
  lagopus_result_t ret = LAGOPUS_RESULT_OK;
  struct pbuf *send_pbuf = NULL;

  if (channel != NULL && pbuf != NULL) {
    send_pbuf = channel_pbuf_list_get(channel,
                                      pbuf_plen_get(pbuf));
    if (send_pbuf != NULL) {
      /* Copy pbuf. */
      ret = pbuf_copy(send_pbuf, pbuf);

      if (ret == LAGOPUS_RESULT_OK) {
        ret = ofp_header_packet_set(channel, send_pbuf);

        if (ret == LAGOPUS_RESULT_OK) {
          channel_send_packet(channel, send_pbuf);
          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("Can't allocate pbuf.\n");
      ret = LAGOPUS_RESULT_NO_MEMORY;
    }

    if (ret != LAGOPUS_RESULT_OK && send_pbuf != NULL) {
      channel_pbuf_list_unget(channel, send_pbuf);
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #12
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;
}
コード例 #13
0
ファイル: ofp_header_handler.c プロジェクト: tidatida/lagopus
lagopus_result_t
ofp_header_mp_copy(struct pbuf *dst_pbuf,
                   struct pbuf *src_pbuf) {
  struct ofp_multipart_reply mp_reply;
  lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES;
  pbuf_info_t cur_src_pbuf_info;
  pbuf_info_t cur_dst_pbuf_info;
  pbuf_info_t update_pbuf_info;
  uint16_t cur_src_length = 0;

  if (dst_pbuf != NULL && src_pbuf != NULL) {
    /* Store current dst/src_pbuf info. */
    pbuf_info_store(dst_pbuf, &cur_dst_pbuf_info);
    pbuf_info_store(src_pbuf, &cur_src_pbuf_info);
    ret = pbuf_length_get(src_pbuf, &cur_src_length);

    if (ret == LAGOPUS_RESULT_OK) {
      /* Update src_pbuf info for ofp_multipart_reply_decode. */
      pbuf_getp_set(&update_pbuf_info, pbuf_data_get(src_pbuf));
      pbuf_putp_set(&update_pbuf_info,
                    pbuf_data_get(src_pbuf) + sizeof(struct ofp_multipart_reply));
      pbuf_plen_set(&update_pbuf_info, sizeof(struct ofp_multipart_reply));
      pbuf_info_load(src_pbuf, &update_pbuf_info);

      ret = ofp_multipart_reply_decode(src_pbuf, &mp_reply);

      if (ret == LAGOPUS_RESULT_OK) {
        /* Set length/flag in src_pbuf. */
        mp_reply.header.length = cur_src_length;
        mp_reply.flags = OFPMPF_REPLY_MORE;
        /* Update src_pbuf info for ofp_multipart_reply_encode. */
        pbuf_reset(src_pbuf);
        pbuf_plen_set(src_pbuf, sizeof(struct ofp_multipart_reply));

        ret = ofp_multipart_reply_encode(src_pbuf, &mp_reply);

        if (ret == LAGOPUS_RESULT_OK) {
          /* Set length/flag in dst_pbuf. */
          mp_reply.header.length = sizeof(struct ofp_multipart_reply);
          mp_reply.flags = 0;
          /* Update dst_pbuf info for ofp_multipart_reply_encode. */
          pbuf_reset(dst_pbuf);
          pbuf_plen_set(dst_pbuf, pbuf_plen_get(&cur_dst_pbuf_info));

          ret = ofp_multipart_reply_encode(dst_pbuf, &mp_reply);
          if (ret == LAGOPUS_RESULT_OK) {
            /* Load pbuf info. */
            pbuf_info_load(src_pbuf, &cur_src_pbuf_info);
          } 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("FAILED (%s).\n",
                          lagopus_error_get_string(ret));
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}
コード例 #14
0
/* FlowMod packet receive. */
lagopus_result_t
ofp_flow_mod_handle(struct channel *channel, struct pbuf *pbuf,
                    struct ofp_header *xid_header,
                    struct ofp_error *error) {
  lagopus_result_t ret;
  uint64_t dpid;
  struct ofp_flow_mod flow_mod;
  struct match_list match_list;
  struct instruction_list instruction_list;

  if (channel != NULL && pbuf != NULL && xid_header != NULL) {
    /* Init lists. */
    TAILQ_INIT(&match_list);
    TAILQ_INIT(&instruction_list);

    /* Parse flow mod header. */
    ret = ofp_flow_mod_decode(pbuf, &flow_mod);

    if (ret == LAGOPUS_RESULT_OK) {
      ret = flow_mod_flags_check(flow_mod.flags, error);

      if (ret == LAGOPUS_RESULT_OK) {
        /* Parse matches. */
        ret = ofp_match_parse(channel, pbuf, &match_list, error);

        if (ret == LAGOPUS_RESULT_OK) {
          /* Parse instructions. */
          if (flow_mod.command == OFPFC_DELETE ||
              flow_mod.command == OFPFC_DELETE_STRICT) {
            /* skip pbuf. */
            ret = pbuf_forward(pbuf, pbuf_plen_get(pbuf));
            if (ret != LAGOPUS_RESULT_OK) {
              lagopus_msg_warning("FAILED (%s).\n",
                                  lagopus_error_get_string(ret));
            }
          } else {
            while (pbuf_plen_get(pbuf) > 0) {
              ret = ofp_instruction_parse(pbuf, &instruction_list, error);
              if (ret != LAGOPUS_RESULT_OK) {
                lagopus_msg_warning("FAILED (%s).\n",
                                    lagopus_error_get_string(ret));
                break;
              }
            }
          }

          if (ret == LAGOPUS_RESULT_OK) {
            /* trace. */
            flow_mod_trace(&flow_mod, &match_list, &instruction_list);

            /* Flow add, modify, delete. */
            dpid = channel_dpid_get(channel);
            switch (flow_mod.command) {
              case OFPFC_ADD:
                ret = ofp_flow_mod_check_add(dpid, &flow_mod,
                                             &match_list, &instruction_list,
                                             error);
                break;
              case OFPFC_MODIFY:
              case OFPFC_MODIFY_STRICT:
                ret = ofp_flow_mod_modify(dpid, &flow_mod,
                                          &match_list, &instruction_list,
                                          error);
                break;
              case OFPFC_DELETE:
              case OFPFC_DELETE_STRICT:
                ret = ofp_flow_mod_delete(dpid,
                                          &flow_mod, &match_list,
                                          error);
                break;
              default:
                ofp_error_set(error, OFPET_FLOW_MOD_FAILED, OFPFMFC_BAD_COMMAND);
                ret = LAGOPUS_RESULT_OFP_ERROR;
                break;
            }

            if (ret == LAGOPUS_RESULT_OFP_ERROR) {
              lagopus_msg_warning("OFP ERROR (%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("FAILED (%s).\n", lagopus_error_get_string(ret));
      ret = LAGOPUS_RESULT_OFP_ERROR;
      ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN);
    }

    /* free. */
    if (ret != LAGOPUS_RESULT_OK) {
      ofp_instruction_list_elem_free(&instruction_list);
      ofp_match_list_elem_free(&match_list);
    }
  } else {
    ret = LAGOPUS_RESULT_INVALID_ARGS;
  }

  return ret;
}