1/** 2 * \file 3 * \brief This code shall be intantiated as a service within kaluga. 4 * It's main purpose is to have a service where the applications network 5 * stack can requests endpoints of NIC drivers. From the NIC drivers the applicatons 6 * network stack can request to initalized a queue and in turn receives the 7 * resources to manage this queue. 8 * 9 */ 10 11/* 12 * Copyright (c) 2018, ETH Zurich. 13 * All rights reserved. 14 * 15 * This file is distributed under the terms in the attached LICENSE file. 16 * If you do not find this file, copies can be found by writing to: 17 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 18 */ 19 20#include <barrelfish/barrelfish.h> 21#include <barrelfish/nameservice_client.h> 22#include <queue_service/client.h> 23 24#include <if/queue_service_defs.h> 25 26#include "debug.h" 27#include "qs_internal.h" 28 29struct queue_service_client { 30 volatile bool connected; 31 coreid_t core; 32 struct capref* ep; 33 struct queue_service_binding* b; 34}; 35 36 37static void bind_cb(void *st, errval_t err, struct queue_service_binding *b) 38{ 39 struct queue_service_client* q = (struct queue_service_client*) st; 40 assert(err_is_ok(err)); 41 42 b->st = q; 43 q->b = b; 44 queue_service_rpc_client_init(q->b); 45 46 q->connected = true; 47 48 QUEUE_SERVICE_DEBUG("%s:%s:%d: binding done\n", __FILE__, __FUNCTION__, __LINE__); 49} 50 51/** 52 * @brief initializes the queue service client using an endpoint 53 * 54 * @param q returned queue service client state handle 55 * @param ep the queue service endpoint to connect to 56 * 57 * @return SYS_ERR_OK on sucess, errval on failure 58 */ 59 60errval_t queue_service_client_init_with_ep(struct queue_service_client** cl, 61 struct capref* ep) 62{ 63 errval_t err; 64 65 struct queue_service_client* tmp = calloc(sizeof(struct queue_service_client), 1); 66 if (tmp == NULL) { 67 return LIB_ERR_MALLOC_FAIL; 68 } 69 70 if (ep == NULL || capref_is_null(*ep)) { 71 return QSERVICE_ERR_NO_VALID_EP; 72 } 73 74 tmp->connected = false; 75 76 err = queue_service_bind_to_endpoint(*ep, bind_cb, tmp, get_default_waitset(), 77 IDC_BIND_FLAGS_DEFAULT); 78 if (err_is_fail(err)) { 79 goto out; 80 } 81 82 tmp->core = disp_get_core_id(); 83 tmp->ep = ep; 84 85 while(!tmp->connected) { 86 event_dispatch(get_default_waitset()); 87 } 88 89 *cl = tmp; 90 91 return SYS_ERR_OK; 92out: 93 free(cl); 94 return err; 95} 96 97/** 98 * @brief initializes the queue service client using the nameservice 99 * 100 * @param q returned queue service client state handle 101 * 102 * @return SYS_ERR_OK on sucess, errval on failure 103 */ 104errval_t queue_service_client_init(struct queue_service_client** cl) 105{ 106 errval_t err; 107 iref_t iref; 108 109 QUEUE_SERVICE_DEBUG("%s:%s:%d: nameservice lookup\n", __FILE__, __FUNCTION__, __LINE__); 110 111 err = nameservice_blocking_lookup(DEFAULT_SERVICE_NAME, &iref); 112 if (err_is_fail(err)) { 113 return err; 114 } 115 116 struct queue_service_client* tmp = calloc(sizeof(struct queue_service_client), 1); 117 if (tmp == NULL) { 118 return LIB_ERR_MALLOC_FAIL; 119 } 120 121 tmp->core = disp_get_core_id(); 122 tmp->connected = false; 123 124 QUEUE_SERVICE_DEBUG("%s:%s:%d: binding\n", __FILE__, __FUNCTION__, __LINE__); 125 err = queue_service_bind(iref, bind_cb, tmp, get_default_waitset(), 126 IDC_BIND_FLAGS_DEFAULT); 127 if (err_is_fail(err)) { 128 goto out; 129 } 130 131 while(!tmp->connected) { 132 event_dispatch(get_default_waitset()); 133 } 134 135 QUEUE_SERVICE_DEBUG("%s:%s:%d: connected\n", __FILE__, __FUNCTION__, __LINE__); 136 *cl = tmp; 137 138 return SYS_ERR_OK; 139out: 140 free(cl); 141 return err; 142} 143 144/** 145 * @brief requests a endpoint to a NIC by name. Using the endpoint the queue 146 * itself can be initalized. 147 * 148 * @param cl queue service client 149 * @param name name of the service we want an endpont from. 150 * @param ep returned endpoint, slot has to be allocated beforehand 151 * 152 * @return SYS_ERR_OK on sucess, errval on failure 153 */ 154errval_t queue_service_client_request_ep_by_name(struct queue_service_client* cl, 155 char* name, struct capref* ep) 156{ 157 errval_t err, err2; 158 159 if (cl == NULL || cl->b == NULL) { 160 return QSERVICE_ERR_INVALID_CLIENT; 161 } 162 163 if (strlen(name) > MAX_NAME_LEN) { 164 return QSERVICE_ERR_NAME; 165 } 166 167 QUEUE_SERVICE_DEBUG("%s:%s:%d: requesting queue by name %s \n", __FILE__, __FUNCTION__, __LINE__, name); 168 err = cl->b->rpc_tx_vtbl.request_queue_by_name(cl->b, name, cl->core, ep, &err2); 169 if (err_is_fail(err) || err_is_fail(err2)) { 170 err = err_is_fail(err) ? err: err2; 171 goto out; 172 } 173 174 return SYS_ERR_OK; 175out: 176 slot_free(*ep); 177 return err; 178} 179