Skip to content

Commit

Permalink
Merge pull request #298 from onmetal/feature/enhance_lpm_table_vnet_p…
Browse files Browse the repository at this point in the history
…eering

Add ResetVni() GRPC function
  • Loading branch information
guvenc authored Jun 12, 2023
2 parents e189663 + 7db47b8 commit aecde57
Show file tree
Hide file tree
Showing 12 changed files with 175 additions and 9 deletions.
1 change: 1 addition & 0 deletions include/dp_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ const char *dp_strerror(int error);
ERR(DEL_PREFIX_ROUTE_ERR, 700) \
ERR(DEL_PREFIX_NO_VM, 701) \
ERR(INIT_RESET_ERR, 710) \
ERR(VNI_TABLE_RESET_ERR, 711) \
ERR(ADD_LB_UNSUPP_IP, 750) \
ERR(ADD_LB_CREATE_ERR, 751) \
ERR(ADD_LB_VNF_ERR, 752) \
Expand Down
1 change: 1 addition & 0 deletions include/dp_lpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ void dp_set_vm_pxe_ip4(uint16_t portid, uint32_t ip, int socketid);
char* dp_get_vm_pxe_str(uint16_t portid);
void dp_set_vm_pxe_str(uint16_t portid, char *p_str);
int dp_lpm_reset_all_route_tables(int socketid);
int dp_lpm_reset_route_tables(int vni, int socketid);
struct dp_fwall_head *dp_get_fwall_head(int port_id);
void dp_set_fwall_head(int port_id, struct dp_fwall_head *fwall_head);
#ifdef __cplusplus
Expand Down
15 changes: 15 additions & 0 deletions include/grpc/dp_async_grpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ class IsVniInUseCall final : BaseCall {
int Proceed() override;
};

class ResetVniCall final : BaseCall {
ServerContext ctx_;
ResetVniRequest request_;
Status reply_;
ServerAsyncResponseWriter<Status> responder_;

public:
ResetVniCall(DPDKonmetal::AsyncService* service, ServerCompletionQueue* cq)
:BaseCall(service, cq, DP_REQ_TYPE_VNI_RESET), responder_(&ctx_) {
service_->RequestresetVni(&ctx_, &request_, &responder_, cq_, cq_,
this);
}
int Proceed() override;
};

class DelLBTargetPfxCall final : BaseCall {
ServerContext ctx_;
DeleteInterfaceLoadBalancerPrefixRequest request_;
Expand Down
1 change: 1 addition & 0 deletions include/grpc/dp_grpc_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ typedef enum {
DP_REQ_TYPE_ADD_NEIGH_NAT,
DP_REQ_TYPE_DEL_NEIGH_NAT,
DP_REQ_TYPE_IS_VNI_IN_USE,
DP_REQ_TYPE_VNI_RESET,
} dp_req_type;

typedef enum {
Expand Down
5 changes: 5 additions & 0 deletions proto/dpdk.proto
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@ message IsVniInUseResponse {
Status status = 2;
}

message ResetVniRequest {
uint32 vni = 1;
VniType type = 2;
}

service DPDKonmetal {
//// INITIALIZATION
Expand Down Expand Up @@ -535,6 +539,7 @@ service DPDKonmetal {
// VNI can be in use by interfaces and by loadbalancer. So get information
// whether the VNI in question is in use or not.
rpc isVniInUse(IsVniInUseRequest) returns (IsVniInUseResponse) {}
rpc resetVni(ResetVniRequest) returns (Status) {}

//// FIREWALL
rpc listFirewallRules(ListFirewallRulesRequest) returns (ListFirewallRulesResponse) {}
Expand Down
49 changes: 40 additions & 9 deletions src/dp_lpm.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ void dp_lpm_free()
dp_free_jhash_table(vm_handle_tbl);
}

int __rte_always_inline dp_lpm_fill_route_tables(int portid, struct vm_entry *entry)
{
if (dp_add_route(portid, entry->vni, 0, entry->info.own_ip, NULL, 32, rte_eth_dev_socket_id(portid))) {
DPS_LOG_ERR("dp_add_route failed during table reset");
return DP_ERROR;
}
if (dp_add_route6(portid, entry->vni, 0, entry->info.dhcp_ipv6, NULL, 128, rte_eth_dev_socket_id(portid))) {
DPS_LOG_ERR("dp_add_route6 failed during table reset");
return DP_ERROR;
}
return DP_OK;
}

int dp_lpm_reset_all_route_tables(int socketid)
{
int i;
Expand All @@ -37,17 +50,35 @@ int dp_lpm_reset_all_route_tables(int socketid)
return DP_ERROR;
}

for (i = 0; i < DP_MAX_PORTS; i++)
if (vm_table[i].vm_ready) {
if (dp_add_route(i, vm_table[i].vni, 0, vm_table[i].info.own_ip, NULL, 32, rte_eth_dev_socket_id(i))) {
DPS_LOG_ERR("dp_add_route failed during table reset");
for (i = 0; i < DP_MAX_PORTS; i++) {
if (vm_table[i].vm_ready)
if (DP_FAILED(dp_lpm_fill_route_tables(i, &vm_table[i])))
return DP_ERROR;
}
if (dp_add_route6(i, vm_table[i].vni, 0, vm_table[i].info.dhcp_ipv6, NULL, 128, rte_eth_dev_socket_id(i))) {
DPS_LOG_ERR("dp_add_route6 failed during table reset");
}

return DP_OK;
}

int dp_lpm_reset_route_tables(int vni, int socketid)
{
int i;

if (DP_FAILED(dp_reset_vni_route_table(vni, DP_IP_PROTO_IPV4, socketid))) {
DPS_LOG_ERR("resetting vni route table failed for vni %d socketid: %d", vni, socketid);
return DP_ERROR;
}

if (DP_FAILED(dp_reset_vni_route_table(vni, DP_IP_PROTO_IPV6, socketid))) {
DPS_LOG_ERR("resetting vni route table failed for vni %d socketid: %d", vni, socketid);
return DP_ERROR;
}

for (i = 0; i < DP_MAX_PORTS; i++) {
if (vm_table[i].vm_ready && (vm_table[i].vni == vni))
if (DP_FAILED(dp_lpm_fill_route_tables(i, &vm_table[i])))
return DP_ERROR;
}
}
}

return DP_OK;
}

Expand Down
44 changes: 44 additions & 0 deletions src/grpc/dp_async_grpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,50 @@ int IsVniInUseCall::Proceed()
return 0;
}

int ResetVniCall::Proceed()
{
dp_request request = {0};
dp_reply reply = {0};

if (status_ == REQUEST) {
new ResetVniCall(service_, cq_);
dp_fill_head(&request.com_head, call_type_, 0, 1);
switch (request_.type())
{
case VniIpv4:
request.vni_in_use.type = DP_VNI_IPV4;
break;
case VniIpv6:
request.vni_in_use.type = DP_VNI_IPV6;
break;
case VniIpv4AndIpv6:
request.vni_in_use.type = DP_VNI_BOTH;
break;
default:
request.vni_in_use.type = DP_VNI_BOTH;
break;
}
request.vni_in_use.vni = request_.vni();
DPGRPC_LOG_INFO("Resetting VNI", DP_LOG_VNI(request.vni_in_use.vni),
DP_LOG_VNI_TYPE(request.vni_in_use.type));
dp_send_to_worker(&request);
status_ = AWAIT_MSG;
return -1;
} else if (status_ == AWAIT_MSG) {
dp_fill_head(&reply.com_head, call_type_, 0, 1);
if (dp_recv_from_worker(&reply))
return -1;

SetErrStatus(&reply_, reply.com_head.err_code);
status_ = FINISH;
responder_.Finish(reply_, ret, this);
} else {
GPR_ASSERT(status_ == FINISH);
delete this;
}
return 0;
}

int BaseCall::InitCheck()
{
GRPCService* grpc_service = dynamic_cast<GRPCService*>(service_);
Expand Down
15 changes: 15 additions & 0 deletions src/grpc/dp_grpc_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,18 @@ static int dp_process_del_fwall_rule(dp_request *req, dp_reply *rep)
return ret;
}

static int dp_process_vni_reset(dp_request *req, dp_reply *rep)
{
if (req->vni_in_use.type == DP_VNI_BOTH) {
if (DP_FAILED(dp_lpm_reset_route_tables(req->vni_in_use.vni, rte_eth_dev_socket_id(dp_port_get_pf0_id())))) {
rep->com_head.err_code = DP_GRPC_ERR_VNI_TABLE_RESET_ERR;
return EXIT_FAILURE;
}
}

return EXIT_SUCCESS;
}

static int dp_process_addvip(dp_request *req, dp_reply *rep)
{
uint8_t ul_addr6[DP_VNF_IPV6_ADDR_SIZE];
Expand Down Expand Up @@ -1144,6 +1156,9 @@ int dp_process_request(struct rte_mbuf *m)
case DP_REQ_TYPE_IS_VNI_IN_USE:
ret = dp_process_vni_in_use(req, &rep);
break;
case DP_REQ_TYPE_VNI_RESET:
ret = dp_process_vni_reset(req, &rep);
break;
case DP_REQ_TYPE_CREATELB:
ret = dp_process_add_lb(req, &rep);
break;
Expand Down
1 change: 1 addition & 0 deletions src/grpc/dp_grpc_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ void GRPCService::HandleRpcs()
new DelFirewallRuleCall(this, cq_.get());
new ListFirewallRulesCall(this, cq_.get());
new IsVniInUseCall(this, cq_.get());
new ResetVniCall(this, cq_.get());

while (true) {
GPR_ASSERT(cq_->Next(&tag, &ok));
Expand Down
6 changes: 6 additions & 0 deletions test/grpc_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,12 @@ def vniinuse(self, vni):
match = re.search(r'(?:^|[\n\r])Vni: '+str(vni)+' is (.*in use)', output)
return match.group(1) == 'in use'

def resetvni(self, vni):
output = self._call(f"--reset_vni --vni {vni}", "")
match = re.search(r'(?:^|[\n\r])Vni: '+str(vni)+' (.*resetted)', output)
return match.group(1) == 'resetted'


@staticmethod
def port_open():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
Expand Down
20 changes: 20 additions & 0 deletions test/test_vni.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,23 @@ def test_vni_existence(prepare_ipv4, grpc_client):
grpc_client.dellb(lb_name)
assert not grpc_client.vniinuse(vni3), \
f"VNI {vni3} should not be in use anymore"


def test_vni_reset(prepare_ipv4, grpc_client):
grpc_client.addinterface(VM4.name, VM4.pci, vni3, VM4.ip, VM4.ipv6)
grpc_client.addroute(vni3, neigh_vni1_ov_ip_route, 0, neigh_vni1_ul_ipv6)


routespec = { "vni": vni3, "prefix": neigh_vni1_ov_ip_route, "nextHop": { "vni": 0, "ip": neigh_vni1_ul_ipv6 } }
routes = grpc_client.listroutes(vni3)
assert routespec in routes, \
"List of routes does not contain the added route"

assert grpc_client.resetvni(vni3), \
f"VNI {vni3} should be resettable"

routes = grpc_client.listroutes(vni3)
assert routespec not in routes, \
"List of routes contains the route although vni resetted"

grpc_client.delinterface(VM4.name)
26 changes: 26 additions & 0 deletions tools/dp_grpc_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ typedef enum {
DP_CMD_DEL_ROUTE,
DP_CMD_GET_ROUTE,
DP_CMD_GET_VNI,
DP_CMD_RESET_VNI,
DP_CMD_ADD_VIP,
DP_CMD_DEL_VIP,
DP_CMD_GET_VIP,
Expand Down Expand Up @@ -167,6 +168,7 @@ static uint32_t priority = 1000;
#define CMD_LINE_OPT_FWALL_ACTION "action"
#define CMD_LINE_OPT_FWALL_PRIO "priority"
#define CMD_LINE_OPT_VNI_IN_USE "vni_in_use"
#define CMD_LINE_OPT_RESET_VNI "reset_vni"

enum {
CMD_LINE_OPT_MIN_NUM = 256,
Expand All @@ -178,6 +180,7 @@ enum {
CMD_LINE_OPT_DEL_ROUTE_NUM,
CMD_LINE_OPT_GET_ROUTE_NUM,
CMD_LINE_OPT_VNI_IN_USE_NUM,
CMD_LINE_OPT_RESET_VNI_NUM,
CMD_LINE_OPT_VNI_NUM,
CMD_LINE_OPT_T_VNI_NUM,
CMD_LINE_OPT_PRIMARY_IPV4_NUM,
Expand Down Expand Up @@ -245,6 +248,7 @@ static const struct option lgopts[] = {
{CMD_LINE_OPT_DEL_ROUTE, 0, 0, CMD_LINE_OPT_DEL_ROUTE_NUM},
{CMD_LINE_OPT_GET_ROUTE, 0, 0, CMD_LINE_OPT_GET_ROUTE_NUM},
{CMD_LINE_OPT_VNI_IN_USE, 0, 0, CMD_LINE_OPT_VNI_IN_USE_NUM},
{CMD_LINE_OPT_RESET_VNI, 0, 0, CMD_LINE_OPT_RESET_VNI_NUM},
{CMD_LINE_OPT_VNI, 1, 0, CMD_LINE_OPT_VNI_NUM},
{CMD_LINE_OPT_T_VNI, 1, 0, CMD_LINE_OPT_T_VNI_NUM},
{CMD_LINE_OPT_PRIMARY_IPV4, 1, 0, CMD_LINE_OPT_PRIMARY_IPV4_NUM},
Expand Down Expand Up @@ -366,6 +370,9 @@ int parse_args(int argc, char **argv)
case CMD_LINE_OPT_VNI_IN_USE_NUM:
command = DP_CMD_GET_VNI;
break;
case CMD_LINE_OPT_RESET_VNI_NUM:
command = DP_CMD_RESET_VNI;
break;
case CMD_LINE_OPT_VNI_NUM:
strncpy(vni_str, optarg, 29);
vni = atoi(vni_str);
Expand Down Expand Up @@ -716,6 +723,21 @@ class GRPCClient {
printf("Vni: %d is not in use\n", vni);
}

void ResetVni() {
ResetVniRequest request;
Status reply;
ClientContext context;

request.set_vni(vni);
request.set_type(dpdkonmetal::VniIpv4AndIpv6);

stub_->resetVni(&context, request, &reply);
if (reply.error())
printf("Received an error %d\n", reply.error());
else
printf("Vni: %d resetted\n", vni);
}

void AddLBVIP() {
AddLoadBalancerTargetRequest request;
Status reply;
Expand Down Expand Up @@ -1477,6 +1499,10 @@ int main(int argc, char** argv)
std::cout << "IsVniInUse called " << std::endl;
dpdk_client.VniInUse();
break;
case DP_CMD_RESET_VNI:
std::cout << "ResetVni called " << std::endl;
dpdk_client.ResetVni();
break;
case DP_CMD_DEL_ROUTE:
dpdk_client.DelRoute();
std::cout << "Delroute called " << std::endl;
Expand Down

0 comments on commit aecde57

Please sign in to comment.