diff --git a/dpdk/vr_dpdk_filestore.c b/dpdk/vr_dpdk_filestore.c new file mode 100644 index 000000000..4b49af0e1 --- /dev/null +++ b/dpdk/vr_dpdk_filestore.c @@ -0,0 +1,100 @@ +/* + * vr_dpdk_filestore.c - implements a persistent store + * to store/retrieve the VM feature set. + * + * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +#include "vr_dpdk.h" +#define FEATURE_STORE_PATH "/var/lib/contrail/vm_feature" + +int vr_dpdk_store_persist_feature(char *tapdev_name, unsigned long feature_set) +{ + char fname[NAME_MAX]; + struct stat fstat; + FILE *fp; + + if (stat(FEATURE_STORE_PATH, &fstat) != 0) { + if (mkdir(FEATURE_STORE_PATH, 0755) < 0) { + RTE_LOG(ERR, USOCK, "mkdir failed with error %d\n", errno); + return -1; + } + } + + if (snprintf(fname, NAME_MAX, FEATURE_STORE_PATH"/%s", tapdev_name) < 0) + return -1; + + RTE_LOG_DP(DEBUG, USOCK, "Write persistent feature %s\n", fname); + + fp = fopen(fname, "w"); + if (fp == NULL) { + return -1; + } + rewind(fp); + fprintf(fp, "%016lx", feature_set); + fclose(fp); + return 0; +} + +int vr_dpdk_load_persist_feature(char *tapdev_name, unsigned long *feature_set) +{ + char fname[NAME_MAX]; + struct stat fstat; + FILE *fp; + + if (stat(FEATURE_STORE_PATH, &fstat) != 0) { + if (mkdir(FEATURE_STORE_PATH, 0755) < 0) { + RTE_LOG(ERR, USOCK, "mkdir failed with error %d\n", errno); + return -1; + } + } + + if (snprintf(fname, NAME_MAX, FEATURE_STORE_PATH"/%s", tapdev_name) < 0) + return -1; + + RTE_LOG_DP(DEBUG, USOCK, "Read persistent feature %s\n", fname); + + if (stat(fname, &fstat) == 0) { + fp = fopen(fname, "r"); + if (fp == NULL) { + return -1; + } + rewind(fp); + if(fscanf(fp, "%016lx", feature_set) == EOF) { + if (errno) { + RTE_LOG(ERR, USOCK, "EOF reached with error %d for tapdev %s\n", + errno, tapdev_name); + fclose(fp); + return -1; + } + } + RTE_LOG_DP(DEBUG, USOCK, "Feature Set Read %lx for tapdev %s\n", + *feature_set, tapdev_name); + fclose(fp); + return 0; + } else { + return -1; + } +} + +void vr_dpdk_del_persist_feature(char *tapdev_name) +{ + char fname[NAME_MAX]; + struct stat fstat; + + if (snprintf(fname, NAME_MAX, FEATURE_STORE_PATH"/%s", tapdev_name) < 0) + return; + + if (stat(fname, &fstat) == 0) { + if(unlink(fname)) { + RTE_LOG(ERR, USOCK, "Error deleting file %d for tapdev %s\n", + errno, tapdev_name); + } + } +} diff --git a/dpdk/vr_dpdk_filestore.h b/dpdk/vr_dpdk_filestore.h new file mode 100644 index 000000000..db39f4a7b --- /dev/null +++ b/dpdk/vr_dpdk_filestore.h @@ -0,0 +1,15 @@ +/* + * vr_dpdk_filestore.h - header for persistent store + * to store/retrieve the VM feature set. + * + * Copyright (c) 2018 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef __VR_DPDK_FILESTORE_H__ +#define __VR_DPDK_FILESTORE_H__ + +int vr_dpdk_store_persist_feature(char *tapdev_name, unsigned long feature_set); +int vr_dpdk_load_persist_feature(char *tapdev_name, unsigned long *feature_set); +void vr_dpdk_del_persist_feature(char *tapdev_name); + +#endif /* __VR_DPDK_FILESTORE_H__ */ diff --git a/dpdk/vr_uvhost_msg.c b/dpdk/vr_uvhost_msg.c index 4ec989398..05bc289dc 100644 --- a/dpdk/vr_uvhost_msg.c +++ b/dpdk/vr_uvhost_msg.c @@ -13,6 +13,7 @@ #include "vr_uvhost_client.h" #include "vr_uvhost_msg.h" #include "vr_uvhost_util.h" +#include "vr_dpdk_filestore.h" #include #include @@ -355,11 +356,18 @@ vr_uvmh_set_features(vr_uvh_client_t *vru_cl) { struct vr_interface *vif; uint8_t is_gso_vm = 1; + unsigned long stored_features = 0; + + if (!vr_dpdk_load_persist_feature(uvhm_client_name(vru_cl), + &stored_features)) { + vru_cl->vruc_msg.u64 |= stored_features; + } + vr_uvhost_log(" SET FEATURES: 0x%"PRIx64"\n", vru_cl->vruc_msg.u64); vif = __vrouter_get_interface(vrouter_get(0), vru_cl->vruc_idx); - is_gso_vm = (vru_cl->vruc_msg.u64 & (1ULL << VIRTIO_NET_F_GUEST_TSO4)) | + is_gso_vm = (vru_cl->vruc_msg.u64 & (1ULL << VIRTIO_NET_F_GUEST_TSO4)) | (vru_cl->vruc_msg.u64 & (1ULL << VIRTIO_NET_F_HOST_TSO4)) | (vru_cl->vruc_msg.u64 & (1ULL << VIRTIO_NET_F_GUEST_TSO6)) | (vru_cl->vruc_msg.u64 & (1ULL << VIRTIO_NET_F_HOST_TSO6)); @@ -369,9 +377,9 @@ vr_uvmh_set_features(vr_uvh_client_t *vru_cl) */ if (vif) { if (!!is_gso_vm) { - vif->vif_flags |= VIF_FLAG_GRO_NEEDED; + vif->vif_flags |= VIF_FLAG_GRO_NEEDED; } else { - vif->vif_flags &= ~VIF_FLAG_GRO_NEEDED; + vif->vif_flags &= ~VIF_FLAG_GRO_NEEDED; } } @@ -379,9 +387,11 @@ vr_uvmh_set_features(vr_uvh_client_t *vru_cl) vif->vif_flags |= VIF_FLAG_MRG_RXBUF; vr_dpdk_set_vhost_send_func(vru_cl->vruc_idx, 1); } else { - vif->vif_flags &= ~VIF_FLAG_MRG_RXBUF; + vif->vif_flags &= ~VIF_FLAG_MRG_RXBUF; vr_dpdk_set_vhost_send_func(vru_cl->vruc_idx, 0); } + vr_dpdk_store_persist_feature(uvhm_client_name(vru_cl), + vru_cl->vruc_msg.u64); return 0; } @@ -1228,6 +1238,7 @@ vr_uvh_nl_vif_del_handler(vrnu_vif_del_t *msg) } /* Unmmap guest memory. */ uvhm_client_munmap(vru_cl); + vr_dpdk_del_persist_feature(uvhm_client_name(vru_cl)); vr_uvhost_del_client(vru_cl); return 0;