diff options
Diffstat (limited to 'accel-pppd/ctrl/pppoe/vpppoe.c')
-rw-r--r-- | accel-pppd/ctrl/pppoe/vpppoe.c | 609 |
1 files changed, 517 insertions, 92 deletions
diff --git a/accel-pppd/ctrl/pppoe/vpppoe.c b/accel-pppd/ctrl/pppoe/vpppoe.c index 4dea5cd..c5fdcf7 100644 --- a/accel-pppd/ctrl/pppoe/vpppoe.c +++ b/accel-pppd/ctrl/pppoe/vpppoe.c @@ -6,6 +6,13 @@ #include <vapi/feature.api.vapi.h> #include <linux/if_ether.h> +#include <pthread.h> + +#include <memory.h> +#include <stdio.h> + +#include "events.h" +#include "triton.h" #include "vpppoe.h" @@ -15,172 +22,590 @@ DEFINE_VAPI_MSG_IDS_PPPOE_API_JSON DEFINE_VAPI_MSG_IDS_LCP_API_JSON DEFINE_VAPI_MSG_IDS_FEATURE_API_JSON -static struct vpp_connect_t { - vapi_ctx_t vapi; - int rfcounter; +static uint32_t sc_fallback_timer = 1000; + +/* rcbc - Reply CallBack Counter. Retry postponed calls if waiting less then sc_fallback_at_rcbc at curent time */ +static int sc_fallback_at_rcbc = 1024; +static int sc_vpp_queue_size = 2048; + +static int sc_teardown_on_max_queue = 512; + +static int sc_non_lcp_mode = 0; + +static struct vpp_connect_t +{ + vapi_ctx_t vapi; + int rfcounter; + + int rcbc; + + pthread_mutex_t lock_vpp; + + struct triton_context_t tctx; + struct triton_md_handler_t vapi_read_hnd; + + struct triton_timer_t timer; + + /* retry fallback lists */ + uint32_t retry_del_count; + struct list_head retry_del_list; } vpp_connect; const char vpp_app_name[] = "accel-vpppoe"; +static int vpppoe_read_events(struct triton_md_handler_t *h); +static void vpppoe_disconnect_from_vpp(); +static void vpppoe_timer(struct triton_timer_t *t); + +static void vpppoe_fallback_allocate_and_add_postponed_pppoe_del(uint8_t *client_mac, in_addr_t *client_ip, uint16_t session_id); + static void vpppoe_connect_to_vpp() { - vapi_error_e verr = vapi_ctx_alloc(&vpp_connect.vapi); + int fd = -1; + vapi_error_e verr = vapi_ctx_alloc(&vpp_connect.vapi); - if (verr != VAPI_OK) { - vpp_connect.vapi = NULL; + if (verr != VAPI_OK) + { + vpp_connect.vapi = NULL; return; } - verr = vapi_connect_ex(vpp_connect.vapi, vpp_app_name, NULL, 32, 32, VAPI_MODE_BLOCKING, true, true); + verr = vapi_connect_ex(vpp_connect.vapi, vpp_app_name, NULL, sc_vpp_queue_size, sc_vpp_queue_size, VAPI_MODE_NONBLOCKING, true, true); + if (verr != VAPI_OK) + { + vapi_ctx_free(vpp_connect.vapi); + vpp_connect.vapi = NULL; + return; + } - if (verr != VAPI_OK) { - vapi_ctx_free(vpp_connect.vapi); - vpp_connect.vapi = NULL; + verr = vapi_get_fd(vpp_connect.vapi, &fd); + if (verr != VAPI_OK) + { + vapi_disconnect_from_vpp(vpp_connect.vapi); + vapi_ctx_free(vpp_connect.vapi); + vpp_connect.vapi = NULL; + return; } + + memset(&vpp_connect.tctx, 0, sizeof(vpp_connect.tctx)); + memset(&vpp_connect.vapi_read_hnd, 0, sizeof(vpp_connect.vapi_read_hnd)); + + vpp_connect.vapi_read_hnd.fd = fd; + vpp_connect.vapi_read_hnd.read = vpppoe_read_events; + + // TODO: add options for triton ctx aka close and free + + vpp_connect.timer.expire = vpppoe_timer; + vpp_connect.timer.period = sc_fallback_timer; + + // TODO: add checks + triton_context_register(&vpp_connect.tctx, NULL); + triton_md_register_handler(&vpp_connect.tctx, &vpp_connect.vapi_read_hnd); + triton_md_enable_handler(&vpp_connect.vapi_read_hnd, MD_MODE_READ); + triton_timer_add(&vpp_connect.tctx, &vpp_connect.timer, 0); + triton_context_wakeup(&vpp_connect.tctx); } -static void vpppoe_disconnect_from_vpp() +void vpppoe_disconnect_from_vpp() { - vapi_disconnect(vpp_connect.vapi); - vapi_ctx_free(vpp_connect.vapi); - vpp_connect.vapi = NULL; -} + triton_timer_del(&vpp_connect.timer); + triton_md_unregister_handler(&vpp_connect.vapi_read_hnd, 0); + triton_context_unregister(&vpp_connect.tctx); -void vpppoe_init() { + vapi_disconnect(vpp_connect.vapi); + vapi_ctx_free(vpp_connect.vapi); vpp_connect.vapi = NULL; - vpp_connect.rfcounter = 0; - - memset(&vpp_connect, 0, sizeof(vpp_connect)); } void vpppoe_get() { int rfc = __sync_fetch_and_add(&vpp_connect.rfcounter, 1); - if (!rfc) - vpppoe_connect_to_vpp(); + if (!rfc) + vpppoe_connect_to_vpp(); } void vpppoe_put() { int rfc = __sync_sub_and_fetch(&vpp_connect.rfcounter, 1); - if (!rfc) - vpppoe_disconnect_from_vpp(); + if (!rfc) + vpppoe_disconnect_from_vpp(); +} + +static vapi_error_e vpppoe_set_feature_callback(struct vapi_ctx_s *ctx, + void *callback_ctx, + vapi_error_e rv, + bool is_last, + vapi_payload_feature_enable_disable_reply *reply) +{ + if (is_last) + vpp_connect.rcbc -= 1; + return VAPI_OK; } -static vapi_error_e vpppoe_session_add_reply_callback(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_pppoe_add_del_session_reply *reply) +int vpppoe_set_feature(uint32_t ifindex, int is_enabled, const char *feature, const char *arc) { - if (callback_ctx != NULL && reply != NULL) { - uint32_t *sw = (uint32_t *)(callback_ctx); - *sw = reply->sw_if_index; - } + vapi_error_e err; + vapi_msg_feature_enable_disable *req = vapi_alloc_feature_enable_disable(vpp_connect.vapi); + if (req == NULL) + return -1; - return VAPI_OK; + strncpy((char *)req->payload.feature_name, feature, 63); + strncpy((char *)req->payload.arc_name, arc, 63); + req->payload.sw_if_index = ifindex; + req->payload.enable = is_enabled; + + pthread_mutex_lock(&vpp_connect.lock_vpp); + vpp_connect.rcbc += 1; + err = vapi_feature_enable_disable(vpp_connect.vapi, req, vpppoe_set_feature_callback, NULL); + pthread_mutex_unlock(&vpp_connect.lock_vpp); + + return err; } -int vpppoe_pppoe_session_add_del(uint8_t *client_mac, in_addr_t *client_ip, uint16_t session_id, int is_add, uint32_t *out_ifindex) +typedef struct vpppoe_add_pppoe_interface_cb_ctx_t { - vapi_msg_pppoe_add_del_session *req = vapi_alloc_pppoe_add_del_session(vpp_connect.vapi); + uint8_t client_mac[ETH_ALEN]; + in_addr_t client_ip; + uint16_t session_id; + vpppoe_setup_pppoe_interface_ctx_t *callback_ctx; +} vpppoe_add_pppoe_interface_cb_ctx_t; + +int vpppoe_async_add_pppoe_interface_with_callback(vpppoe_add_pppoe_interface_cb_ctx_t *vppoe_callback_ctx); +static void vpppoe_a_add_lcp_pair_triton(vpppoe_add_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx); + +static void vpppoe_a_setup_features_triton(vpppoe_setup_pppoe_interface_ctx_t *vpppoe_callback_ctx) { + vpppoe_set_feature(vpppoe_callback_ctx->ifindex, 0, "ip4-not-enabled", "ip4-unicast"); + vpppoe_set_feature(vpppoe_callback_ctx->ifindex, 0, "ip6-not-enabled", "ip6-unicast"); + triton_context_call(vpppoe_callback_ctx->tctx, (triton_event_func)vpppoe_callback_ctx->callback, vpppoe_callback_ctx); +} + +static vapi_error_e vpppoe_a_lcp_callback(struct vapi_ctx_s *ctx, + void *callback_ctx, + vapi_error_e rv, + bool is_last, + vapi_payload_lcp_itf_pair_add_del_reply *reply) +{ + + if (is_last) + vpp_connect.rcbc -= 1; + + vpppoe_add_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx = (vpppoe_add_pppoe_interface_cb_ctx_t *)callback_ctx; + + if (callback_ctx != NULL && reply != NULL && rv == VAPI_OK) + { + triton_context_call(&vpp_connect.tctx, (triton_event_func)vpppoe_a_setup_features_triton, vpppoe_callback_ctx->callback_ctx); + free(vpppoe_callback_ctx); + } else { + fprintf(stderr, "\e[1;31m --| %s unexpected issue ctx %p reply %p rv %d rcbc %d\e[0m\n", __FUNCTION__, callback_ctx, reply, rv, vpp_connect.rcbc); + if (vpppoe_callback_ctx != NULL) { + + fprintf(stderr, "\e[1;31m --| %s ISSUE during lcp creation sid %d rcbc %d\e[0m\n", __FUNCTION__, vpppoe_callback_ctx->session_id, vpp_connect.rcbc); + + vpppoe_fallback_allocate_and_add_postponed_pppoe_del(vpppoe_callback_ctx->client_mac, &vpppoe_callback_ctx->client_ip, vpppoe_callback_ctx->session_id); + + vpppoe_callback_ctx->callback_ctx->err = rv; + triton_context_call(vpppoe_callback_ctx->callback_ctx->tctx, (triton_event_func)vpppoe_callback_ctx->callback_ctx->callback, vpppoe_callback_ctx->callback_ctx); + free(vpppoe_callback_ctx); + } + } + return rv; +} + +void vpppoe_a_add_lcp_pair_triton(vpppoe_add_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx) { + vapi_error_e err; + vapi_msg_lcp_itf_pair_add_del *req = vapi_alloc_lcp_itf_pair_add_del(vpp_connect.vapi); + + // TODO check logic if (req == NULL) + { + fprintf(stderr, "\e[1;31m --| %s can't allocate lcp add request ifindex %d rcbc %d\e[0m\n", __FUNCTION__, vpppoe_callback_ctx->callback_ctx->ifindex, vpp_connect.rcbc); + return; + } + + snprintf((char *)req->payload.host_if_name, 15, "vppp%d", vpppoe_callback_ctx->callback_ctx->ifindex); + strncpy(vpppoe_callback_ctx->callback_ctx->ifname, (char *)req->payload.host_if_name, 15); + // strncpy((char *)req->payload.host_if_name, host_if_name, 15); + req->payload.sw_if_index = vpppoe_callback_ctx->callback_ctx->ifindex; + req->payload.host_if_type = LCP_API_ITF_HOST_TUN; + req->payload.is_add = 1; + + pthread_mutex_lock(&vpp_connect.lock_vpp); + vpp_connect.rcbc += 1; + err = vapi_lcp_itf_pair_add_del(vpp_connect.vapi, req, vpppoe_a_lcp_callback, vpppoe_callback_ctx); + pthread_mutex_unlock(&vpp_connect.lock_vpp); + + if (err != VAPI_OK) + { + if (vpppoe_callback_ctx != NULL) + { + fprintf(stderr, "\e[1;31m --| %s can't send lcp pair creation request sid %d rcbc %d\e[0m\n", __FUNCTION__, vpppoe_callback_ctx->session_id, vpp_connect.rcbc); + + vpppoe_fallback_allocate_and_add_postponed_pppoe_del(vpppoe_callback_ctx->client_mac, &vpppoe_callback_ctx->client_ip, vpppoe_callback_ctx->session_id); + + vpppoe_callback_ctx->callback_ctx->err = err; + triton_context_call(vpppoe_callback_ctx->callback_ctx->tctx, (triton_event_func)vpppoe_callback_ctx->callback_ctx->callback, vpppoe_callback_ctx->callback_ctx); + free(vpppoe_callback_ctx); + } + } +} + +static vapi_error_e vpppoe_a_session_add_reply_callback(struct vapi_ctx_s *ctx, + void *callback_ctx, + vapi_error_e rv, + bool is_last, + vapi_payload_pppoe_add_del_session_reply *reply) +{ + + if (is_last) + vpp_connect.rcbc -= 1; + + vpppoe_add_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx = (vpppoe_add_pppoe_interface_cb_ctx_t *)callback_ctx; + if (callback_ctx != NULL && reply != NULL && rv == VAPI_OK) + { + vpppoe_callback_ctx->callback_ctx->ifindex = reply->sw_if_index; + if (sc_non_lcp_mode) { + triton_context_call(&vpp_connect.tctx, (triton_event_func)vpppoe_a_setup_features_triton, vpppoe_callback_ctx->callback_ctx); + free(vpppoe_callback_ctx); + } else { + triton_context_call(&vpp_connect.tctx, (triton_event_func)vpppoe_a_add_lcp_pair_triton, vpppoe_callback_ctx); + } + fprintf(stderr, "\e[1;32m --| %s add pppoe session ifindex %d rcbc %d \e[0m\n", __FUNCTION__, vpppoe_callback_ctx->callback_ctx->ifindex, vpp_connect.rcbc); + } else { + fprintf(stderr, "\e[1;31m --| %s unexpected issue ctx %p reply %p rv %d rcbc %d\e[0m\n", __FUNCTION__, callback_ctx, reply, rv, vpp_connect.rcbc); + + if (vpppoe_callback_ctx != NULL) { + + vpppoe_callback_ctx->callback_ctx->err = rv; + triton_context_call(vpppoe_callback_ctx->callback_ctx->tctx, (triton_event_func)vpppoe_callback_ctx->callback_ctx->callback, vpppoe_callback_ctx->callback_ctx); + free(vpppoe_callback_ctx); + } + } + + return rv; +} + +int vpppoe_async_add_pppoe_interface_with_callback(vpppoe_add_pppoe_interface_cb_ctx_t *vppoe_callback_ctx) { + vapi_error_e err; + + vapi_msg_pppoe_add_del_session *req = vapi_alloc_pppoe_add_del_session(vpp_connect.vapi); + if (req == NULL) { + fprintf(stderr, "\e[1;31m --| %s can't allocate pppoe add request session %d rcbc %d\e[0m\n", __FUNCTION__, vppoe_callback_ctx->session_id, vpp_connect.rcbc); + return -1; + } + + vppoe_callback_ctx->callback_ctx->err = 0; + vppoe_callback_ctx->callback_ctx->ifindex = 0; req->payload.client_ip.af = ADDRESS_IP4; - memcpy(req->payload.client_ip.un.ip4, client_ip, sizeof(*client_ip)); - memcpy(req->payload.client_mac, client_mac, ETH_ALEN); + memcpy(req->payload.client_ip.un.ip4, &vppoe_callback_ctx->client_ip, sizeof(vppoe_callback_ctx->client_ip)); + memcpy(req->payload.client_mac, vppoe_callback_ctx->client_mac, ETH_ALEN); - req->payload.is_add = is_add; - req->payload.session_id = session_id; + req->payload.is_add = 1; + req->payload.session_id = vppoe_callback_ctx->session_id; req->payload.disable_fib = 1; - return vapi_pppoe_add_del_session(vpp_connect.vapi, req, vpppoe_session_add_reply_callback, out_ifindex); + pthread_mutex_lock(&vpp_connect.lock_vpp); + vpp_connect.rcbc += 1; + err = vapi_pppoe_add_del_session(vpp_connect.vapi, req, vpppoe_a_session_add_reply_callback, vppoe_callback_ctx); + pthread_mutex_unlock(&vpp_connect.lock_vpp); + + if (err != VAPI_OK) { + if (vppoe_callback_ctx != NULL) { + fprintf(stderr, "\e[1;31m --| %s can't send pppoe creation request sid %d rcbc %d\e[0m\n", __FUNCTION__, vppoe_callback_ctx->session_id, vpp_connect.rcbc); + vppoe_callback_ctx->callback_ctx->err = err; + triton_context_call(vppoe_callback_ctx->callback_ctx->tctx, (triton_event_func)vppoe_callback_ctx->callback_ctx->callback, vppoe_callback_ctx->callback_ctx); + free(vppoe_callback_ctx); + } + } + + return err; } -typedef struct { +int vpppoe_async_add_pppoe_interface(uint8_t *client_mac, in_addr_t *client_ip, uint16_t session_id, vpppoe_setup_pppoe_interface_ctx_t *callback_ctx) +{ + if (vpp_connect.rcbc >= sc_teardown_on_max_queue) { + fprintf(stderr, "\e[1;31m --| %s TOO much request sid %d rcbc %d\e[0m\n", __FUNCTION__, session_id, vpp_connect.rcbc); + callback_ctx->err = -100; + triton_context_call(callback_ctx->tctx, (triton_event_func)callback_ctx->callback, callback_ctx); + return -100; + } + + vpppoe_add_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx = malloc(sizeof(*vpppoe_callback_ctx)); + memset(vpppoe_callback_ctx, 0, sizeof(*vpppoe_callback_ctx)); + + memcpy(&vpppoe_callback_ctx->client_ip, client_ip, sizeof(*client_ip)); + memcpy(vpppoe_callback_ctx->client_mac, client_mac, ETH_ALEN); + vpppoe_callback_ctx->session_id = session_id; + vpppoe_callback_ctx->callback_ctx = callback_ctx; + + return vpppoe_async_add_pppoe_interface_with_callback(vpppoe_callback_ctx); +} + +typedef struct vpppoe_del_pppoe_interface_cb_ctx_t +{ + uint8_t mac[ETH_ALEN]; + in_addr_t client_ip; + uint16_t session_id; uint32_t ifindex; - char *name; - size_t len; -} vpppoe_ifname_by_ifindex_t; - -static vapi_error_e vpppoe_ifname_by_ifindex_reply_callback(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_sw_interface_details *reply) -{ - if (reply && callback_ctx != NULL) { - vpppoe_ifname_by_ifindex_t *ifname = (vpppoe_ifname_by_ifindex_t *)callback_ctx; - if (ifname->ifindex == reply->sw_if_index) { - size_t len = ifname->len > 63 ? 63 : ifname->len; - strncpy(ifname->name, (const char *)reply->interface_name, len); + char ifname[16]; + + /* retry fallback */ + uint32_t retrys; + struct list_head entry; + uint32_t retry_at; /* 0 - from lcp delete routine, 1 - from pppoe session delete routine */ +} vpppoe_del_pppoe_interface_cb_ctx_t; + + +static void vpppoe_async_del_pppoe_interface_with_callback(vpppoe_del_pppoe_interface_cb_ctx_t *callback_ctx); +static void vpppoe_a_del_session_triton(vpppoe_del_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx); + +static void vpppoe_retry_del_later(vpppoe_del_pppoe_interface_cb_ctx_t *ctx) { + ctx->retrys += 1; + vpp_connect.retry_del_count += 1; + list_add_tail(&ctx->entry, &vpp_connect.retry_del_list); +} + +void vpppoe_fallback_allocate_and_add_postponed_pppoe_del(uint8_t *client_mac, in_addr_t *client_ip, uint16_t session_id) { + + vpppoe_del_pppoe_interface_cb_ctx_t *callback_ctx = malloc(sizeof(*callback_ctx)); + memset(callback_ctx, 0, sizeof(*callback_ctx)); + memcpy(&callback_ctx->mac, client_mac, ETH_ALEN); + memcpy(&callback_ctx->client_ip, client_ip, sizeof(*client_ip)); + callback_ctx->session_id = session_id; + + callback_ctx->retry_at = 1; + vpppoe_retry_del_later(callback_ctx); +} + +static void vpppoe_launch_del_retrys(uint32_t count) { + if (vpp_connect.retry_del_count) { + + uint32_t i = 0; + struct list_head *pos, *n; + vpppoe_del_pppoe_interface_cb_ctx_t *callback_ctx; + + list_for_each_safe(pos, n, &vpp_connect.retry_del_list) { + callback_ctx = list_entry(pos, typeof(*callback_ctx), entry); + + vpp_connect.retry_del_count -= 1; + list_del(&callback_ctx->entry); + + fprintf(stderr, "\033[104m --| %s RETRY DEL %d ifname %16s rcbc %d retry %d\e[0m\n", __FUNCTION__, callback_ctx->ifindex, callback_ctx->ifname, vpp_connect.rcbc, vpp_connect.retry_del_count); + + if (callback_ctx->retry_at == 0) + vpppoe_async_del_pppoe_interface_with_callback(callback_ctx); + else + vpppoe_a_del_session_triton(callback_ctx); + + ++i; + if (i > count) { + break; + } } } +} + +static vapi_error_e vpppoe_a_del_session_add_reply_callback(struct vapi_ctx_s *ctx, + void *callback_ctx, + vapi_error_e rv, + bool is_last, + vapi_payload_pppoe_add_del_session_reply *reply) +{ + if (is_last) + vpp_connect.rcbc -= 1; + + vpppoe_del_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx = (vpppoe_del_pppoe_interface_cb_ctx_t *)callback_ctx; + if (callback_ctx && rv == VAPI_OK) { + fprintf(stderr, "\e[1;33m --| %s del pppoe %p %p %d ifindex %d ifname %s rcbc %d \e[0m\n", __FUNCTION__, callback_ctx, reply, rv, vpppoe_callback_ctx->ifindex, vpppoe_callback_ctx->ifname, vpp_connect.rcbc); + free(vpppoe_callback_ctx); + + } else { + fprintf(stderr, "\e[1;31m --| %s some issue in pppoe del - adding to the retry list - responce %d ifindex %d ifname %16s rcbc %d retrys %d\e[0m\n", __FUNCTION__, rv, vpppoe_callback_ctx->ifindex, vpppoe_callback_ctx->ifname, vpp_connect.rcbc, vpp_connect.retry_del_count); + vpppoe_callback_ctx->retry_at = 1; + vpppoe_retry_del_later(vpppoe_callback_ctx); + + } return VAPI_OK; } -int vpppoe_get_sw_ifname_by_index(uint32_t sw_ifindex, char *ifname, size_t len) -{ - vpppoe_ifname_by_ifindex_t ctx; +void vpppoe_a_del_session_triton(vpppoe_del_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx) { - ctx.ifindex = sw_ifindex; - ctx.name = ifname; - ctx.len = len; + vapi_error_e err; - vapi_msg_sw_interface_dump *req = vapi_alloc_sw_interface_dump(vpp_connect.vapi, 0); - if (req == NULL) - return -1; + if (vpp_connect.rcbc >= sc_teardown_on_max_queue) { + fprintf(stderr, "\e[1;31m --| %s TOO much DEL LCP request - add to postpone list sid %d ifindex %d rcbc %d\e[0m\n", __FUNCTION__, vpppoe_callback_ctx->session_id, vpppoe_callback_ctx->ifindex, vpp_connect.rcbc); + vpppoe_callback_ctx->retry_at = 1; + vpppoe_retry_del_later(vpppoe_callback_ctx); + return; + } - req->payload.sw_if_index = sw_ifindex; + vapi_msg_pppoe_add_del_session *req = vapi_alloc_pppoe_add_del_session(vpp_connect.vapi); + if (req == NULL) { + fprintf(stderr, "\e[1;31m --| %s can't allocate pppoe delete request ifindex %d ifname %16s rcbc %d\e[0m\n", __FUNCTION__, vpppoe_callback_ctx->ifindex, vpppoe_callback_ctx->ifname, vpp_connect.rcbc); + return; + } - return vapi_sw_interface_dump(vpp_connect.vapi, req, vpppoe_ifname_by_ifindex_reply_callback, &ctx); -} + req->payload.client_ip.af = ADDRESS_IP4; + memcpy(req->payload.client_ip.un.ip4, &vpppoe_callback_ctx->client_ip, sizeof(vpppoe_callback_ctx->client_ip)); + memcpy(req->payload.client_mac, &vpppoe_callback_ctx->mac, ETH_ALEN); + req->payload.is_add = 0; + req->payload.session_id = vpppoe_callback_ctx->session_id; + // req->payload.disable_fib = 1; -static vapi_error_e vpppoe_lsc_callback(struct vapi_ctx_s *ctx, + + pthread_mutex_lock(&vpp_connect.lock_vpp); + vpp_connect.rcbc += 1; + err = vapi_pppoe_add_del_session(vpp_connect.vapi, req, vpppoe_a_del_session_add_reply_callback, vpppoe_callback_ctx); + pthread_mutex_unlock(&vpp_connect.lock_vpp); + + if (err != VAPI_OK) { + fprintf(stderr, "\e[1;31m --| %s cant SEND pppoe del - adding to the retry list - responce %d ifindex %d ifname %16s rcbc %d retrys %d\e[0m\n", __FUNCTION__, err, vpppoe_callback_ctx->ifindex, vpppoe_callback_ctx->ifname, vpp_connect.rcbc, vpp_connect.retry_del_count); + vpppoe_callback_ctx->retry_at = 1; + vpppoe_retry_del_later(vpppoe_callback_ctx); + } +} + +static vapi_error_e vpppoe_a_del_lcp_callback(struct vapi_ctx_s *ctx, void *callback_ctx, vapi_error_e rv, bool is_last, vapi_payload_lcp_itf_pair_add_del_reply *reply) { + + if (is_last) + vpp_connect.rcbc -= 1; + + vpppoe_del_pppoe_interface_cb_ctx_t *vpppoe_callback_ctx = (vpppoe_del_pppoe_interface_cb_ctx_t *)callback_ctx; + + if (callback_ctx != NULL && rv == VAPI_OK) + { + triton_context_call(&vpp_connect.tctx, (triton_event_func)vpppoe_a_del_session_triton, vpppoe_callback_ctx); + + } else { + fprintf(stderr, "\e[1;31m --| %s unexpected issue ctx %p reply %p rv %d rcbc %d\e[0m\n", __FUNCTION__, callback_ctx, reply, rv, vpp_connect.rcbc); + if (vpppoe_callback_ctx != NULL) { + fprintf(stderr, "\e[1;31m --| %s some issue in lcp del - adding to the retry list - responce %d ifindex %d ifname %16s rcbc %d retrys %d\e[0m\n", __FUNCTION__, rv, vpppoe_callback_ctx->ifindex, vpppoe_callback_ctx->ifname, vpp_connect.rcbc, vpp_connect.retry_del_count); + vpppoe_callback_ctx->retry_at = 0; + vpppoe_retry_del_later(vpppoe_callback_ctx); + + } + } + return VAPI_OK; } -int vpppoe_lcp_tun_add_del(uint32_t ifindex, const char *host_if_name, int is_add) -{ - vapi_msg_lcp_itf_pair_add_del* req = vapi_alloc_lcp_itf_pair_add_del(vpp_connect.vapi); +void vpppoe_async_del_pppoe_interface_with_callback(vpppoe_del_pppoe_interface_cb_ctx_t *callback_ctx) { + + vapi_error_e err; + + if (vpp_connect.rcbc >= sc_teardown_on_max_queue) { + fprintf(stderr, "\e[1;31m --| %s TOO much DEL request - add to postpone list sid %d ifindex %d rcbc %d\e[0m\n", __FUNCTION__, callback_ctx->session_id, callback_ctx->ifindex, vpp_connect.rcbc); + callback_ctx->retry_at = 0; + vpppoe_retry_del_later(callback_ctx); + return; + } + + vapi_msg_lcp_itf_pair_add_del *req = vapi_alloc_lcp_itf_pair_add_del(vpp_connect.vapi); + if (req == NULL) - return -1; + { + fprintf(stderr, "\e[1;31m --| %s can't allocate lcp delete request ifindex %d ifname %16s rcbc %d\e[0m\n", __FUNCTION__, + callback_ctx->ifindex, callback_ctx->ifname, vpp_connect.rcbc); + return; + } - strncpy((char *)req->payload.host_if_name, host_if_name, 15); - req->payload.sw_if_index = ifindex; + strncpy((char *)req->payload.host_if_name, callback_ctx->ifname, 15); + req->payload.sw_if_index = callback_ctx->ifindex; req->payload.host_if_type = LCP_API_ITF_HOST_TUN; - req->payload.is_add = is_add; + req->payload.is_add = 0; + + + pthread_mutex_lock(&vpp_connect.lock_vpp); + vpp_connect.rcbc += 1; + err = vapi_lcp_itf_pair_add_del(vpp_connect.vapi, req, vpppoe_a_del_lcp_callback, callback_ctx); + pthread_mutex_unlock(&vpp_connect.lock_vpp); + + if (err != VAPI_OK) { + fprintf(stderr, "\e[1;31m --| %s cant SEND lcp del - adding to the retry list - responce %d ifindex %d ifname %16s rcbc %d retrys %d\e[0m\n", __FUNCTION__, err, callback_ctx->ifindex, callback_ctx->ifname, vpp_connect.rcbc, vpp_connect.retry_del_count); + callback_ctx->retry_at = 0; + vpppoe_retry_del_later(callback_ctx); + } +} + +void vpppoe_async_del_pppoe_interface(uint8_t *client_mac, in_addr_t *client_ip, uint16_t session_id, uint32_t ifindex, char *ifname) { + vpppoe_del_pppoe_interface_cb_ctx_t *callback_ctx = malloc(sizeof(*callback_ctx)); + memset(callback_ctx, 0, sizeof(*callback_ctx)); + memcpy(&callback_ctx->mac, client_mac, ETH_ALEN); + memcpy(&callback_ctx->client_ip, client_ip, sizeof(*client_ip)); + callback_ctx->session_id = session_id; - return vapi_lcp_itf_pair_add_del(vpp_connect.vapi, req, vpppoe_lsc_callback, NULL); + callback_ctx->ifindex = ifindex; + strncpy((char *)&callback_ctx->ifname, ifname, 15); + + if (sc_non_lcp_mode) { + vpppoe_a_del_session_triton(callback_ctx); + } else { + vpppoe_async_del_pppoe_interface_with_callback(callback_ctx); + } } -static vapi_error_e vpppoe_set_feature_callback(struct vapi_ctx_s *ctx, - void *callback_ctx, - vapi_error_e rv, - bool is_last, - vapi_payload_feature_enable_disable_reply *reply) + +/* NOTE DIRTY HACKS ALL AROUND! */ +int vpppoe_read_events(struct triton_md_handler_t *h) { - return VAPI_OK; + pthread_mutex_lock(&vpp_connect.lock_vpp); + vapi_dispatch(vpp_connect.vapi); + pthread_mutex_unlock(&vpp_connect.lock_vpp); + + return 0; } -int vpppoe_set_feature(uint32_t ifindex, int is_enabled, const char *feature, const char *arc) +void vpppoe_timer(struct triton_timer_t *t) { + + if (vpp_connect.rcbc < sc_fallback_at_rcbc) { + vpppoe_launch_del_retrys(sc_teardown_on_max_queue); + } + /* HACK */ + vpppoe_read_events(NULL); +} + +static void vpppoe_load_config(void) { - vapi_msg_feature_enable_disable* req = vapi_alloc_feature_enable_disable(vpp_connect.vapi); - if (req == NULL) - return -1; + char *opt; + + opt = conf_get_opt("vpp", "queue_size"); + if (opt) + sc_vpp_queue_size = atoi(opt); + + opt = conf_get_opt("vpp", "fallback_timer"); + if (opt) + sc_fallback_timer = atoi(opt); + + opt = conf_get_opt("vpp", "teardown_at_max_requests"); + if (opt) + sc_fallback_at_rcbc = atoi(opt); + + opt = conf_get_opt("vpp", "fallback_requests"); + if (opt) + sc_teardown_on_max_queue = atoi(opt); + + opt = conf_get_opt("vpp", "non_lcp_mode"); + if (opt) + sc_non_lcp_mode = atoi(opt); +} - strncpy((char *)req->payload.feature_name, feature, 63); - strncpy((char *)req->payload.arc_name, arc, 63); - req->payload.sw_if_index = ifindex; - req->payload.enable = is_enabled; +static void vpppoe_init() +{ + memset(&vpp_connect, 0, sizeof(vpp_connect)); + INIT_LIST_HEAD(&vpp_connect.retry_del_list); + pthread_mutex_init(&vpp_connect.lock_vpp, NULL); + + vpppoe_load_config(); - return vapi_feature_enable_disable(vpp_connect.vapi, req, vpppoe_set_feature_callback, NULL); + triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)vpppoe_load_config); } + +DEFINE_INIT(20, vpppoe_init);
\ No newline at end of file |