From 4dd729fef4290638a4550fc199993c6b3d517648 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 29 Jan 2023 15:25:53 +0800 Subject: [PATCH 001/105] add/update agent about socket message --- include/conf/dest.h | 13 + include/conf/flow.h | 9 +- include/conf/inetaddr.h | 21 +- include/conf/laddr.h | 20 ++ include/conf/route.h | 15 +- include/conf/service.h | 9 +- include/conf/sockopts.h | 256 +++++++------- include/ctrl.h | 8 + include/ipvs/service.h | 1 + src/ctrl.c | 30 +- src/inetaddr.c | 282 +++++++++++++-- src/ipv6/route6.c | 58 ++- src/ipv6/route6_hlist.c | 10 +- src/ipv6/route6_lpm.c | 8 +- src/ipvs/ip_vs_dest.c | 334 +++++++++++++++++- src/ipvs/ip_vs_laddr.c | 323 ++++++++++++++++- src/ipvs/ip_vs_service.c | 134 ++++++- src/ipvs/ip_vs_xmit.c | 2 +- src/route.c | 146 ++++---- src/sa_pool.c | 2 +- tools/dpip/route.c | 108 +++--- .../keepalived/keepalived/vrrp/vrrp_iproute.c | 4 +- 22 files changed, 1435 insertions(+), 358 deletions(-) diff --git a/include/conf/dest.h b/include/conf/dest.h index 932fe6ef3..36fadde09 100644 --- a/include/conf/dest.h +++ b/include/conf/dest.h @@ -90,8 +90,21 @@ typedef struct dp_vs_dest_table { dpvs_dest_compat_t entrytable[0]; } dpvs_dest_table_t; +typedef struct dp_vs_dest_front { + uint32_t af; + uint16_t proto; + uint16_t port; + uint32_t fwmark; + union inet_addr addr; + unsigned int num_dests; + struct dp_vs_match match; + uint32_t cid; + uint32_t index; +} dpvs_dest_front_t; + #define dp_vs_get_dests dp_vs_dest_table #define dp_vs_dest_entry dp_vs_dest_compat #define dp_vs_dest_conf dp_vs_dest_compat +#define dp_vs_dest_detail dp_vs_dest_compat #endif /* __DPVS_DEST_CONF_H__ */ diff --git a/include/conf/flow.h b/include/conf/flow.h index b4294e6b0..b9cb1d761 100644 --- a/include/conf/flow.h +++ b/include/conf/flow.h @@ -26,6 +26,7 @@ #define __DPVS_FLOW_CONF_H__ #include +#include "inet.h" /* linux:include/uapi/route.h */ #define RTF_UP 0x0001 /* route usable */ @@ -47,9 +48,9 @@ #define RTF_KNI 0X2000 #define RTF_OUTWALL 0x4000 -struct rt6_prefix { - struct in6_addr addr; - int plen; -}; +typedef struct rt6_prefix { + union inet_addr addr; + int plen; /*prefix len*/ +} rt_addr_t; #endif /* __DPVS_FLOW_CONF_H__ */ diff --git a/include/conf/inetaddr.h b/include/conf/inetaddr.h index 726964fbb..7f9eb5abc 100644 --- a/include/conf/inetaddr.h +++ b/include/conf/inetaddr.h @@ -50,15 +50,16 @@ typedef enum ifaddr_ops { struct inet_addr_entry { int af; + uint32_t valid_lft; + uint32_t prefered_lft; + uint32_t flags; char ifname[IFNAMSIZ]; - union inet_addr addr; union inet_addr bcast; + union inet_addr addr; uint8_t plen; uint8_t scope; lcoreid_t cid; - uint32_t valid_lft; - uint32_t prefered_lft; - uint32_t flags; + uint8_t nop; } __attribute__((__packed__)); struct inet_addr_stats { @@ -85,4 +86,16 @@ struct inet_addr_data_array { struct inet_addr_data addrs[0]; } __attribute__((__packed__)); +struct inet_addr_stats_detail { + union inet_addr addr; + uint32_t sa_used; + uint32_t sa_free; + uint32_t sa_miss; +}; + +struct inet_addr_front { + int count; + int data[0]; +}; + #endif /* __DPVS_INETADDR_CONF_H__ */ diff --git a/include/conf/laddr.h b/include/conf/laddr.h index 58b08c491..bebe51b4e 100644 --- a/include/conf/laddr.h +++ b/include/conf/laddr.h @@ -56,4 +56,24 @@ typedef struct dp_vs_laddr_conf { struct dp_vs_laddr_entry laddrs[0]; } dpvs_laddr_table_t; +typedef struct dp_vs_laddr_detail { + uint32_t af; + uint32_t conns; + uint64_t nport_conflict; + union inet_addr addr; + char ifname[IFNAMSIZ]; +} dpvs_laddr_detail_t; + +typedef struct dp_vs_laddr_front { + uint32_t af; + uint32_t port; + uint32_t proto; + uint32_t fwmark; + uint32_t cid; + uint32_t count; + union inet_addr addr; + struct dp_vs_match match; + struct dp_vs_laddr_detail laddrs[0]; +} dpvs_laddr_front_t; + #endif /* __DPVS_LADDR_CONF_H__ */ diff --git a/include/conf/route.h b/include/conf/route.h index 73dec69bb..20839b20c 100644 --- a/include/conf/route.h +++ b/include/conf/route.h @@ -22,6 +22,7 @@ #ifndef __DPVS_ROUTE_CONF_H__ #define __DPVS_ROUTE_CONF_H__ +#include "flow.h" #include "inet.h" #include "net/if.h" #include "conf/sockopts.h" @@ -62,9 +63,21 @@ struct dp_vs_route_conf { int32_t outwalltb; } __attribute__((__packed__)); +typedef struct dp_vs_route_detail { + uint32_t af; + uint32_t mtu; + uint32_t flags; + uint32_t metric; + rt_addr_t dst; + rt_addr_t src; + rt_addr_t gateway; + rt_addr_t prefsrc; + char ifname[IFNAMSIZ]; +} dpvs_route_detail_t; + struct dp_vs_route_conf_array { int nroute; - struct dp_vs_route_conf routes[0]; + struct dp_vs_route_detail routes[0]; } __attribute__((__packed__)); #endif /* __DPVS_ROUTE_CONF_H__ */ diff --git a/include/conf/service.h b/include/conf/service.h index 8ed2d7db2..ae812e3ff 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -77,10 +77,17 @@ typedef struct dp_vs_service_compat { typedef struct dp_vs_services_table { lcoreid_t cid; lcoreid_t index; - unsigned int num_services; + unsigned int num_services; dpvs_service_compat_t entrytable[0]; } dpvs_service_table_t; +typedef struct dp_vs_agent_services_front { + uint8_t cid; + uint8_t index; + uint16_t count; + dpvs_service_compat_t entrytable[0]; +} dpvs_agent_services_front_t; + struct dp_vs_getinfo { unsigned int version; unsigned int size; diff --git a/include/conf/sockopts.h b/include/conf/sockopts.h index 3313b9937..36067053e 100644 --- a/include/conf/sockopts.h +++ b/include/conf/sockopts.h @@ -20,129 +20,141 @@ #include -enum { - /* laddr */ - SOCKOPT_SET_LADDR_ADD = 100, - SOCKOPT_SET_LADDR_DEL, - SOCKOPT_SET_LADDR_FLUSH, - SOCKOPT_GET_LADDR_GETALL = 100, -#define SOCKOPT_LADDR_BASE SOCKOPT_SET_LADDR_ADD -#define SOCKOPT_GET_LADDR_MAX 199 +#define ENUM_ITEM(ITEM) ITEM, +#define ENUM_STRING(ITEM) #ITEM, + +#define DPVSMSG_SOCKOPT_ENUM(DPVSMSG) \ + DPVSMSG(SOCKOPT_SET_LADDR_ADD) \ + DPVSMSG(SOCKOPT_SET_LADDR_DEL) \ + DPVSMSG(SOCKOPT_SET_LADDR_FLUSH) \ + DPVSMSG(SOCKOPT_GET_LADDR_GETALL) \ + DPVSMSG(SOCKOPT_GET_LADDR_MAX) \ + \ + DPVSMSG(DPVSAGENT_VS_GET_LADDR) \ + DPVSMSG(DPVSAGENT_VS_ADD_LADDR) \ + DPVSMSG(DPVSAGENT_VS_DEL_LADDR) \ + \ + DPVSMSG(DPVS_SO_SET_FLUSH) \ + DPVSMSG(DPVS_SO_SET_ZERO) \ + DPVSMSG(DPVS_SO_SET_ADD) \ + DPVSMSG(DPVS_SO_SET_EDIT) \ + DPVSMSG(DPVS_SO_SET_DEL) \ + DPVSMSG(DPVS_SO_SET_ADDDEST) \ + DPVSMSG(DPVS_SO_SET_EDITDEST) \ + DPVSMSG(DPVS_SO_SET_DELDEST) \ + DPVSMSG(DPVS_SO_SET_GRATARP) \ + DPVSMSG(DPVS_SO_GET_VERSION) \ + DPVSMSG(DPVS_SO_GET_INFO) \ + DPVSMSG(DPVS_SO_GET_SERVICES) \ + DPVSMSG(DPVS_SO_GET_SERVICE) \ + DPVSMSG(DPVS_SO_GET_DESTS) \ + DPVSMSG(DPVSAGENT_SO_GET_SERVICES) \ + DPVSMSG(SOCKOPT_SVC_MAX) \ + \ + DPVSMSG(DPVSAGENT_VS_GET_DESTS) \ + DPVSMSG(DPVSAGENT_VS_ADD_DESTS) \ + DPVSMSG(DPVSAGENT_VS_DEL_DESTS) \ + \ + DPVSMSG(DPVSAGENT_ROUTE_GET) \ + DPVSMSG(DPVSAGENT_ROUTE_ADD) \ + DPVSMSG(DPVSAGENT_ROUTE_DEL) \ + DPVSMSG(DPVSAGENT_ROUTE6_GET) \ + DPVSMSG(DPVSAGENT_ROUTE6_ADD) \ + DPVSMSG(DPVSAGENT_ROUTE6_DEL) \ + \ + DPVSMSG(DPVSAGENT_IFADDR_GET_BASE) \ + DPVSMSG(DPVSAGENT_IFADDR_GET_STATS) \ + DPVSMSG(DPVSAGENT_IFADDR_GET_VERBOSE) \ + DPVSMSG(DPVSAGENT_IFADDR_ADD) \ + DPVSMSG(DPVSAGENT_IFADDR_DEL) \ + \ + DPVSMSG(SOCKOPT_SET_ROUTE_ADD) \ + DPVSMSG(SOCKOPT_SET_ROUTE_DEL) \ + DPVSMSG(SOCKOPT_SET_ROUTE_SET) \ + DPVSMSG(SOCKOPT_SET_ROUTE_FLUSH)\ + DPVSMSG(SOCKOPT_GET_ROUTE_SHOW) \ + \ + DPVSMSG(SOCKOPT_SET_IFADDR_ADD) \ + DPVSMSG(SOCKOPT_SET_IFADDR_DEL) \ + DPVSMSG(SOCKOPT_SET_IFADDR_SET) \ + DPVSMSG(SOCKOPT_SET_IFADDR_FLUSH) \ + DPVSMSG(SOCKOPT_GET_IFADDR_SHOW) \ + \ + DPVSMSG(SOCKOPT_NETIF_SET_LCORE) \ + DPVSMSG(SOCKOPT_NETIF_SET_PORT) \ + DPVSMSG(SOCKOPT_NETIF_SET_BOND) \ + DPVSMSG(SOCKOPT_NETIF_SET_MAX) \ + DPVSMSG(SOCKOPT_NETIF_GET_LCORE_MASK) \ + DPVSMSG(SOCKOPT_NETIF_GET_LCORE_BASIC) \ + DPVSMSG(SOCKOPT_NETIF_GET_LCORE_STATS) \ + DPVSMSG(SOCKOPT_NETIF_GET_PORT_LIST) \ + DPVSMSG(SOCKOPT_NETIF_GET_PORT_BASIC) \ + DPVSMSG(SOCKOPT_NETIF_GET_PORT_STATS) \ + DPVSMSG(SOCKOPT_NETIF_GET_PORT_EXT_INFO) \ + DPVSMSG(SOCKOPT_NETIF_GET_BOND_STATUS) \ + DPVSMSG(SOCKOPT_NETIF_GET_MAX) \ + \ + DPVSMSG(SOCKOPT_SET_NEIGH_ADD) \ + DPVSMSG(SOCKOPT_SET_NEIGH_DEL) \ + DPVSMSG(SOCKOPT_GET_NEIGH_SHOW) \ + \ + DPVSMSG(SOCKOPT_SET_BLKLST_ADD) \ + DPVSMSG(SOCKOPT_SET_BLKLST_DEL) \ + DPVSMSG(SOCKOPT_SET_BLKLST_FLUSH) \ + DPVSMSG(SOCKOPT_GET_BLKLST_GETALL) \ + \ + DPVSMSG(SOCKOPT_SET_WHTLST_ADD) \ + DPVSMSG(SOCKOPT_SET_WHTLST_DEL) \ + DPVSMSG(SOCKOPT_SET_WHTLST_FLUSH) \ + DPVSMSG(SOCKOPT_GET_WHTLST_GETALL) \ + \ + DPVSMSG(SOCKOPT_SET_VLAN_ADD) \ + DPVSMSG(SOCKOPT_SET_VLAN_DEL) \ + DPVSMSG(SOCKOPT_GET_VLAN_SHOW) \ + \ + DPVSMSG(SOCKOPT_TC_ADD) \ + DPVSMSG(SOCKOPT_TC_DEL) \ + DPVSMSG(SOCKOPT_TC_CHANGE) \ + DPVSMSG(SOCKOPT_TC_REPLACE) \ + DPVSMSG(SOCKOPT_TC_SHOW) \ + \ + DPVSMSG(SOCKOPT_SET_CONN) \ + DPVSMSG(SOCKOPT_GET_CONN_ALL) \ + DPVSMSG(SOCKOPT_GET_CONN_SPECIFIED) \ + \ + DPVSMSG(SOCKOPT_IP6_SET) \ + DPVSMSG(SOCKOPT_IP6_STATS) \ + \ + DPVSMSG(SOCKOPT_TUNNEL_ADD) \ + DPVSMSG(SOCKOPT_TUNNEL_DEL) \ + DPVSMSG(SOCKOPT_TUNNEL_CHANGE) \ + DPVSMSG(SOCKOPT_TUNNEL_REPLACE) \ + DPVSMSG(SOCKOPT_TUNNEL_SHOW) \ + \ + DPVSMSG(SOCKOPT_SET_KNI_ADD) \ + DPVSMSG(SOCKOPT_SET_KNI_DEL) \ + DPVSMSG(SOCKOPT_SET_KNI_FLUSH) \ + DPVSMSG(SOCKOPT_GET_KNI_LIST) \ + \ + DPVSMSG(SOCKOPT_SET_IPSET) \ + DPVSMSG(SOCKOPT_GET_IPSET_TEST) \ + DPVSMSG(SOCKOPT_GET_IPSET_LIST) \ + \ + DPVSMSG(SOCKOPT_SET_ROUTE6_ADD_DEL) \ + DPVSMSG(SOCKOPT_SET_ROUTE6_FLUSH) \ + DPVSMSG(SOCKOPT_GET_ROUTE6_SHOW) \ + \ + DPVSMSG(SOCKOPT_SET_IFTRAF_ADD) \ + DPVSMSG(SOCKOPT_SET_IFTRAF_DEL) \ + DPVSMSG(SOCKOPT_GET_IFTRAF_SHOW)\ + +typedef enum { + DPVSMSG_SOCKOPT_ENUM(ENUM_ITEM) +}SOCKOPT_CODE; - /* service */ - DPVS_SO_SET_FLUSH = 200, - DPVS_SO_SET_ZERO, - DPVS_SO_SET_ADD, - DPVS_SO_SET_EDIT, - DPVS_SO_SET_DEL, - DPVS_SO_SET_ADDDEST, - DPVS_SO_SET_EDITDEST, - DPVS_SO_SET_DELDEST, - DPVS_SO_SET_GRATARP, - DPVS_SO_GET_VERSION = 200, - DPVS_SO_GET_INFO, - DPVS_SO_GET_SERVICES, - DPVS_SO_GET_SERVICE, - DPVS_SO_GET_DESTS, +#define SOCKOPT_LADDR_BASE SOCKOPT_SET_LADDR_ADD #define SOCKOPT_SVC_BASE DPVS_SO_SET_FLUSH -#define SOCKOPT_SVC_SET_CMD_MAX DPVS_SO_SET_GRATARP -#define SOCKOPT_SVC_GET_CMD_MAX DPVS_SO_GET_DESTS -#define SOCKOPT_SVC_MAX 299 - - /* route */ - SOCKOPT_SET_ROUTE_ADD = 300, - SOCKOPT_SET_ROUTE_DEL, - SOCKOPT_SET_ROUTE_SET, - SOCKOPT_SET_ROUTE_FLUSH, - SOCKOPT_GET_ROUTE_SHOW = 300, - - /* ifaddr */ - SOCKOPT_SET_IFADDR_ADD = 400, - SOCKOPT_SET_IFADDR_DEL, - SOCKOPT_SET_IFADDR_SET, - SOCKOPT_SET_IFADDR_FLUSH, - SOCKOPT_GET_IFADDR_SHOW = 400, - - /* netif */ - SOCKOPT_NETIF_SET_LCORE = 500, - SOCKOPT_NETIF_SET_PORT, - SOCKOPT_NETIF_SET_BOND, - SOCKOPT_NETIF_SET_MAX, - SOCKOPT_NETIF_GET_LCORE_MASK = 500, - SOCKOPT_NETIF_GET_LCORE_BASIC, - SOCKOPT_NETIF_GET_LCORE_STATS, - SOCKOPT_NETIF_GET_PORT_LIST, - SOCKOPT_NETIF_GET_PORT_BASIC, - SOCKOPT_NETIF_GET_PORT_STATS, - SOCKOPT_NETIF_GET_PORT_EXT_INFO, - SOCKOPT_NETIF_GET_BOND_STATUS, - SOCKOPT_NETIF_GET_MAX, - - /* neigh */ - SOCKOPT_SET_NEIGH_ADD = 600, - SOCKOPT_SET_NEIGH_DEL, - SOCKOPT_GET_NEIGH_SHOW = 600, - - /* blklst */ - SOCKOPT_SET_BLKLST_ADD = 700, - SOCKOPT_SET_BLKLST_DEL, - SOCKOPT_SET_BLKLST_FLUSH, - SOCKOPT_GET_BLKLST_GETALL = 700, - - /* vlan */ - SOCKOPT_SET_VLAN_ADD = 800, - SOCKOPT_SET_VLAN_DEL, - SOCKOPT_GET_VLAN_SHOW = 800, - - /* tc */ - SOCKOPT_TC_ADD = 900, - SOCKOPT_TC_DEL, - SOCKOPT_TC_CHANGE, - SOCKOPT_TC_REPLACE, - SOCKOPT_TC_SHOW = 900, - - /* connection */ - SOCKOPT_SET_CONN = 1000, - SOCKOPT_GET_CONN_ALL = 1000, - SOCKOPT_GET_CONN_SPECIFIED, - - /* ip6 */ - SOCKOPT_IP6_SET = 1100, - SOCKOPT_IP6_STATS = 1100, - - /* tunnel */ - SOCKOPT_TUNNEL_ADD = 1200, - SOCKOPT_TUNNEL_DEL, - SOCKOPT_TUNNEL_CHANGE, - SOCKOPT_TUNNEL_REPLACE, - SOCKOPT_TUNNEL_SHOW = 1200, - - /* whtlst */ - SOCKOPT_SET_WHTLST_ADD = 1300, - SOCKOPT_SET_WHTLST_DEL, - SOCKOPT_SET_WHTLST_FLUSH, - SOCKOPT_GET_WHTLST_GETALL = 1300, - - /* kni */ - SOCKOPT_SET_KNI_ADD = 1400, - SOCKOPT_SET_KNI_DEL, - SOCKOPT_SET_KNI_FLUSH, - SOCKOPT_GET_KNI_LIST = 1400, - - /* ipset */ - SOCKOPT_SET_IPSET = 3300, - SOCKOPT_GET_IPSET_TEST = 3300, - SOCKOPT_GET_IPSET_LIST, - - /* route6 */ - SOCKOPT_SET_ROUTE6_ADD_DEL = 6300, - SOCKOPT_SET_ROUTE6_FLUSH, - SOCKOPT_GET_ROUTE6_SHOW = 6300, - - /* iftraf */ - SOCKOPT_SET_IFTRAF_ADD = 6400, - SOCKOPT_SET_IFTRAF_DEL, - SOCKOPT_GET_IFTRAF_SHOW = 6400, -}; +#define SOCKOPT_SVC_GET_CMD_MAX SOCKOPT_SVC_MAX +#define SOCKOPT_SVC_SET_CMD_MAX SOCKOPT_SVC_MAX #endif /* __DPVS_SOCKOPTS_CONF_H__ */ diff --git a/include/ctrl.h b/include/ctrl.h index 98f652395..9162bdea1 100644 --- a/include/ctrl.h +++ b/include/ctrl.h @@ -20,6 +20,7 @@ #include "global_data.h" #include "conf/common.h" +#include "conf/sockopts.h" #include "list.h" #include "dpdk.h" @@ -229,8 +230,15 @@ enum { MSG_TYPE_SVC_GET_SERVICES, MSG_TYPE_SVC_GET_SERVICE, MSG_TYPE_SVC_GET_DESTS, + MSG_TYPE_AGENT_GET_DESTS, MSG_TYPE_LADDR_GET_ALL, + MSG_TYPE_AGENT_GET_LADDR, + MSG_TYPE_AGENT_ADD_LADDR, + MSG_TYPE_AGENT_DEL_LADDR, + MSG_TYPE_AGENT_ADD_DESTS, + MSG_TYPE_AGENT_DEL_DESTS, }; + #define MSG_TYPE_SVC_SET_BASE MSG_TYPE_SVC_SET_FLUSH #define MSG_TYPE_SVC_GET_BASE MSG_TYPE_SVC_GET_INFO #define MSG_TYPE_SET_LADDR_BASE MSG_TYPE_LADDR_SET_ADD diff --git a/include/ipvs/service.h b/include/ipvs/service.h index d4b7b56ed..1b8328fd0 100644 --- a/include/ipvs/service.h +++ b/include/ipvs/service.h @@ -110,5 +110,6 @@ void dp_vs_service_put(struct dp_vs_service *svc); struct dp_vs_service *dp_vs_vip_lookup(int af, uint16_t protocol, const union inet_addr *vaddr, lcoreid_t cid); +void dp_vs_copy_udest_compat(struct dp_vs_dest_conf *udest, dpvs_dest_compat_t *udest_compat); #endif /* __DPVS_SVC_H__ */ diff --git a/src/ctrl.c b/src/ctrl.c index 89c59c8dc..0be8e5f17 100644 --- a/src/ctrl.c +++ b/src/ctrl.c @@ -42,6 +42,10 @@ static int g_msg_timeout = MSG_TIMEOUT_US; static uint8_t g_msg_prio = MSG_PRIO_LOW; +const char* dpvs_sockopts_name[] = { + DPVSMSG_SOCKOPT_ENUM(ENUM_STRING) +}; + #define DPVS_MT_BITS 8 #define DPVS_MT_LEN (1 << DPVS_MT_BITS) #define DPVS_MT_MASK (DPVS_MT_LEN - 1) @@ -1223,9 +1227,9 @@ int sockopt_register(struct dpvs_sockopts *sockopts) if (sockopts_exist(sockopts)) { RTE_LOG(WARNING, MSGMGR, "%s: socket msg type already exist\n", __func__); rte_exit(EXIT_FAILURE, "sockopt type already exist ->\n" - "\t\tget: %d - %d\n\t\tset: %d - %d\n", - sockopts->get_opt_min, sockopts->get_opt_max, - sockopts->set_opt_min, sockopts->set_opt_max); + "\t\tget: %s - %s\n\t\tset: %s - %s\n", + dpvs_sockopts_name[sockopts->get_opt_min], dpvs_sockopts_name[sockopts->get_opt_max], + dpvs_sockopts_name[sockopts->set_opt_min], dpvs_sockopts_name[sockopts->set_opt_max]); return EDPVS_EXIST; } @@ -1287,8 +1291,8 @@ static inline int sockopt_msg_recv(int clt_fd, struct dpvs_sock_msg **pmsg) if (msg_hdr.len > 0) { res = readn(clt_fd, msg->data, msg->len); if (res != msg->len) { - RTE_LOG(WARNING, MSGMGR, "%s: sockopt msg body recv fail -- " - "%d/%d recieved\n", __func__, res, (int)msg->len); + RTE_LOG(WARNING, MSGMGR, "%s: sockopt[%s] msg body recv fail -- " + "%d/%d recieved\n", __func__, dpvs_sockopts_name[msg->id], res, (int)msg->len); rte_free(msg); *pmsg = NULL; return EDPVS_IO; @@ -1316,22 +1320,22 @@ static int sockopt_msg_send(int clt_fd, len = sizeof(struct dpvs_sock_msg_reply); res = sendn(clt_fd, hdr, len, MSG_NOSIGNAL); if (len != res) { - RTE_LOG(WARNING, MSGMGR, "[%s:msg#%d] sockopt reply msg header send error" - " -- %d/%d sent\n", __func__, hdr->id, res, len); + RTE_LOG(WARNING, MSGMGR, "[%s:msg#%s] sockopt reply msg header send error" + " -- %d/%d sent\n", __func__, dpvs_sockopts_name[hdr->id], res, len); return EDPVS_IO; } if (hdr->errcode) { - RTE_LOG(DEBUG, MSGMGR, "[%s:msg#%d] errcode set in sockopt msg reply: %s\n", - __func__, hdr->id, dpvs_strerror(hdr->errcode)); + RTE_LOG(DEBUG, MSGMGR, "[%s:msg#%s] errcode set in sockopt msg reply: %s\n", + __func__, dpvs_sockopts_name[hdr->id], dpvs_strerror(hdr->errcode)); return hdr->errcode; } if (data_len) { res = sendn(clt_fd, data, data_len, MSG_NOSIGNAL); if (data_len != res) { - RTE_LOG(WARNING, MSGMGR, "[%s:msg#%d] sockopt reply msg body send error" - " -- %d/%d sent\n", __func__, hdr->id, res, data_len); + RTE_LOG(WARNING, MSGMGR, "[%s:msg#%s] sockopt reply msg body send error" + " -- %d/%d sent\n", __func__, dpvs_sockopts_name[hdr->id], res, data_len); return EDPVS_IO; } } @@ -1381,8 +1385,8 @@ static int sockopt_ctl(__rte_unused void *arg) reply_data = NULL; reply_data_len = 0; #ifdef CONFIG_MSG_DEBUG - RTE_LOG(INFO, MSGMGR, "%s: socket msg callback failed\n", - __func__, msg->type == SOCKOPT_GET ? "GET" : "SET", msg->id); + RTE_LOG(INFO, MSGMGR, "%s: socket msg callback failed\n", + __func__, msg->type == SOCKOPT_GET ? "GET" : "SET", dpvs_sockopts_name[msg->id]); #endif } diff --git a/src/inetaddr.c b/src/inetaddr.c index 981cc7d96..53e1281c6 100644 --- a/src/inetaddr.c +++ b/src/inetaddr.c @@ -1121,6 +1121,53 @@ static void fill_ifaddr_entry(lcoreid_t cid, const struct inet_ifaddr *ifa, stru } } +static void fill_ifaddr_basic(lcoreid_t cid, const struct inet_ifaddr *ifa, struct inet_addr_entry *entry) +{ + entry->af = ifa->af; + entry->addr = ifa->addr; + entry->bcast = ifa->bcast; + entry->plen = ifa->plen; + entry->scope = ifa->scope; + entry->cid = cid; + entry->flags = ifa->flags; + entry->valid_lft = 0; + entry->prefered_lft = 0; + snprintf(entry->ifname, sizeof(entry->ifname), "%.15s", ifa->idev->dev->name); + if (!(ifa->flags & IFA_F_PERMANENT)) { + struct timeval now, diff; + dpvs_time_now(&now, rte_lcore_id() == rte_get_main_lcore()); + timersub(&now, &ifa->tstemp, &diff); + entry->valid_lft = ifa->valid_lft - diff.tv_sec; + entry->prefered_lft = ifa->prefered_lft - diff.tv_sec; + } +} + +static int agent_copy_lcore_entries(const struct inet_device *idev, struct inet_addr_entry *entries, int cnt) { + int hash, off = 0; + struct inet_ifaddr *ifa; + struct inet_addr_entry *entry; + lcoreid_t cid = rte_lcore_id(); + + if (idev) { + list_for_each_entry(ifa, &idev->ifa_list[cid], d_list) { + entry = entries + off; + fill_ifaddr_basic(cid, ifa, entry); + if (++off == cnt) + break; + } + } else { + for (hash = 0; hash < INET_ADDR_HSIZE; hash++) { + list_for_each_entry(ifa, &inet_addr_tab[cid][hash], h_list) { + entry = entries + off; + fill_ifaddr_basic(cid, ifa, entry); + if (++off == cnt) + break; + } + } + } + return EDPVS_OK; +} + static int copy_lcore_entries(const struct inet_device *idev, int max_entries, struct inet_addr_data_array *array) { @@ -1479,6 +1526,38 @@ static int inet_addr_sync(const struct ifaddr_action *param) return err; } +static int ifaddr_agent_get_basic(struct inet_device *idev, struct inet_addr_front** parray, int *plen) +{ + lcoreid_t cid; + int ifa_cnt, len, err; + struct inet_addr_front *array; + + /* convey ifa data on master lcore */ + cid = rte_lcore_id(); + assert(cid == rte_get_main_lcore()); + + if (idev) + ifa_cnt = idev->ifa_cnt[cid]; + else + ifa_cnt = inet_addr_cnt[cid]; + + len = sizeof(struct inet_addr_front) + ifa_cnt * sizeof(struct inet_addr_entry); + array = rte_calloc(NULL, 1, len, RTE_CACHE_LINE_SIZE); + if (unlikely(!array)) + return EDPVS_NOMEM; + + array->count = ifa_cnt; + + err = agent_copy_lcore_entries(idev, (struct inet_addr_entry*)array->data, array->count); + if (err != EDPVS_OK) { + rte_free(array); + return err; + } + + *parray = array; + *plen = len; + return EDPVS_OK; +} static int ifaddr_get_basic(struct inet_device *idev, struct inet_addr_data_array **parray, int *plen) { @@ -1511,6 +1590,73 @@ static int ifaddr_get_basic(struct inet_device *idev, struct inet_addr_data_arra return EDPVS_OK; } +static int ifaddr_agent_get_stats(struct inet_device *idev, struct inet_addr_front **parray, int *plen) +{ + int err, i; + struct inet_addr_stats_detail *detail; + struct dpvs_msg *cur, *msg = NULL; + struct inet_addr_data_array *arrmsg; + struct dpvs_multicast_queue *reply = NULL; + + /* collect ifa sapool stats from slaves */ + if (idev) + msg = msg_make(MSG_TYPE_IFA_GET, 0, DPVS_MSG_MULTICAST, rte_lcore_id(), sizeof(idev), &idev); + else + msg = msg_make(MSG_TYPE_IFA_GET, 0, DPVS_MSG_MULTICAST, rte_lcore_id(), 0, NULL); + if (!msg) { + err = EDPVS_NOMEM; + goto errout; + } + + err = multicast_msg_send(msg, 0, &reply); + if (err != EDPVS_OK) + goto errout; + + list_for_each_entry(cur, &reply->mq, mq_node) { + arrmsg = (struct inet_addr_data_array *)cur->data; + if (*parray == NULL) { + *plen = sizeof(struct inet_addr_front) + arrmsg->naddr * sizeof(struct inet_addr_stats_detail); + *parray = rte_calloc(NULL, 1, *plen, RTE_CACHE_LINE_SIZE); + if (*parray == NULL) { + goto errout; + } + + (*parray)->count = arrmsg->naddr; + detail = (struct inet_addr_stats_detail*)(*parray)->data; + for (i = 0; i < arrmsg->naddr; i++) { + detail->addr = arrmsg->addrs[i].ifa_entry.addr; + detail += 1; + } + } + + detail = (struct inet_addr_stats_detail*)(*parray)->data; + for (i = 0; i < arrmsg->naddr; i++) { + assert(memcmp(&arrmsg->addrs[i].ifa_entry.addr, &detail->addr, sizeof(union inet_addr)) == 0); + + detail->sa_used += arrmsg->addrs[i].ifa_stats.sa_used; + detail->sa_free += arrmsg->addrs[i].ifa_stats.sa_free; + detail->sa_miss += arrmsg->addrs[i].ifa_stats.sa_miss; + + detail += 1; + } + } + + msg_destroy(&msg); + return EDPVS_OK; + +errout: + + if (msg) + msg_destroy(&msg); + + if (*parray) { + rte_free(*parray); + *parray = NULL; + *plen = 0; + } + return err; +} + static int ifaddr_get_stats(struct inet_device *idev, struct inet_addr_data_array **parray, int *plen) { int ii, err; @@ -1646,55 +1792,66 @@ static int ifa_sockopt_set(sockoptid_t opt, const void *conf, size_t size) { struct netif_port *dev; const struct inet_addr_param *param = conf; + const struct inet_addr_entry *entry = conf; - if (!conf || size < sizeof(struct inet_addr_param)) + if (!conf || size < sizeof(struct inet_addr_entry)) return EDPVS_INVAL; + if (opt >= SOCKOPT_SET_IFADDR_ADD && opt <= SOCKOPT_SET_IFADDR_FLUSH) + entry = ¶m->ifa_entry; + else if (opt >= DPVSAGENT_IFADDR_ADD && opt <= DPVSAGENT_IFADDR_DEL) + entry = conf; + if (opt != SOCKOPT_SET_IFADDR_FLUSH) { - if (!ifa_prefix_check(param->ifa_entry.af, - ¶m->ifa_entry.addr, - param->ifa_entry.plen)) { + if (!ifa_prefix_check(entry->af, + &entry->addr, + entry->plen)) { RTE_LOG(WARNING, IFA, "%s: bad %s prefix %d\n", __func__, - param->ifa_entry.af == AF_INET ? "ipv4" : "ipv6", - param->ifa_entry.plen); + entry->af == AF_INET ? "ipv4" : "ipv6", + entry->plen); return EDPVS_INVAL; } } - dev = netif_port_get_by_name(param->ifa_entry.ifname); + dev = netif_port_get_by_name(entry->ifname); if (!dev) { RTE_LOG(WARNING, IFA, "%s: device %s not found\n", __func__, - param->ifa_entry.ifname); + entry->ifname); return EDPVS_NOTEXIST; } switch (opt) { + case DPVSAGENT_IFADDR_ADD: + /*fallthrough*/ case SOCKOPT_SET_IFADDR_ADD: - return inet_addr_add(param->ifa_entry.af, dev, - ¶m->ifa_entry.addr, - param->ifa_entry.plen, - ¶m->ifa_entry.bcast, - param->ifa_entry.valid_lft, - param->ifa_entry.prefered_lft, - param->ifa_entry.scope, - param->ifa_entry.flags); - + return inet_addr_add(entry->af, dev, + &entry->addr, + entry->plen, + &entry->bcast, + entry->valid_lft, + entry->prefered_lft, + entry->scope, + entry->flags); + + case DPVSAGENT_IFADDR_DEL: + /*fallthrough*/ case SOCKOPT_SET_IFADDR_DEL: - return inet_addr_del(param->ifa_entry.af, dev, - ¶m->ifa_entry.addr, - param->ifa_entry.plen); + return inet_addr_del(entry->af, dev, + &entry->addr, + entry->plen); case SOCKOPT_SET_IFADDR_SET: - return inet_addr_mod(param->ifa_entry.af, dev, - ¶m->ifa_entry.addr, - param->ifa_entry.plen, - ¶m->ifa_entry.bcast, - param->ifa_entry.valid_lft, - param->ifa_entry.prefered_lft, - param->ifa_entry.scope); + return inet_addr_mod(entry->af, dev, + &entry->addr, + entry->plen, + &entry->bcast, + entry->valid_lft, + entry->prefered_lft, + entry->scope); case SOCKOPT_SET_IFADDR_FLUSH: - return inet_addr_flush(param->ifa_entry.af, dev); + return inet_addr_flush(entry->af, dev); + default: return EDPVS_NOTSUPP; @@ -1703,6 +1860,54 @@ static int ifa_sockopt_set(sockoptid_t opt, const void *conf, size_t size) return EDPVS_OK; } +static int ifa_sockopt_agent_get(sockoptid_t opt, const void *conf, size_t size, void **out, size_t *outsize) { + struct netif_port *dev; + struct inet_device *idev = NULL; + struct inet_addr_front *array = NULL; + const struct inet_addr_entry *entry = conf; + int len; + int err; + + if (entry->af != AF_INET && entry->af != AF_INET6 && entry->af != AF_UNSPEC) { + return EDPVS_NOTSUPP; + } + if (strlen(entry->ifname)) { + dev = netif_port_get_by_name(entry->ifname); + if (!dev) { + RTE_LOG(WARNING, IFA, "%s: no such device: %s\n", + __func__, entry->ifname); + return EDPVS_NOTEXIST; + } + + idev = dev_get_idev(dev); + if (!idev) + return EDPVS_RESOURCE; + } + + switch (opt) { + case DPVSAGENT_IFADDR_GET_STATS: + err = ifaddr_agent_get_stats(idev, &array, &len); + break; + case DPVSAGENT_IFADDR_GET_VERBOSE: + // err = ifaddr_agent_get_verbose(idev, &array, &len); + return EDPVS_NOTSUPP; + default: + err = ifaddr_agent_get_basic(idev, &array, &len); + } + if (err != EDPVS_OK) { + RTE_LOG(WARNING, IFA, "%s: fail to get inet addresses -- %s!\n", + __func__, dpvs_strerror(err)); + return err; + } + + if (idev) + idev_put(idev); + + *out = array; + *outsize = len; + return EDPVS_OK; +} + static int ifa_sockopt_get(sockoptid_t opt, const void *conf, size_t size, void **out, size_t *outsize) { @@ -1791,6 +1996,16 @@ static struct dpvs_msg_type ifa_msg_types[] = { } }; +static struct dpvs_sockopts agent_ifa_sockopts = { + .version = SOCKOPT_VERSION, + .set_opt_min = DPVSAGENT_IFADDR_ADD, + .set_opt_max = DPVSAGENT_IFADDR_DEL, + .set = ifa_sockopt_set, + .get_opt_min = DPVSAGENT_IFADDR_GET_BASE, + .get_opt_max = DPVSAGENT_IFADDR_GET_VERBOSE, + .get = ifa_sockopt_agent_get, +}; + static struct dpvs_sockopts ifa_sockopts = { .version = SOCKOPT_VERSION, .set_opt_min = SOCKOPT_SET_IFADDR_ADD, @@ -1823,6 +2038,13 @@ int inet_addr_init(void) return err; } + if ((err = sockopt_register(&agent_ifa_sockopts)) != EDPVS_OK) { + RTE_LOG(ERR, IFA, "%s: fail to register agent_ifa_sockopts -- %s\n", + __func__, dpvs_strerror(err)); + sockopt_unregister(&ifa_sockopts); + return err; + } + for (ii = 0; ii < NELEMS(ifa_msg_types); ii++) { switch (ifa_msg_types[ii].mode) { case DPVS_MSG_UNICAST: @@ -1861,6 +2083,10 @@ int inet_addr_term(void) int ii, err = EDPVS_OK; /* TODO: flush all address */ + if ((err = sockopt_unregister(&agent_ifa_sockopts)) != EDPVS_OK) { + RTE_LOG(ERR, IFA, "%s: fail to unregister ifa_sockopts -- %s\n", + __func__, dpvs_strerror(err)); + } if ((err = sockopt_unregister(&ifa_sockopts)) != EDPVS_OK) { RTE_LOG(ERR, IFA, "%s: fail to unregister ifa_sockopts -- %s\n", diff --git a/src/ipv6/route6.c b/src/ipv6/route6.c index d0ac2461e..81ad877cf 100644 --- a/src/ipv6/route6.c +++ b/src/ipv6/route6.c @@ -17,6 +17,7 @@ */ #include #include "route6.h" +#include "conf/route.h" #include "linux_ipv6.h" #include "ctrl.h" #include "route6_lpm.h" @@ -52,8 +53,8 @@ static inline void rt6_zero_prefix_tail(struct rt6_prefix *rt6_p) { struct in6_addr addr6; - ipv6_addr_prefix(&addr6, &rt6_p->addr, rt6_p->plen); - memcpy(&rt6_p->addr, &addr6, sizeof(addr6)); + ipv6_addr_prefix(&addr6, &rt6_p->addr.in6, rt6_p->plen); + memcpy(&rt6_p->addr.in6, &addr6, sizeof(addr6)); } static void rt6_cfg_zero_prefix_tail(const struct dp_vs_route6_conf *src, @@ -262,12 +263,12 @@ static int __route6_add_del(const struct in6_addr *dest, int plen, uint32_t flag cf.ops = RT6_OPS_ADD; else cf.ops = RT6_OPS_DEL; - cf.dst.addr = *dest; + cf.dst.addr.in6 = *dest; cf.dst.plen = plen; cf.flags = flags; cf.gateway = *gw; snprintf(cf.ifname, sizeof(cf.ifname), "%s", dev->name); - cf.src.addr = *src; + cf.src.addr.in6 = *src; cf.src.plen = plen; cf.mtu = mtu; @@ -343,17 +344,35 @@ static bool rt6_conf_check(const struct dp_vs_route6_conf *rt6_cfg) static int rt6_sockopt_set(sockoptid_t opt, const void *in, size_t inlen) { - const struct dp_vs_route6_conf *rt6_cfg_in = in; + const struct dp_vs_route6_conf *rt6_cfg_in = in; + const struct dp_vs_route_detail *detail = in; struct dp_vs_route6_conf rt6_cfg; - if (!rt6_conf_check(rt6_cfg_in)) { - RTE_LOG(INFO, RT6, "%s: invalid route6 sockopt!\n", __func__); - return EDPVS_INVAL; - } + if (opt == DPVSAGENT_ROUTE6_ADD || opt == DPVSAGENT_ROUTE6_DEL) { + memcpy(&rt6_cfg.dst, &detail->dst, sizeof(struct rt6_prefix)); + memcpy(&rt6_cfg.src, &detail->src, sizeof(struct rt6_prefix)); + memcpy(&rt6_cfg.prefsrc, &detail->prefsrc, sizeof(struct rt6_prefix)); + memcpy(&rt6_cfg.gateway, &detail->gateway.addr, sizeof(struct in6_addr)); + memcpy(rt6_cfg.ifname, detail->ifname, IFNAMSIZ); + rt6_cfg.mtu = detail->mtu; + rt6_cfg.flags = detail->flags; + rt6_cfg.ops = opt == DPVSAGENT_ROUTE6_ADD ? RT6_OPS_ADD : RT6_OPS_DEL; + + rt6_zero_prefix_tail(&rt6_cfg.dst); + } else { + if (!rt6_conf_check(rt6_cfg_in)) { + RTE_LOG(INFO, RT6, "%s: invalid route6 sockopt!\n", __func__); + return EDPVS_INVAL; + } - rt6_cfg_zero_prefix_tail(rt6_cfg_in, &rt6_cfg); + rt6_cfg_zero_prefix_tail(rt6_cfg_in, &rt6_cfg); + } switch (opt) { + case DPVSAGENT_ROUTE6_ADD: + /*fallthrough*/ + case DPVSAGENT_ROUTE6_DEL: + /*fallthrough*/ case SOCKOPT_SET_ROUTE6_ADD_DEL: return rt6_add_del(&rt6_cfg); case SOCKOPT_SET_ROUTE6_FLUSH: @@ -372,6 +391,16 @@ static int rt6_sockopt_get(sockoptid_t opt, const void *in, size_t inlen, return EDPVS_OK; } +static struct dpvs_sockopts agent_route6_sockopts = { + .version = SOCKOPT_VERSION, + .set_opt_min = DPVSAGENT_ROUTE6_ADD, + .set_opt_max = DPVSAGENT_ROUTE6_DEL, + .set = rt6_sockopt_set, + .get_opt_min = DPVSAGENT_ROUTE6_GET, + .get_opt_max = DPVSAGENT_ROUTE6_GET, + .get = rt6_sockopt_get, +}; + static struct dpvs_sockopts route6_sockopts = { .version = SOCKOPT_VERSION, .set_opt_min = SOCKOPT_SET_ROUTE6_ADD_DEL, @@ -438,6 +467,12 @@ int route6_init(void) return err; } + if ((err = sockopt_register(&agent_route6_sockopts)) != EDPVS_OK) { + RTE_LOG(ERR, RT6, "%s: fail to register route6 sockopt!\n", __func__); + return err; + } + + return EDPVS_OK; } @@ -449,6 +484,9 @@ int route6_term(void) rt6_method_term(); + if ((err = sockopt_unregister(&agent_route6_sockopts)) != EDPVS_OK) + RTE_LOG(WARNING, RT6, "%s: fail to unregister route6 sockopt!\n", __func__); + if ((err = sockopt_unregister(&route6_sockopts)) != EDPVS_OK) RTE_LOG(WARNING, RT6, "%s: fail to unregister route6 sockopt!\n", __func__); diff --git a/src/ipv6/route6_hlist.c b/src/ipv6/route6_hlist.c index 65e69a384..92d2d025b 100644 --- a/src/ipv6/route6_hlist.c +++ b/src/ipv6/route6_hlist.c @@ -103,7 +103,7 @@ static inline bool rt6_match(const struct route6 *rt6, const struct dp_vs_route6 { /* Note: Do not use `ipv6_masked_addr_cmp` here for performance consideration * here. We ensure the route6 entry is masked when added to route table. */ - if (ipv6_addr_cmp(&rt6->rt6_dst.addr, &cf->dst.addr) != 0) + if (ipv6_addr_cmp(&rt6->rt6_dst.addr.in6, &cf->dst.addr.in6) != 0) return false; if (rt6->rt6_dst.plen != cf->dst.plen) return false; @@ -131,7 +131,7 @@ static struct route6 *__rt6_hlist_get(const struct dp_vs_route6_conf *cf, continue; if (hlist->plen < cf->dst.plen) break; - hashkey = rt6_hlist_hashkey(&cf->dst.addr, hlist->plen, hlist->nbuckets); + hashkey = rt6_hlist_hashkey(&cf->dst.addr.in6, hlist->plen, hlist->nbuckets); list_for_each_entry(rt6, &hlist->hlist[hashkey], hnode) { if (rt6_match(rt6, cf)) { if (phlist) @@ -215,7 +215,7 @@ static int rt6_hlist_add_lcore(const struct dp_vs_route6_conf *cf) rt6_fill_with_cfg(rt6, cf); rte_atomic32_set(&rt6->refcnt, 1); - hashkey = rt6_hlist_hashkey(&cf->dst.addr, cf->dst.plen, hlist->nbuckets); + hashkey = rt6_hlist_hashkey(&cf->dst.addr.in6, cf->dst.plen, hlist->nbuckets); list_add_tail(&rt6->hnode, &hlist->hlist[hashkey]); hlist->nroutes++; this_rt6_nroutes++; @@ -270,10 +270,10 @@ static inline bool rt6_hlist_flow_match(const struct route6 *rt6, const struct flow6 *fl6) { if (rt6->rt6_dst.plen < 128) { - if (!ipv6_prefix_equal(&fl6->fl6_daddr, &rt6->rt6_dst.addr, rt6->rt6_dst.plen)) + if (!ipv6_prefix_equal(&fl6->fl6_daddr, &rt6->rt6_dst.addr.in6, rt6->rt6_dst.plen)) return false; } else { - if (!ipv6_addr_equal(&fl6->fl6_daddr, &rt6->rt6_dst.addr)) + if (!ipv6_addr_equal(&fl6->fl6_daddr, &rt6->rt6_dst.addr.in6)) return false; } diff --git a/src/ipv6/route6_lpm.c b/src/ipv6/route6_lpm.c index 7c0ce488b..7b950a054 100644 --- a/src/ipv6/route6_lpm.c +++ b/src/ipv6/route6_lpm.c @@ -78,7 +78,7 @@ static RTE_DEFINE_PER_LCORE(struct list_head*, dpvs_rt6_hash); static inline bool rt6_default(const struct rt6_prefix *rt6_p) { - return ipv6_addr_any(&rt6_p->addr) && (rt6_p->plen == 0); + return ipv6_addr_any(&rt6_p->addr.in6) && (rt6_p->plen == 0); } static inline int rt6_find_free_array_idx(uint32_t *idx) @@ -260,7 +260,7 @@ static struct route6* rt6_lpm_get(const struct dp_vs_route6_conf *rt6_cfg) hashkey = rt6_hash_key(&rt6_cfg->dst); list_for_each_entry_safe(entry, next, &this_rt6_hash[hashkey], hnode) { if (entry->rt6_dst.plen == rt6_cfg->dst.plen && - ipv6_prefix_equal(&entry->rt6_dst.addr, &rt6_cfg->dst.addr, + ipv6_prefix_equal(&entry->rt6_dst.addr.in6, &rt6_cfg->dst.addr.in6, rt6_cfg->dst.plen)) { /* Do not match rt6_cfg->ifname, because LPM6 does not support * the same rt6_prefix with different ifname */ @@ -268,7 +268,7 @@ static struct route6* rt6_lpm_get(const struct dp_vs_route6_conf *rt6_cfg) } } - if (rt6_cfg->dst.plen == 0 && ipv6_addr_any(&rt6_cfg->dst.addr)) + if (rt6_cfg->dst.plen == 0 && ipv6_addr_any(&rt6_cfg->dst.addr.in6)) return this_rt6_default; return NULL; @@ -389,7 +389,7 @@ static int rt6_lpm_del_lcore(const struct dp_vs_route6_conf *rt6_cfg) list_for_each_entry_safe(entry, next, &this_rt6_hash[hashkey], hnode) { if (entry->rt6_dst.plen == rt6_cfg->dst.plen && strcmp(rt6_cfg->ifname, entry->rt6_dev->name) == 0 && - ipv6_prefix_equal(&entry->rt6_dst.addr, &rt6_cfg->dst.addr, + ipv6_prefix_equal(&entry->rt6_dst.addr.in6, &rt6_cfg->dst.addr.in6, rt6_cfg->dst.plen)) { /* hit! route source is not checked */ ret = rte_lpm6_delete(this_lpm6_struct, (uint8_t *)&entry->rt6_dst.addr, diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index fea1cd4f6..cf4c907d3 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -24,6 +24,7 @@ #include "ipvs/sched.h" #include "ipvs/laddr.h" #include "ipvs/conn.h" +#include "ctrl.h" /* * Trash for destinations @@ -321,12 +322,341 @@ int dp_vs_dest_get_entries(const struct dp_vs_service *svc, return ret; } -int dp_vs_dest_init(void) +static int dp_vs_dest_get_details(const struct dp_vs_service *svc, + struct dp_vs_dest_front *uptr) { + int ret = 0; + int count = 0; + struct dp_vs_dest *dest; + struct dp_vs_dest_entry entry, *detail; + + uptr->cid = rte_lcore_id(); + uptr->index = g_lcore_id2index[uptr->cid]; + uptr->num_dests = svc->num_dests; + detail = (struct dp_vs_dest_entry*)((char*)uptr + sizeof(*uptr)); + + list_for_each_entry(dest, &svc->dests, n_list){ + if(count >= svc->num_dests) + break; + memset(&entry, 0, sizeof(entry)); + entry.af = dest->af; + entry.addr = dest->addr; + entry.port = dest->port; + entry.conn_flags = dest->fwdmode; + entry.weight = rte_atomic16_read(&dest->weight); + entry.max_conn = dest->max_conn; + entry.min_conn = dest->min_conn; + entry.actconns = rte_atomic32_read(&dest->actconns); + entry.inactconns = rte_atomic32_read(&dest->inactconns); + entry.persistconns = rte_atomic32_read(&dest->persistconns); + ret = dp_vs_stats_add(&(entry.stats), &dest->stats); + if (ret != EDPVS_OK) + break; + + memcpy(detail, &entry, sizeof(entry)); + detail += 1; + count++; + } + + return ret; +} + +static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len); +static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void **out, size_t *outlen); + +struct dpvs_sockopts sockopts_dest = { + .version = SOCKOPT_VERSION, + .set_opt_min = DPVSAGENT_VS_ADD_DESTS, + .set_opt_max = DPVSAGENT_VS_DEL_DESTS, + .set = dp_vs_dest_set, + .get_opt_min = DPVSAGENT_VS_GET_DESTS, + .get_opt_max = DPVSAGENT_VS_GET_DESTS, + .get = dp_vs_dest_get, +}; + +static int dest_msg_seq(void) { + static uint32_t seq = 0; + return seq++; +} + +static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len) +{ + struct dp_vs_dest_front *insvc; + struct dp_vs_dest_detail *details; + struct dp_vs_dest_conf udest; + struct dpvs_msg *msg; + struct dp_vs_service *getsvc; + int i, ret = EDPVS_INVAL; + lcoreid_t cid; + + insvc = (struct dp_vs_dest_front*)user; + if (len != sizeof(*insvc) + insvc->num_dests*sizeof(struct dp_vs_dest_detail)) { + return EDPVS_INVAL; + } + details = (struct dp_vs_dest_detail*)(user + sizeof(struct dp_vs_dest_front)); + + cid = rte_lcore_id(); + if (cid < 0 || cid >= DPVS_MAX_LCORE) { + return EDPVS_INVAL; + } + + if (cid == rte_get_main_lcore()) { + if (opt == DPVSAGENT_VS_ADD_DESTS) { + msg = msg_make(MSG_TYPE_AGENT_ADD_DESTS, dest_msg_seq(), DPVS_MSG_MULTICAST, cid, len, user); + } else if (opt == DPVSAGENT_VS_DEL_DESTS) { + msg = msg_make(MSG_TYPE_AGENT_DEL_DESTS, dest_msg_seq(), DPVS_MSG_MULTICAST, cid, len, user); + } else { + return EDPVS_NOTSUPP; + } + if (!msg) + return EDPVS_NOMEM; + + ret = multicast_msg_send(msg, DPVS_MSG_F_ASYNC, NULL); + if (ret != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "[%s] fail to send multicast message\n", __func__); + } + msg_destroy(&msg); + } + + getsvc = dp_vs_service_lookup(insvc->af, insvc->proto, &insvc->addr, insvc->port, insvc->fwmark, NULL, &insvc->match, NULL, cid); + if (!getsvc || getsvc->proto != insvc->proto) { + return EDPVS_INVAL; + } + + for (i = 0; i < insvc->num_dests; i++) { + memset(&udest, 0, sizeof(struct dp_vs_dest_conf)); + dp_vs_copy_udest_compat(&udest, &details[i]); + switch (opt) { + case DPVSAGENT_VS_ADD_DESTS: + ret = dp_vs_dest_add(getsvc, &udest); + if (ret == EDPVS_EXIST) + ret = dp_vs_dest_edit(getsvc, &udest); + break; + case DPVSAGENT_VS_DEL_DESTS: + ret = dp_vs_dest_del(getsvc, &udest); + break; + default: + return EDPVS_NOTSUPP; + } + } + return ret; +} + +static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void **out, size_t *outlen) +{ + struct dp_vs_dest_front *insvc, *outsvc, *front; + struct dp_vs_dest_detail *outdest, *slave_dest; + struct dp_vs_service *getsvc; + struct dp_vs_dest *dest; + int size, ret, i; + struct dpvs_msg *msg, *cur; + struct dpvs_multicast_queue *reply = NULL; + lcoreid_t cid; + + switch (opt) { + case DPVSAGENT_VS_GET_DESTS: + insvc = (struct dp_vs_dest_front*)user; + if (len != sizeof(*insvc)) { + *outlen = 0; + return EDPVS_INVAL; + } + + cid = g_lcore_index2id[insvc->index]; + if (cid < 0 || cid >= DPVS_MAX_LCORE) { + *outlen = 0; + return EDPVS_INVAL; + } + + size = sizeof(*insvc) + insvc->num_dests*sizeof(struct dp_vs_dest_detail); + + msg = msg_make(MSG_TYPE_AGENT_GET_DESTS, 0, DPVS_MSG_MULTICAST, rte_lcore_id(), len, user); + if (!msg) { + return EDPVS_NOMEM; + } + + ret = multicast_msg_send(msg, 0, &reply); + if (ret != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: send message fail.\n", __func__); + msg_destroy(&msg); + return EDPVS_MSG_FAIL; + } + + if (cid == rte_get_main_lcore()) { + // getsvc = dp_vs_service_get_lcore(&outsvc, cid); + getsvc = dp_vs_service_lookup(insvc->af, insvc->proto, &insvc->addr, insvc->port, insvc->fwmark, NULL, &insvc->match, NULL, cid); + if (!getsvc) { + msg_destroy(&msg); + return EDPVS_NOTEXIST; + } + + size = sizeof(*insvc) + getsvc->num_dests*sizeof(struct dp_vs_dest_detail); + *out = rte_zmalloc("get_dests", size, 0); + if (!*out) { + msg_destroy(&msg); + return EDPVS_NOMEM; + } + + rte_memcpy(*out, insvc, sizeof(insvc)); + outsvc = (struct dp_vs_dest_front*)*out; + outsvc->cid = rte_lcore_id(); + outsvc->index = g_lcore_id2index[outsvc->cid]; + outsvc->num_dests = getsvc->num_dests; + outdest = (struct dp_vs_dest_detail*)(*out + sizeof(outsvc)); + + list_for_each_entry(dest, &getsvc->dests, n_list) { + outdest->af = dest->af; + outdest->addr = dest->addr; + outdest->port = dest->port; + outdest->conn_flags = dest->fwdmode; + outdest->max_conn = dest->max_conn; + outdest->min_conn = dest->min_conn; + outdest->weight = rte_atomic16_read(&dest->weight); + outdest->actconns = rte_atomic32_read(&dest->actconns); + outdest->inactconns = rte_atomic32_read(&dest->inactconns); + outdest->persistconns = rte_atomic32_read(&dest->persistconns); + + ret = dp_vs_stats_add(&outdest->stats, &dest->stats); + if (ret != EDPVS_OK) { + msg_destroy(&msg); + rte_free(out); + return ret; + } + outdest += 1; + } + + list_for_each_entry(cur, &reply->mq, mq_node) { + slave_dest = (struct dp_vs_dest_detail*)(cur->data + sizeof(struct dp_vs_dest_front)); + outdest = (struct dp_vs_dest_detail*)(*out + sizeof(outsvc)); + for (i = 0; i < outsvc->num_dests; i++) { + outdest->max_conn += slave_dest->max_conn; + outdest->min_conn += slave_dest->min_conn; + outdest->actconns += slave_dest->actconns; + outdest->inactconns+= slave_dest->inactconns; + outdest->persistconns += slave_dest->persistconns; + dp_vs_stats_add(&outdest->stats, &slave_dest->stats); + + outdest += 1; + slave_dest += 1; + } + } + + *outlen = size; + msg_destroy(&msg); + return EDPVS_OK; + } else { + *out = rte_zmalloc("get_dests", size, 0); + if (!*out) { + msg_destroy(&msg); + return EDPVS_NOMEM; + } + + list_for_each_entry(cur, &reply->mq, mq_node) { + front = (struct dp_vs_dest_front*)cur->data; + if (cid == front->cid) { + rte_memcpy(*out, cur->data, size); + } + } + *outlen = size; + msg_destroy(&msg); + return EDPVS_OK; + } + break; + default: + return EDPVS_NOTSUPP; + } + return EDPVS_INVAL; +} + +static int adddest_msg_cb(struct dpvs_msg *msg) +{ + return dp_vs_dest_set(DPVSAGENT_VS_ADD_DESTS, msg->data, msg->len); +} + +static int deldest_msg_cb(struct dpvs_msg *msg) +{ + return dp_vs_dest_set(DPVSAGENT_VS_DEL_DESTS, msg->data, msg->len); +} + +static int dp_vs_dests_get_uc_cb(struct dpvs_msg *msg) +{ + lcoreid_t cid = rte_lcore_id(); + int ret = EDPVS_INVAL; + size_t size; + struct dp_vs_dest_front *get, *output; + struct dp_vs_service *svc; + + get = (struct dp_vs_dest_front*)msg->data; + svc = dp_vs_service_lookup(get->af, get->proto, &get->addr, get->port, get->fwmark, NULL, &get->match, NULL, cid); + if (!svc) + return EDPVS_NOTEXIST; + if (svc->num_dests != get->num_dests) { + RTE_LOG(ERR, SERVICE, "%s: dests number not match in cid=%d.\n", __func__, cid); + return EDPVS_INVAL; + } + + size = sizeof(*get) + sizeof(struct dp_vs_dest_detail) * (svc->num_dests); + output = msg_reply_alloc(size); + if (output == NULL) + return EDPVS_NOMEM; + + rte_memcpy(output, get, sizeof(*get)); + ret = dp_vs_dest_get_details(svc, output); + + if (ret != EDPVS_OK) { + msg_reply_free(output); + return ret; + } + + msg->reply.len = size; + msg->reply.data = (void *)output; return EDPVS_OK; } +int dp_vs_dest_init(void) +{ + int err; + struct dpvs_msg_type msg_type; + + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_ADD_DESTS; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = adddest_msg_cb; + err = msg_type_mc_register(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } + + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_DEL_DESTS; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = deldest_msg_cb; + err = msg_type_mc_register(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } + + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_GET_DESTS; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = dp_vs_dests_get_uc_cb; + err = msg_type_mc_register(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } + + return sockopt_register(&sockopts_dest); +} + int dp_vs_dest_term(void) { - return EDPVS_OK; + return sockopt_unregister(&sockopts_dest); } diff --git a/src/ipvs/ip_vs_laddr.c b/src/ipvs/ip_vs_laddr.c index d4fae582c..2f3a2a78b 100644 --- a/src/ipvs/ip_vs_laddr.c +++ b/src/ipvs/ip_vs_laddr.c @@ -361,6 +361,39 @@ int dp_vs_laddr_del(struct dp_vs_service *svc, int af, const union inet_addr *ad return err; } +static int dpvs_agent_laddr_getall(struct dp_vs_service *svc, + struct dp_vs_laddr_detail **addrs, size_t *naddr) +{ + struct dp_vs_laddr *laddr; + int i; + + if (!svc || !addrs || !naddr) + return EDPVS_INVAL; + + if (svc->num_laddrs > 0) { + *naddr = svc->num_laddrs; + *addrs = rte_malloc(0, sizeof(struct dp_vs_laddr_detail) * svc->num_laddrs, + RTE_CACHE_LINE_SIZE); + if (!(*addrs)) { + return EDPVS_NOMEM; + } + + i = 0; + list_for_each_entry(laddr, &svc->laddr_list, list) { + assert(i < *naddr); + (*addrs)[i].af = laddr->af; + (*addrs)[i].addr = laddr->addr; + (*addrs)[i].conns = rte_atomic32_read(&laddr->conn_counts); + i++; + } + } else { + *naddr = 0; + *addrs = NULL; + } + + return EDPVS_OK; +} + /* if success, it depend on caller to free @addrs by rte_free() */ static int dp_vs_laddr_getall(struct dp_vs_service *svc, struct dp_vs_laddr_entry **addrs, size_t *naddr) @@ -427,21 +460,54 @@ static uint32_t laddr_msg_seq(void) static inline sockoptid_t set_opt_so2msg(int opt) { - return opt - SOCKOPT_LADDR_BASE + MSG_TYPE_SET_LADDR_BASE; + // return opt - SOCKOPT_LADDR_BASE + MSG_TYPE_SET_LADDR_BASE; + switch (opt) { + case SOCKOPT_SET_LADDR_ADD: + return MSG_TYPE_LADDR_SET_ADD; + case SOCKOPT_SET_LADDR_DEL: + return MSG_TYPE_LADDR_SET_DEL; + case SOCKOPT_SET_LADDR_FLUSH: + return MSG_TYPE_LADDR_SET_FLUSH; + case SOCKOPT_GET_LADDR_GETALL: + return MSG_TYPE_LADDR_GET_ALL; + case DPVSAGENT_VS_ADD_LADDR: + return MSG_TYPE_AGENT_ADD_LADDR; + case DPVSAGENT_VS_DEL_LADDR: + return MSG_TYPE_AGENT_DEL_LADDR; + case DPVSAGENT_VS_GET_LADDR: + return MSG_TYPE_AGENT_GET_LADDR; + default: + return -1; + } } static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) { const struct dp_vs_laddr_conf *laddr_conf = conf; + const struct dp_vs_laddr_front *laddr_front = conf; + struct dp_vs_laddr_detail *details, *detail; struct dp_vs_service *svc; - int err; + int err = EDPVS_INVAL; + + int af; + uint16_t proto, port; + uint32_t fwmark, i; + const struct dp_vs_match *match; + const union inet_addr *addr; + lcoreid_t cid = rte_lcore_id(); // send to slave core if (cid == rte_get_main_lcore()) { struct dpvs_msg *msg; - msg = msg_make(set_opt_so2msg(opt), laddr_msg_seq(), DPVS_MSG_MULTICAST, cid, size, conf); + if (opt == DPVSAGENT_VS_ADD_LADDR) { + msg = msg_make(MSG_TYPE_AGENT_ADD_LADDR, laddr_msg_seq(), DPVS_MSG_MULTICAST, cid, size, conf); + } else if (opt == DPVSAGENT_VS_DEL_LADDR) { + msg = msg_make(MSG_TYPE_AGENT_DEL_LADDR, laddr_msg_seq(), DPVS_MSG_MULTICAST, cid, size, conf); + } else { + msg = msg_make(set_opt_so2msg(opt), laddr_msg_seq(), DPVS_MSG_MULTICAST, cid, size, conf); + } if (!msg) return EDPVS_NOMEM; @@ -455,9 +521,26 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) if (!conf && size < sizeof(*laddr_conf)) return EDPVS_INVAL; - svc = dp_vs_service_lookup(laddr_conf->af_s, laddr_conf->proto, - &laddr_conf->vaddr, laddr_conf->vport, - laddr_conf->fwmark, NULL, &laddr_conf->match, + if (opt == DPVSAGENT_VS_ADD_LADDR || opt == DPVSAGENT_VS_DEL_LADDR) { + af = (int)laddr_front->af; + proto = (uint16_t)laddr_front->proto; + port = (uint16_t)laddr_front->port; + fwmark = (uint32_t)laddr_front->fwmark; + addr = &laddr_front->addr; + match = &laddr_front->match; + details = (struct dp_vs_laddr_detail*)((char*)conf + sizeof(struct dp_vs_laddr_front)); + } else { + af = (int)laddr_conf->af_s; + proto = (uint16_t)laddr_conf->proto; + port = (uint16_t)laddr_conf->vport; + fwmark = (uint32_t)laddr_conf->fwmark; + addr = &laddr_conf->vaddr; + match = &laddr_conf->match; + } + + svc = dp_vs_service_lookup(af, proto, + addr, port, + fwmark, NULL, match, NULL, rte_lcore_id()); if (!svc) return EDPVS_NOSERV; @@ -473,6 +556,37 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) case SOCKOPT_SET_LADDR_FLUSH: err = dp_vs_laddr_flush(svc); break; + case DPVSAGENT_VS_ADD_LADDR: + details = (struct dp_vs_laddr_detail*)((char*)conf + sizeof(struct dp_vs_laddr_front)); + for (i = 0; i < laddr_front->count; i++) { + detail = (struct dp_vs_laddr_detail*)((char*)details + sizeof(struct dp_vs_laddr_detail) * i); + err = dp_vs_laddr_add(svc, + detail->af, + &detail->addr, + detail->ifname); + if (err != EDPVS_OK) { + if (err == EDPVS_EXIST) { + continue; + } + break; + } + } + break; + case DPVSAGENT_VS_DEL_LADDR: + details = (struct dp_vs_laddr_detail*)((char*)conf + sizeof(struct dp_vs_laddr_front)); + for (i = 0; i < laddr_front->count; i++) { + detail = (struct dp_vs_laddr_detail*)((char*)details + sizeof(struct dp_vs_laddr_detail) * i); + err = dp_vs_laddr_del(svc, + detail->af, + &detail->addr); + if (err != EDPVS_OK) { + if (err == EDPVS_NOTEXIST) { + continue; + } + break; + } + } + break; default: err = EDPVS_NOTSUPP; break; @@ -481,6 +595,58 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) return err; } + +static int agent_get_msg_cb(struct dpvs_msg *msg) +{ + lcoreid_t cid = rte_lcore_id(); + struct dp_vs_laddr_front *laddr_conf, *laddrs; + struct dp_vs_laddr_detail *addrs; + struct dp_vs_service *svc; + size_t naddr; + int err, size, i; + + laddr_conf = (struct dp_vs_laddr_front *)msg->data; + + svc = dp_vs_service_lookup(laddr_conf->af, laddr_conf->proto, + &laddr_conf->addr, laddr_conf->port, + laddr_conf->fwmark, NULL, &laddr_conf->match, + NULL, cid); + if (!svc) { + return EDPVS_NOSERV; + } + + err = dpvs_agent_laddr_getall(svc, &addrs, &naddr); + if (err != EDPVS_OK) + return err; + + size = sizeof(*laddr_conf) + naddr * sizeof(struct dp_vs_laddr_detail); + laddrs = msg_reply_alloc(size); + if (!laddrs) { + if (addrs) + rte_free(addrs); + return EDPVS_NOMEM; + } + + *laddrs = *laddr_conf; + laddrs->count = naddr; + laddrs->cid = cid; + // laddrs->index = g_lcore_id2index[cid]; + + for (i = 0; i < naddr; i++) { + laddrs->laddrs[i].af = addrs[i].af; + laddrs->laddrs[i].addr = addrs[i].addr; + /* TODO: nport_conflict & nconns */ + laddrs->laddrs[i].nport_conflict = 0; + laddrs->laddrs[i].conns = addrs[i].conns; + } + if (addrs) + rte_free(addrs); + + msg->reply.len = size; + msg->reply.data = (void *)laddrs; + return EDPVS_OK; +} + static int get_msg_cb(struct dpvs_msg *msg) { lcoreid_t cid = rte_lcore_id(); @@ -549,26 +715,27 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, { const struct dp_vs_laddr_conf *laddr_conf = conf; struct dp_vs_laddr_conf *laddrs, *get_msg; + const struct dp_vs_laddr_front *laddr_front; + struct dp_vs_laddr_front *out_front, *iter_front; struct dp_vs_service *svc; struct dp_vs_laddr_entry *addrs; + struct dp_vs_laddr_detail *details; size_t naddr, i; int err; struct dpvs_multicast_queue *reply = NULL; struct dpvs_msg *msg, *cur; lcoreid_t cid; - if (unlikely(opt > SOCKOPT_GET_LADDR_GETALL)) - return EDPVS_INVAL; - - if (!conf && size < sizeof(*laddr_conf)) - return EDPVS_INVAL; - - cid = g_lcore_index2id[laddr_conf->index]; - if (cid < 0 || cid >= DPVS_MAX_LCORE) - return EDPVS_INVAL; - switch (opt) { case SOCKOPT_GET_LADDR_GETALL: + laddr_conf = conf; + if (!conf || size < sizeof(*laddr_conf)) + return EDPVS_INVAL; + + cid = g_lcore_index2id[laddr_conf->index]; + if (cid < 0 || cid >= DPVS_MAX_LCORE) + return EDPVS_INVAL; + msg = msg_make(MSG_TYPE_LADDR_GET_ALL, 0, DPVS_MSG_MULTICAST, rte_lcore_id(), sizeof(struct dp_vs_laddr_conf), laddr_conf); if (!msg) @@ -654,11 +821,85 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, msg_destroy(&msg); return EDPVS_NOTEXIST; } + case DPVSAGENT_VS_GET_LADDR: + laddr_front = conf; + if (!conf || size != sizeof(*laddr_front)) + return EDPVS_INVAL; + msg = msg_make(MSG_TYPE_AGENT_GET_LADDR, 0, DPVS_MSG_MULTICAST, rte_lcore_id(), sizeof(struct dp_vs_laddr_front), laddr_front); + if (!msg) + return EDPVS_NOMEM; + + err = multicast_msg_send(msg, 0, &reply); + if (err != EDPVS_OK) { + msg_destroy(&msg); + RTE_LOG(ERR, SERVICE, "%s: send message fail.\n", __func__); + return EDPVS_MSG_FAIL; + } + + svc = dp_vs_service_lookup(laddr_front->af, laddr_front->proto, &laddr_front->addr, laddr_front->port, laddr_front->fwmark, NULL, &laddr_front->match, NULL, rte_get_main_lcore()); + if (!svc) { + msg_destroy(&msg); + return EDPVS_NOSERV; + } + + err = dpvs_agent_laddr_getall(svc, &details, &naddr); + if (err != EDPVS_OK) { + msg_destroy(&msg); + return err; + } + + *outsize = sizeof(*laddr_front) + naddr * sizeof(struct dp_vs_laddr_detail); + *out = rte_malloc(0, *outsize, RTE_CACHE_LINE_SIZE); + if (!*out) { + if (details) + rte_free(details); + msg_destroy(&msg); + return EDPVS_NOMEM; + } + + out_front = *out; + *out_front = *laddr_front; + + out_front->count = naddr; + out_front->cid = rte_get_main_lcore(); + for (i = 0; i < naddr; i++) { + out_front->laddrs[i].af = details[i].af; + out_front->laddrs[i].addr = details[i].addr; + out_front->laddrs[i].nport_conflict = 0; + out_front->laddrs[i].conns = details[i].conns; + } + if (details) + rte_free(details); + list_for_each_entry(cur, &reply->mq, mq_node) { + iter_front = (struct dp_vs_laddr_front*)(cur->data); + if (iter_front->count != out_front->count) { + msg_destroy(&msg); + rte_free(*out); + *out = NULL; + return EDPVS_INVAL; + } + for (i = 0; i < out_front->count; i++) { + out_front->laddrs[i].nport_conflict += iter_front->laddrs[i].nport_conflict; + out_front->laddrs[i].conns += iter_front->laddrs[i].conns; + } + } + msg_destroy(&msg); + return EDPVS_OK; default: return EDPVS_NOTSUPP; } } +static struct dpvs_sockopts agent_laddr_sockopts = { + .version = SOCKOPT_VERSION, + .set_opt_min = DPVSAGENT_VS_ADD_LADDR, + .set_opt_max = DPVSAGENT_VS_DEL_LADDR, + .set = laddr_sockopt_set, + .get_opt_min = DPVSAGENT_VS_GET_LADDR, + .get_opt_max = DPVSAGENT_VS_GET_LADDR, + .get = laddr_sockopt_get, +}; + static struct dpvs_sockopts laddr_sockopts = { .version = SOCKOPT_VERSION, .set_opt_min = SOCKOPT_SET_LADDR_ADD, @@ -668,6 +909,15 @@ static struct dpvs_sockopts laddr_sockopts = { .get_opt_max = SOCKOPT_GET_LADDR_MAX, .get = laddr_sockopt_get, }; +static int agent_add_msg_cb(struct dpvs_msg *msg) +{ + return laddr_sockopt_set(DPVSAGENT_VS_ADD_LADDR, msg->data, msg->len); +} + +static int agent_del_msg_cb(struct dpvs_msg *msg) +{ + return laddr_sockopt_set(DPVSAGENT_VS_DEL_LADDR, msg->data, msg->len); +} static int add_msg_cb(struct dpvs_msg *msg) { @@ -736,10 +986,48 @@ int dp_vs_laddr_init(void) RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); return err; } + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_GET_LADDR; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_LOW; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = agent_get_msg_cb; + err = msg_type_mc_register(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } + + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_ADD_LADDR; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = agent_add_msg_cb; + err = msg_type_mc_register(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } + + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_DEL_LADDR; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = agent_del_msg_cb; + err = msg_type_mc_register(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } if ((err = sockopt_register(&laddr_sockopts)) != EDPVS_OK) return err; + if ((err = sockopt_register(&agent_laddr_sockopts)) != EDPVS_OK) + return err; + return EDPVS_OK; } @@ -747,6 +1035,9 @@ int dp_vs_laddr_term(void) { int err; + if ((err = sockopt_unregister(&agent_laddr_sockopts)) != EDPVS_OK) + return err; + if ((err = sockopt_unregister(&laddr_sockopts)) != EDPVS_OK) return err; diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index 440cd4c11..fe56757a4 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -795,7 +795,7 @@ static int dp_vs_copy_usvc_compat(struct dp_vs_service_conf *conf, return EDPVS_OK; } -static void dp_vs_copy_udest_compat(struct dp_vs_dest_conf *udest, +void dp_vs_copy_udest_compat(struct dp_vs_dest_conf *udest, dpvs_dest_compat_t *udest_compat) { udest->af = udest_compat->af; @@ -823,7 +823,25 @@ static int gratuitous_arp_send_vip(struct in_addr *vip) static inline int set_opt_so2msg(sockoptid_t opt) { - return opt - SOCKOPT_SVC_BASE + MSG_TYPE_SVC_SET_BASE; + // return opt - SOCKOPT_SVC_BASE + MSG_TYPE_SVC_SET_BASE; + switch (opt) { + case DPVS_SO_SET_ZERO: + return MSG_TYPE_SVC_SET_ZERO; + case DPVS_SO_SET_ADD: + return MSG_TYPE_SVC_SET_ADD; + case DPVS_SO_SET_EDIT: + return MSG_TYPE_SVC_SET_EDIT; + case DPVS_SO_SET_DEL: + return MSG_TYPE_SVC_SET_DEL; + case DPVS_SO_SET_ADDDEST: + return MSG_TYPE_SVC_SET_ADDDEST; + case DPVS_SO_SET_DELDEST: + return MSG_TYPE_SVC_SET_DELDEST; + case DPVS_SO_SET_EDITDEST: + return MSG_TYPE_SVC_SET_EDITDEST; + default: + return -1; + } } static int svc_msg_seq(void) @@ -1133,6 +1151,118 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void *outlen = sizeof(struct dp_vs_getinfo); return EDPVS_OK; } + case DPVSAGENT_SO_GET_SERVICES: + { + dpvs_service_table_t msg_data, *get_msg, *tmp; + dpvs_agent_services_front_t *get, *real_output; + struct dpvs_msg *msg, *cur; + struct dpvs_multicast_queue *reply = NULL; + int size, real_size; + + get = (dpvs_agent_services_front_t*)user; + get->count = rte_atomic16_read(&dp_vs_num_services[get->cid]); + + msg_data.num_services = get->count; + msg_data.cid = get->cid; + msg_data.index = get->index; + + real_size = sizeof(*get) + \ + sizeof(struct dp_vs_service_entry) * msg_data.num_services; + + if (len != sizeof(*get)){ + *outlen = 0; + return EDPVS_INVAL; + } + + cid = g_lcore_index2id[get->index]; + if (cid < 0 || cid >= DPVS_MAX_LCORE) { + *outlen = 0; + return EDPVS_INVAL; + } + + /* get slave core svc */ + msg = msg_make(MSG_TYPE_SVC_GET_SERVICES, 0, DPVS_MSG_MULTICAST, rte_lcore_id(), + sizeof(msg_data), &msg_data); + if (unlikely(!msg)) { + return EDPVS_NOMEM; + } + + ret = multicast_msg_send(msg, 0, &reply); + if (ret != EDPVS_OK) { + msg_destroy(&msg); + RTE_LOG(ERR, SERVICE, "%s: send message fail\n", __func__); + return EDPVS_MSG_FAIL; + } + + if (cid == rte_get_main_lcore()) { + + size = sizeof(msg_data) + \ + sizeof(struct dp_vs_service_entry) * msg_data.num_services; + tmp = rte_zmalloc("get_services", size, 0); + if (unlikely(NULL == tmp)) { + msg_destroy(&msg); + return EDPVS_NOMEM; + } + + ret = dp_vs_service_get_entries(get->count, tmp, cid); + if (ret != EDPVS_OK) { + msg_destroy(&msg); + rte_free(tmp); + return ret; + } + + list_for_each_entry(cur, &reply->mq, mq_node) { + get_msg = (dpvs_service_table_t*)(cur->data); + ret = dp_vs_services_copy_percore_stats(tmp, get_msg); + if (ret != EDPVS_OK) { + msg_destroy(&msg); + rte_free(tmp); + return ret; + } + } + real_output = rte_zmalloc("agent_get_services", real_size, 0); + if (!real_output) { + msg_destroy(&msg); + rte_free(tmp); + return EDPVS_NOMEM; + } + + rte_memcpy(real_output, get, sizeof(*get)); + rte_memcpy(((char*)real_output)+sizeof(*get), ((char*)tmp)+sizeof(msg_data), real_size-sizeof(*get)); + + *out = real_output; + *outlen = real_size; + + rte_free(tmp); + msg_destroy(&msg); + return EDPVS_OK; + } else { + size = sizeof(msg_data) + \ + sizeof(struct dp_vs_service_entry) * msg_data.num_services; + + list_for_each_entry(cur, &reply->mq, mq_node) { + get_msg = (dpvs_service_table_t*)(cur->data); + if (get_msg->cid == cid) { + // FIXME: + real_output = rte_zmalloc("agent_get_services", real_size, 0); + if (unlikely(NULL == real_output)) { + msg_destroy(&msg); + return EDPVS_NOMEM; + } + // rte_memcpy(tmp, get_msg, size); + rte_memcpy(real_output, get, sizeof(*get)); + rte_memcpy(((char*)real_output)+sizeof(*get), ((char*)get_msg)+sizeof(msg_data), real_size-sizeof(*get)); + *out = real_output; + *outlen = real_size; + msg_destroy(&msg); + return EDPVS_OK; + } + } + RTE_LOG(ERR, SERVICE, "%s: find no services for cid=%d\n", __func__, cid); + msg_destroy(&msg); + return EDPVS_NOTEXIST; + } + } case DPVS_SO_GET_SERVICES: { dpvs_service_table_t *get, *get_msg, *output; diff --git a/src/ipvs/ip_vs_xmit.c b/src/ipvs/ip_vs_xmit.c index 6e557493c..2fb7270c1 100644 --- a/src/ipvs/ip_vs_xmit.c +++ b/src/ipvs/ip_vs_xmit.c @@ -2236,7 +2236,7 @@ static int __dp_vs_xmit_tunnel6(struct dp_vs_proto *proto, new_ip6h->ip6_nxt = IPPROTO_IPV6; new_ip6h->ip6_hops = old_ip6h->ip6_hops; - new_ip6h->ip6_src = rt6->rt6_src.addr; + new_ip6h->ip6_src = rt6->rt6_src.addr.in6; if (unlikely(ipv6_addr_any(&new_ip6h->ip6_src))) { RTE_LOG(INFO, IPVS, "%s: route6 without source, slect source" " address from inetaddr.\n", __func__); diff --git a/src/route.c b/src/route.c index 02175090d..a05e59e49 100644 --- a/src/route.c +++ b/src/route.c @@ -508,47 +508,53 @@ int route_flush(void) static int route_sockopt_set(sockoptid_t opt, const void *conf, size_t size) { - struct dp_vs_route_conf *cf = (void *)conf; + struct dp_vs_route_detail *detail = (struct dp_vs_route_detail*)conf; struct netif_port *dev; + union inet_addr *src, *dst, *gw; + uint32_t af, plen, metric, mtu; uint32_t flags = 0; - if (!conf || size < sizeof(*cf)) + if (!conf || size != sizeof(*detail)) return EDPVS_INVAL; - if (cf->af != AF_INET && cf->af != AF_UNSPEC) - return EDPVS_NOTSUPP; + af = detail->af; + plen = detail->dst.plen; + metric = detail->metric; + mtu = detail->mtu; + flags = detail->flags; - if (cf->scope == ROUTE_CF_SCOPE_HOST) { - flags |= RTF_LOCALIN; + dst = &detail->dst.addr; + src = &detail->src.addr; + gw = &detail->gateway.addr; - if (inet_is_addr_any(cf->af, &cf->dst) || cf->plen != 32) - return EDPVS_INVAL; - } - else if (cf->scope == ROUTE_CF_SCOPE_KNI) { - flags |= RTF_KNI; - if (inet_is_addr_any(cf->af, &cf->dst) || cf->plen != 32) + if (af != AF_INET && af != AF_UNSPEC) + return EDPVS_NOTSUPP; + + if (flags & RTF_LOCALIN || flags & RTF_KNI) + if (inet_is_addr_any(af, dst) || plen != 32) return EDPVS_INVAL; - } - else { - flags |= RTF_FORWARD; - if (inet_is_addr_any(cf->af, &cf->dst)) - flags |= RTF_DEFAULT; - } - if (cf->outwalltb) - flags |= RTF_OUTWALL; + if (flags & RTF_FORWARD) + if (inet_is_addr_any(af, dst)) + flags |= RTF_DEFAULT; - dev = netif_port_get_by_name(cf->ifname); + dev = netif_port_get_by_name(detail->ifname); if (!dev) /* no dev is OK ? */ return EDPVS_INVAL; switch (opt) { + case DPVSAGENT_ROUTE_ADD: + /*fallthrough*/ case SOCKOPT_SET_ROUTE_ADD: - return route_add(&cf->dst.in, cf->plen, flags, - &cf->via.in, dev, &cf->src.in, cf->mtu, cf->metric); + return route_add(&dst->in, plen, flags, + &gw->in, dev, &src->in, mtu, metric); + + case DPVSAGENT_ROUTE_DEL: + /*fallthrough*/ case SOCKOPT_SET_ROUTE_DEL: - return route_del(&cf->dst.in, cf->plen, flags, - &cf->via.in, dev, &cf->src.in, cf->mtu, cf->metric); + return route_del(&dst->in, plen, flags, + &gw->in, dev, &src->in, mtu, metric); + case SOCKOPT_SET_ROUTE_SET: return EDPVS_NOTSUPP; case SOCKOPT_SET_ROUTE_FLUSH: @@ -556,90 +562,54 @@ static int route_sockopt_set(sockoptid_t opt, const void *conf, size_t size) default: return EDPVS_NOTSUPP; } + + return EDPVS_NOTSUPP; } -static void route_fill_conf(int af, struct dp_vs_route_conf *cf, - const struct route_entry *entry) +static void route_fill_conf(int af, struct dp_vs_route_detail *detail, const struct route_entry *entry) { - memset(cf, 0, sizeof(*cf)); + memset(detail, 0, sizeof(*detail)); + detail->af = af; + detail->mtu = entry->mtu; + detail->metric = entry->metric; + detail->flags = entry->flag; - /* - * FIXME: - * some config fields are not implemented in route_entry. - */ - cf->af = af; - cf->dst.in = entry->dest; - cf->plen = entry->netmask; - cf->via.in = entry->gw; - cf->src.in = entry->src; - cf->mtu = entry->mtu; - cf->metric = entry->metric; + detail->dst.plen = entry->netmask; - if (entry->flag & RTF_LOCALIN){ - cf->scope = ROUTE_CF_SCOPE_HOST; - } else if (entry->flag & RTF_KNI) { - cf->scope = ROUTE_CF_SCOPE_KNI; - } else if (entry->gw.s_addr == htonl(INADDR_ANY)) { - cf->scope = ROUTE_CF_SCOPE_LINK; - cf->flags |= ROUTE_CF_FLAG_ONLINK; - } else { - cf->scope = ROUTE_CF_SCOPE_GLOBAL; - } + detail->dst.addr.in = entry->dest; + detail->src.addr.in = entry->src; + detail->gateway.addr.in = entry->gw; if (entry->port) - snprintf(cf->ifname, sizeof(cf->ifname), "%s", entry->port->name); - - return; + snprintf(detail->ifname, sizeof(detail->ifname), "%s", entry->port->name); } static int route_sockopt_get(sockoptid_t opt, const void *conf, size_t size, void **out, size_t *outsize) { - const struct dp_vs_route_conf *cf; struct dp_vs_route_conf_array *array; size_t nroute, hash; struct route_entry *entry; struct netif_port *port = NULL; int off = 0; - bool outwall_table=false; - - if (conf && size >= sizeof(*cf)) - cf = conf; - else - cf = NULL; - - if (cf && strlen(cf->ifname)) { - port = netif_port_get_by_name(cf->ifname); + char *ifname = ((struct dp_vs_route_detail*)conf)->ifname; + if (conf && strlen(ifname)) { + port = netif_port_get_by_name(ifname); if (!port) { RTE_LOG(WARNING, ROUTE, "%s: no such device: %s\n", - __func__, cf->ifname); + __func__, ifname); return EDPVS_NOTEXIST; } } nroute = rte_atomic32_read(&this_num_routes); - if (cf && cf->outwalltb) { - nroute = rte_atomic32_read(&this_num_out_routes); - outwall_table = true; - } + *outsize = sizeof(struct dp_vs_route_conf_array) + nroute * sizeof(struct dp_vs_route_detail); - *outsize = sizeof(struct dp_vs_route_conf_array) + \ - nroute * sizeof(struct dp_vs_route_conf); *out = rte_calloc(NULL, 1, *outsize, 0); if (!(*out)) return EDPVS_NOMEM; - array = *out; - - if (outwall_table) { - list_for_each_entry(entry, &this_gfw_route_table, list) { - if (off >= nroute) - break; - route_fill_conf(AF_INET, &array->routes[off++], entry); - } - array->nroute = off; - return EDPVS_OK; - } + array = (struct dp_vs_route_conf_array*)*out; if (port) { for (hash = 0; hash < LOCAL_ROUTE_TAB_SIZE; hash++) { @@ -717,6 +687,16 @@ static int route_del_msg_cb(struct dpvs_msg *msg) return route_msg_process(false, msg); } +static struct dpvs_sockopts agent_route_sockopts = { + .version = SOCKOPT_VERSION, + .set_opt_min = DPVSAGENT_ROUTE_ADD, + .set_opt_max = DPVSAGENT_ROUTE_DEL, + .set = route_sockopt_set, + .get_opt_min = DPVSAGENT_ROUTE_GET, + .get_opt_max = DPVSAGENT_ROUTE_GET, + .get = route_sockopt_get, +}; + static struct dpvs_sockopts route_sockopts = { .version = SOCKOPT_VERSION, .set_opt_min = SOCKOPT_SET_ROUTE_ADD, @@ -795,6 +775,9 @@ int route_init(void) if ((err = sockopt_register(&route_sockopts)) != EDPVS_OK) return err; + if ((err = sockopt_register(&agent_route_sockopts)) != EDPVS_OK) + return err; + return EDPVS_OK; } @@ -803,6 +786,9 @@ int route_term(void) int err; lcoreid_t cid; + if ((err = sockopt_unregister(&agent_route_sockopts)) != EDPVS_OK) + return err; + if ((err = sockopt_unregister(&route_sockopts)) != EDPVS_OK) return err; diff --git a/src/sa_pool.c b/src/sa_pool.c index 1495c2f56..86e5c858a 100644 --- a/src/sa_pool.c +++ b/src/sa_pool.c @@ -584,7 +584,7 @@ static int sa6_fetch(struct netif_port *dev, return EDPVS_NOROUTE; /* select source address. */ - if (ipv6_addr_any(&rt6->rt6_src.addr)) { + if (ipv6_addr_any(&rt6->rt6_src.addr.in6)) { inet_addr_select(AF_INET6, rt6->rt6_dev, (union inet_addr *)&rt6->rt6_dst.addr, RT_SCOPE_UNIVERSE, diff --git a/tools/dpip/route.c b/tools/dpip/route.c index 117324d08..9951051b5 100644 --- a/tools/dpip/route.c +++ b/tools/dpip/route.c @@ -119,19 +119,31 @@ static const char *flags_itoa(uint32_t flags) return flags_buf; } -static void route4_dump(const struct dp_vs_route_conf *route) +static void route4_dump(struct dp_vs_route_detail *route) { char dst[64], via[64], src[64]; + int scope; + if (route->flags & RTF_LOCALIN) { + scope = ROUTE_CF_SCOPE_HOST; + } else if (route->flags & RTF_KNI) { + scope = ROUTE_CF_SCOPE_KNI; + } else if (route->gateway.addr.in.s_addr == htonl(INADDR_ANY)) { + scope = ROUTE_CF_SCOPE_LINK; + route->flags |= ROUTE_CF_FLAG_ONLINK; + } else { + scope = ROUTE_CF_SCOPE_GLOBAL; + } + printf("%s %s/%d via %s src %s dev %s" - " mtu %d tos %d scope %s metric %d proto %s %s\n", + " mtu %d tos 0 scope %s metric %d proto %s %s\n", af_itoa(route->af), - inet_ntop(route->af, &route->dst, dst, sizeof(dst)) ? dst : "::", - route->plen, - inet_ntop(route->af, &route->via, via, sizeof(via)) ? via : "::", - inet_ntop(route->af, &route->src, src, sizeof(src)) ? src : "::", - route->ifname, route->mtu, route->tos, scope_itoa(route->scope), - route->metric, proto_itoa(route->proto), flags_itoa(route->flags)); + inet_ntop(route->af, &route->dst.addr.in, dst, sizeof(dst)) ? dst : "::", + route->dst.plen, + inet_ntop(route->af, &route->gateway.addr.in, via, sizeof(via)) ? via : "::", + inet_ntop(route->af, &route->src.addr.in, src, sizeof(src)) ? src : "::", + route->ifname, route->mtu, scope_itoa(scope), + route->metric, proto_itoa(0), flags_itoa(route->flags)); return; } @@ -152,7 +164,7 @@ static void route6_dump(const struct dp_vs_route6_conf *rt6_cfg) } else snprintf(scope, sizeof(scope), "%s", "::"); - if (ipv6_addr_any(&rt6_cfg->dst.addr) && rt6_cfg->dst.plen == 0) { + if (ipv6_addr_any(&rt6_cfg->dst.addr.in6) && rt6_cfg->dst.plen == 0) { snprintf(dst, sizeof(dst), "%s", "default"); printf("%s %s", af_itoa(AF_INET6), dst); } else { @@ -163,7 +175,7 @@ static void route6_dump(const struct dp_vs_route6_conf *rt6_cfg) if (!ipv6_addr_any(&rt6_cfg->gateway)) printf(" via %s", inet_ntop(AF_INET6, (union inet_addr*)&rt6_cfg->gateway, gateway, sizeof(gateway)) ? gateway : "::"); - if (!ipv6_addr_any(&rt6_cfg->src.addr)) + if (!ipv6_addr_any(&rt6_cfg->src.addr.in6)) printf(" src %s", inet_ntop(AF_INET6, (union inet_addr*)&rt6_cfg->src.addr, src, sizeof(src)) ? src : "::"); printf(" dev %s", rt6_cfg->ifname); @@ -177,70 +189,43 @@ static void route6_dump(const struct dp_vs_route6_conf *rt6_cfg) } static int route4_parse_args(struct dpip_conf *conf, - struct dp_vs_route_conf *route) + struct dp_vs_route_detail *route) { char *prefix = NULL; + int scope; memset(route, 0, sizeof(*route)); route->af = conf->af; - route->scope = ROUTE_CF_SCOPE_NONE; + scope = ROUTE_CF_SCOPE_NONE; while (conf->argc > 0) { if (strcmp(conf->argv[0], "via") == 0) { NEXTARG_CHECK(conf, "via"); - if (inet_pton_try(&route->af, conf->argv[0], &route->via) <= 0) + if (inet_pton_try((int*)&route->af, conf->argv[0], &route->gateway.addr) <= 0) return -1; } else if (strcmp(conf->argv[0], "dev") == 0) { NEXTARG_CHECK(conf, "dev"); snprintf(route->ifname, sizeof(route->ifname), "%s", conf->argv[0]); - } else if (strcmp(conf->argv[0], "tos") == 0) { - NEXTARG_CHECK(conf, "tos"); - route->tos = atoi(conf->argv[0]); } else if (strcmp(conf->argv[0], "mtu") == 0) { NEXTARG_CHECK(conf, "mtu"); route->mtu = atoi(conf->argv[0]); } else if (strcmp(conf->argv[0], "scope") == 0) { NEXTARG_CHECK(conf, "scope"); - if (strcmp(conf->argv[0], "host") == 0) - route->scope = ROUTE_CF_SCOPE_HOST; + route->flags |= RTF_LOCALIN; else if (strcmp(conf->argv[0], "kni_host") == 0) - route->scope = ROUTE_CF_SCOPE_KNI; + route->flags |= RTF_KNI; else if (strcmp(conf->argv[0], "link") == 0) - route->scope = ROUTE_CF_SCOPE_LINK; - else if (strcmp(conf->argv[0], "global") == 0) - route->scope = ROUTE_CF_SCOPE_GLOBAL; - else - route->scope = atoi(conf->argv[0]); + route->flags |= ROUTE_CF_FLAG_ONLINK; } else if (strcmp(conf->argv[0], "src") == 0) { NEXTARG_CHECK(conf, "src"); - if (inet_pton_try(&route->af, conf->argv[0], &route->src) <= 0) + if (inet_pton_try((int*)&route->af, conf->argv[0], &route->src.addr) <= 0) return -1; } else if (strcmp(conf->argv[0], "metric") == 0) { NEXTARG_CHECK(conf, "metric"); route->metric = atoi(conf->argv[0]); - } else if (strcmp(conf->argv[0], "proto") == 0) { - NEXTARG_CHECK(conf, "proto"); - - if (strcmp(conf->argv[0], "auto") == 0) - route->proto = ROUTE_CF_PROTO_AUTO; - else if (strcmp(conf->argv[0], "boot") == 0) - route->proto = ROUTE_CF_PROTO_BOOT; - else if (strcmp(conf->argv[0], "static") == 0) - route->proto = ROUTE_CF_PROTO_STATIC; - else if (strcmp(conf->argv[0], "ra") == 0) - route->proto = ROUTE_CF_PROTO_RA; - else - route->proto = atoi(conf->argv[0]); - } else if (strcmp(conf->argv[0], "onlink") == 0) { - ;/* on-link is output only */ } else if (strcmp(conf->argv[0], "local") == 0) { - route->scope = ROUTE_CF_SCOPE_HOST; - } else if (strcmp(conf->argv[0], "table") == 0) { - NEXTARG_CHECK(conf, "outwall"); - if (strcmp(conf->argv[0], "outwall") != 0) - return -1; - route->outwalltb = 1; + route->flags |= RTF_HOST; } else { prefix = conf->argv[0]; } @@ -263,7 +248,7 @@ static int route4_parse_args(struct dpip_conf *conf, /* PREFIX */ if (strcmp(prefix, "default") == 0) { - memset(&route->dst, 0, sizeof(route->dst)); + memset(&route->dst.addr.in, 0, sizeof(route->dst.addr.in)); if (route->af == AF_UNSPEC) route->af = AF_INET; } else { @@ -273,10 +258,10 @@ static int route4_parse_args(struct dpip_conf *conf, if ((plen = strchr(addr, '/')) != NULL) *plen++ = '\0'; - if (inet_pton_try(&route->af, prefix, &route->dst) <= 0) + if (inet_pton_try((int*)&route->af, prefix, &route->dst.addr) <= 0) return -1; - route->plen = plen ? atoi(plen) : 0; + route->dst.plen = plen ? atoi(plen) : 0; } if (route->af != AF_INET && route->af != AF_INET6) { @@ -294,20 +279,18 @@ static int route4_parse_args(struct dpip_conf *conf, * ELSE (@via is not set) * scope == LINK */ - if (route->scope == ROUTE_CF_SCOPE_NONE) { - if (inet_is_addr_any(route->af, &route->via)) { - route->scope = ROUTE_CF_SCOPE_LINK; - route->flags |= ROUTE_CF_FLAG_ONLINK; - } else { - route->scope = ROUTE_CF_SCOPE_GLOBAL; - } + if (scope == ROUTE_CF_SCOPE_NONE) { + if (inet_is_addr_any(route->af, &route->gateway.addr)) { + route->flags |= ROUTE_CF_FLAG_ONLINK; /*ROUTE_CF_FLAG_ONLINK is invalid flags value*/ + } + route->flags |= RTF_FORWARD; } - if (!route->plen && (strcmp(prefix, "default") != 0)) { + if (!route->dst.plen && (strcmp(prefix, "default") != 0)) { if (route->af == AF_INET) - route->plen = 32; + route->dst.plen = 32; else - route->plen = 128; + route->dst.plen = 128; } if (conf->verbose) @@ -368,7 +351,7 @@ static int route6_parse_args(struct dpip_conf *conf, NEXTARG(conf); } - if ((rt6_cfg->flags & RTF_FORWARD) && (ipv6_addr_any(&rt6_cfg->dst.addr) == 0)) + if ((rt6_cfg->flags & RTF_FORWARD) && (ipv6_addr_any(&rt6_cfg->dst.addr.in6) == 0)) rt6_cfg->flags |= RTF_DEFAULT; if (!(rt6_cfg->flags & (RTF_LOCALIN|RTF_KNI|RTF_FORWARD|RTF_DEFAULT))) rt6_cfg->flags |= RTF_FORWARD; @@ -415,7 +398,8 @@ static int route6_parse_args(struct dpip_conf *conf, static int route4_do_cmd(struct dpip_obj *obj, dpip_cmd_t cmd, struct dpip_conf *conf) { - struct dp_vs_route_conf route; + // struct dp_vs_route_conf route; + struct dp_vs_route_detail route; struct dp_vs_route_conf_array *array; size_t size, i; int err; @@ -444,7 +428,7 @@ static int route4_do_cmd(struct dpip_obj *obj, dpip_cmd_t cmd, if (size < sizeof(*array) || size != sizeof(*array) + \ - array->nroute * sizeof(struct dp_vs_route_conf)) { + array->nroute * sizeof(struct dp_vs_route_detail)) { fprintf(stderr, "corrupted response.\n"); dpvs_sockopt_msg_free(array); return EDPVS_INVAL; diff --git a/tools/keepalived/keepalived/vrrp/vrrp_iproute.c b/tools/keepalived/keepalived/vrrp/vrrp_iproute.c index 5451316d2..750f92bd8 100644 --- a/tools/keepalived/keepalived/vrrp/vrrp_iproute.c +++ b/tools/keepalived/keepalived/vrrp/vrrp_iproute.c @@ -346,7 +346,7 @@ static void dpvs_fill_rt4conf(ip_route_t *iproute, struct dp_vs_route_conf *rout static void dpvs_fill_rt6conf(ip_route_t *iproute, struct dp_vs_route6_conf *rt6_cfg) { - rt6_cfg->dst.addr = ((iproute->dst)->u).sin6_addr; + rt6_cfg->dst.addr.in6 = ((iproute->dst)->u).sin6_addr; rt6_cfg->dst.plen = iproute->dst->ifa.ifa_prefixlen; rt6_cfg->src.plen = 128; if (iproute->via) { @@ -356,7 +356,7 @@ static void dpvs_fill_rt6conf(ip_route_t *iproute, struct dp_vs_route6_conf *rt6 } if (iproute->pref_src) { - rt6_cfg->src.addr = (iproute->pref_src->u).sin6_addr; + rt6_cfg->src.addr.in6 = (iproute->pref_src->u).sin6_addr; } else { memset(&rt6_cfg->src, 0, sizeof(rt6_cfg->src)); } From 0f3c69f97bd3a5b1ecedae8fafa7a28d9082c4b3 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 6 Mar 2023 14:03:55 +0800 Subject: [PATCH 002/105] rename rt6_prefix as rt_addr --- include/conf/flow.h | 2 +- include/conf/route6.h | 6 +++--- include/route6.h | 8 ++++---- src/ipv6/route6.c | 8 ++++---- src/ipv6/route6_lpm.c | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/include/conf/flow.h b/include/conf/flow.h index b9cb1d761..95baf407c 100644 --- a/include/conf/flow.h +++ b/include/conf/flow.h @@ -48,7 +48,7 @@ #define RTF_KNI 0X2000 #define RTF_OUTWALL 0x4000 -typedef struct rt6_prefix { +typedef struct rt_addr { union inet_addr addr; int plen; /*prefix len*/ } rt_addr_t; diff --git a/include/conf/route6.h b/include/conf/route6.h index 6ea7dcf5b..6543978d9 100644 --- a/include/conf/route6.h +++ b/include/conf/route6.h @@ -31,9 +31,9 @@ enum { struct dp_vs_route6_conf { int ops; - struct rt6_prefix dst; - struct rt6_prefix src; - struct rt6_prefix prefsrc; + rt_addr_t dst; + rt_addr_t src; + rt_addr_t prefsrc; char ifname[IFNAMSIZ]; struct in6_addr gateway; uint32_t mtu; diff --git a/include/route6.h b/include/route6.h index c9d74edf6..323667474 100644 --- a/include/route6.h +++ b/include/route6.h @@ -27,9 +27,9 @@ #define RT6_METHOD_NAME_SZ 32 struct route6 { - struct rt6_prefix rt6_dst; - struct rt6_prefix rt6_src; - struct rt6_prefix rt6_prefsrc; + rt_addr_t rt6_dst; + rt_addr_t rt6_src; + rt_addr_t rt6_prefsrc; struct in6_addr rt6_gateway; struct netif_port *rt6_dev; uint32_t rt6_mtu; @@ -60,7 +60,7 @@ int route6_del(const struct in6_addr *dest, int plen, uint32_t flags, /* for route6_xxx.c only */ void route6_free(struct route6*); -static inline int dump_rt6_prefix(const struct rt6_prefix *rt6_p, char *buf, int len) +static inline int dump_rt6_prefix(const rt_addr_t *rt6_p, char *buf, int len) { size_t rlen; diff --git a/src/ipv6/route6.c b/src/ipv6/route6.c index 81ad877cf..c06b36514 100644 --- a/src/ipv6/route6.c +++ b/src/ipv6/route6.c @@ -49,7 +49,7 @@ static int rt6_msg_seq(void) return seq++; } -static inline void rt6_zero_prefix_tail(struct rt6_prefix *rt6_p) +static inline void rt6_zero_prefix_tail(rt_addr_t *rt6_p) { struct in6_addr addr6; @@ -349,9 +349,9 @@ static int rt6_sockopt_set(sockoptid_t opt, const void *in, size_t inlen) struct dp_vs_route6_conf rt6_cfg; if (opt == DPVSAGENT_ROUTE6_ADD || opt == DPVSAGENT_ROUTE6_DEL) { - memcpy(&rt6_cfg.dst, &detail->dst, sizeof(struct rt6_prefix)); - memcpy(&rt6_cfg.src, &detail->src, sizeof(struct rt6_prefix)); - memcpy(&rt6_cfg.prefsrc, &detail->prefsrc, sizeof(struct rt6_prefix)); + memcpy(&rt6_cfg.dst, &detail->dst, sizeof(rt_addr_t)); + memcpy(&rt6_cfg.src, &detail->src, sizeof(rt_addr_t)); + memcpy(&rt6_cfg.prefsrc, &detail->prefsrc, sizeof(rt_addr_t)); memcpy(&rt6_cfg.gateway, &detail->gateway.addr, sizeof(struct in6_addr)); memcpy(rt6_cfg.ifname, detail->ifname, IFNAMSIZ); rt6_cfg.mtu = detail->mtu; diff --git a/src/ipv6/route6_lpm.c b/src/ipv6/route6_lpm.c index 7b950a054..e4f271b07 100644 --- a/src/ipv6/route6_lpm.c +++ b/src/ipv6/route6_lpm.c @@ -66,7 +66,7 @@ static RTE_DEFINE_PER_LCORE(struct route6*, dpvs_rt6_default); /*lpm6 not suppor /* Why need hash lists while using LPM6? * LPM6 can help find the best match route rule, but cannot find any route rule we want. - * For example, assume there exists two rules with rt6_prefix + * For example, assume there exists two rules with rt_addr * FE80::0/16 --> rt6_array::entries[0] * FE80::0/64 --> rt6_array::entries[1] * LPM6 lookup would never hit the first rule using 'rte_lpm6_lookup'. @@ -76,7 +76,7 @@ static RTE_DEFINE_PER_LCORE(struct route6*, dpvs_rt6_default); /*lpm6 not suppor */ static RTE_DEFINE_PER_LCORE(struct list_head*, dpvs_rt6_hash); -static inline bool rt6_default(const struct rt6_prefix *rt6_p) +static inline bool rt6_default(const rt_addr_t *rt6_p) { return ipv6_addr_any(&rt6_p->addr.in6) && (rt6_p->plen == 0); } @@ -99,7 +99,7 @@ static inline int rt6_find_free_array_idx(uint32_t *idx) return EDPVS_INVAL; } -static inline int rt6_hash_key(const struct rt6_prefix *rt6_p) +static inline int rt6_hash_key(const rt_addr_t *rt6_p) { return rte_jhash_32b((const uint32_t *)&rt6_p->addr, 4, rt6_p->plen) % g_rt6_hash_bucket; @@ -263,7 +263,7 @@ static struct route6* rt6_lpm_get(const struct dp_vs_route6_conf *rt6_cfg) ipv6_prefix_equal(&entry->rt6_dst.addr.in6, &rt6_cfg->dst.addr.in6, rt6_cfg->dst.plen)) { /* Do not match rt6_cfg->ifname, because LPM6 does not support - * the same rt6_prefix with different ifname */ + * the same rt_addr_t with different ifname */ return entry; } } From b855d7bb3d5d9d94816b221cd7a97323d0f4fd25 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 6 Mar 2023 18:15:58 +0800 Subject: [PATCH 003/105] replace dpvs_service_table_t by dpvs_agent_services_front_t --- include/conf/service.h | 11 +--- src/ipvs/ip_vs_service.c | 53 +++++++++---------- tools/ipvsadm/ipvsadm.c | 32 +++++------ tools/keepalived/keepalived/check/libipvs.c | 12 ++--- tools/keepalived/keepalived/include/libipvs.h | 4 +- 5 files changed, 52 insertions(+), 60 deletions(-) diff --git a/include/conf/service.h b/include/conf/service.h index ae812e3ff..c50908e18 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -74,16 +74,9 @@ typedef struct dp_vs_service_compat { #define dp_vs_service_entry dp_vs_service_compat #define dp_vs_service_user dp_vs_service_compat -typedef struct dp_vs_services_table { - lcoreid_t cid; - lcoreid_t index; - unsigned int num_services; - dpvs_service_compat_t entrytable[0]; -} dpvs_service_table_t; - typedef struct dp_vs_agent_services_front { - uint8_t cid; - uint8_t index; + lcoreid_t cid; + lcoreid_t index; uint16_t count; dpvs_service_compat_t entrytable[0]; } dpvs_agent_services_front_t; diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index fe56757a4..7341b3151 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -669,7 +669,7 @@ dp_vs_service_copy(struct dp_vs_service_entry *dst, struct dp_vs_service *src) } static int dp_vs_service_get_entries(int num_services, - dpvs_service_table_t *uptr, + dpvs_agent_services_front_t *uptr, lcoreid_t cid) { int idx, count = 0; @@ -678,7 +678,7 @@ static int dp_vs_service_get_entries(int num_services, uptr->cid = cid; uptr->index = g_lcore_id2index[cid]; - uptr->num_services = num_services; + uptr->count = num_services; for (idx = 0; idx < DP_VS_SVC_TAB_SIZE; idx++) { list_for_each_entry(svc, &dp_vs_svc_table[cid][idx], s_list){ if (count >= num_services) @@ -964,13 +964,13 @@ static int dp_vs_service_set(sockoptid_t opt, const void *user, size_t len) } /* copy service/dest/stats */ -static int dp_vs_services_copy_percore_stats(dpvs_service_table_t *master_svcs, - dpvs_service_table_t *slave_svcs) +static int dp_vs_services_copy_percore_stats(dpvs_agent_services_front_t *master_svcs, + dpvs_agent_services_front_t *slave_svcs) { int i; - if (master_svcs->num_services != slave_svcs->num_services) + if (master_svcs->count!= slave_svcs->count) return EDPVS_INVAL; - for (i = 0; i < master_svcs->num_services; i++) + for (i = 0; i < master_svcs->count; i++) dp_vs_stats_add(&master_svcs->entrytable[i].stats, &slave_svcs->entrytable[i].stats); return EDPVS_OK; } @@ -998,22 +998,22 @@ static int dp_vs_services_get_uc_cb(struct dpvs_msg *msg) { lcoreid_t cid = rte_lcore_id(); size_t size; - dpvs_service_table_t *get, *output; + dpvs_agent_services_front_t *get, *output; int ret; /* service may be changed */ - get = (dpvs_service_table_t*)msg->data; - if (get->num_services != rte_atomic16_read(&dp_vs_num_services[cid])) { + get = (dpvs_agent_services_front_t*)msg->data; + if (get->count != rte_atomic16_read(&dp_vs_num_services[cid])) { RTE_LOG(ERR, SERVICE, "%s: svc number %d not match %d in cid=%d.\n", - __func__, get->num_services, rte_atomic16_read(&dp_vs_num_services[cid]), cid); + __func__, get->count, rte_atomic16_read(&dp_vs_num_services[cid]), cid); return EDPVS_INVAL; } - size = sizeof(*get) + sizeof(struct dp_vs_service_entry) * get->num_services; + size = sizeof(*get) + sizeof(struct dp_vs_service_entry) * get->count; output = msg_reply_alloc(size); if (output == NULL) return EDPVS_NOMEM; - ret = dp_vs_service_get_entries(get->num_services, output, cid); + ret = dp_vs_service_get_entries(get->count, output, cid); if (ret != EDPVS_OK) { msg_reply_free(output); return ret; @@ -1153,8 +1153,7 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void } case DPVSAGENT_SO_GET_SERVICES: { - dpvs_service_table_t msg_data, *get_msg, *tmp; - dpvs_agent_services_front_t *get, *real_output; + dpvs_agent_services_front_t msg_data, *get, *real_output, *get_msg, *tmp; struct dpvs_msg *msg, *cur; struct dpvs_multicast_queue *reply = NULL; int size, real_size; @@ -1162,14 +1161,14 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void get = (dpvs_agent_services_front_t*)user; get->count = rte_atomic16_read(&dp_vs_num_services[get->cid]); - msg_data.num_services = get->count; + msg_data.count = get->count; msg_data.cid = get->cid; msg_data.index = get->index; real_size = sizeof(*get) + \ - sizeof(struct dp_vs_service_entry) * msg_data.num_services; + sizeof(struct dp_vs_service_entry) * msg_data.count; - if (len != sizeof(*get)){ + if (len != sizeof(*get)) { *outlen = 0; return EDPVS_INVAL; } @@ -1197,7 +1196,7 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void if (cid == rte_get_main_lcore()) { size = sizeof(msg_data) + \ - sizeof(struct dp_vs_service_entry) * msg_data.num_services; + sizeof(struct dp_vs_service_entry) * msg_data.count; tmp = rte_zmalloc("get_services", size, 0); if (unlikely(NULL == tmp)) { msg_destroy(&msg); @@ -1212,7 +1211,7 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void } list_for_each_entry(cur, &reply->mq, mq_node) { - get_msg = (dpvs_service_table_t*)(cur->data); + get_msg = (dpvs_agent_services_front_t*)(cur->data); ret = dp_vs_services_copy_percore_stats(tmp, get_msg); if (ret != EDPVS_OK) { msg_destroy(&msg); @@ -1238,10 +1237,10 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void return EDPVS_OK; } else { size = sizeof(msg_data) + \ - sizeof(struct dp_vs_service_entry) * msg_data.num_services; + sizeof(struct dp_vs_service_entry) * msg_data.count; list_for_each_entry(cur, &reply->mq, mq_node) { - get_msg = (dpvs_service_table_t*)(cur->data); + get_msg = (dpvs_agent_services_front_t*)(cur->data); if (get_msg->cid == cid) { // FIXME: real_output = rte_zmalloc("agent_get_services", real_size, 0); @@ -1265,14 +1264,14 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void } case DPVS_SO_GET_SERVICES: { - dpvs_service_table_t *get, *get_msg, *output; + dpvs_agent_services_front_t *get, *get_msg, *output; struct dpvs_msg *msg, *cur; struct dpvs_multicast_queue *reply = NULL; int size; - get = (dpvs_service_table_t*)user; + get = (dpvs_agent_services_front_t*)user; size = sizeof(*get) + \ - sizeof(struct dp_vs_service_entry) * (get->num_services); + sizeof(struct dp_vs_service_entry) * (get->count); if (len != sizeof(*get)){ *outlen = 0; return EDPVS_INVAL; @@ -1305,14 +1304,14 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void return EDPVS_NOMEM; } //rte_memcpy(output, get, sizeof(*get)); - ret = dp_vs_service_get_entries(get->num_services, output, cid); + ret = dp_vs_service_get_entries(get->count, output, cid); if (ret != EDPVS_OK) { msg_destroy(&msg); rte_free(output); return ret; } list_for_each_entry(cur, &reply->mq, mq_node) { - get_msg = (dpvs_service_table_t*)(cur->data); + get_msg = (dpvs_agent_services_front_t*)(cur->data); ret = dp_vs_services_copy_percore_stats(output, get_msg); if (ret != EDPVS_OK) { msg_destroy(&msg); @@ -1326,7 +1325,7 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void return EDPVS_OK; } else { list_for_each_entry(cur, &reply->mq, mq_node) { - get_msg = (dpvs_service_table_t*)(cur->data); + get_msg = (dpvs_agent_services_front_t*)(cur->data); if (get_msg->cid == cid) { output = rte_zmalloc("get_services", size, 0); if (unlikely(NULL == output)) { diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index a6226853d..daad672be 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -2219,24 +2219,24 @@ static int list_laddrs(dpvs_service_compat_t* desc) static int list_all_laddrs(lcoreid_t index) { int i; - dpvs_service_table_t* table; + dpvs_agent_services_front_t* table; struct ip_vs_get_laddrs *d = NULL; - table = (dpvs_service_table_t*)malloc(sizeof(dpvs_service_table_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); + table = (dpvs_agent_services_front_t*)malloc(sizeof(dpvs_agent_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); if (!table) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); } table->index = ce.index; - table->num_services = g_ipvs_info.num_services; + table->count = (uint16_t)g_ipvs_info.num_services; if (!dpvs_get_services(table)) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); } - for (i = 0; i < table->num_services; i++) { + for (i = 0; i < table->count; i++) { if(!dpvs_get_laddrs(&(table->entrytable[i]), &d)) { free(table); fprintf(stderr, "%s\n", ipvs_strerror(errno)); @@ -2325,16 +2325,16 @@ static int list_blklst(int af, const union inet_addr *addr, uint16_t port, uint1 static int list_all_blklsts(void) { int i; - dpvs_service_table_t* table; + dpvs_agent_services_front_t* table; - table = (dpvs_service_table_t*)malloc(sizeof(dpvs_service_table_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); + table = (dpvs_agent_services_front_t*)malloc(sizeof(dpvs_agent_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); if (!table) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); } table->index = ce.index; - table->num_services = g_ipvs_info.num_services; + table->count = (uint16_t)g_ipvs_info.num_services; if (!dpvs_get_services(table)) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); @@ -2342,7 +2342,7 @@ static int list_all_blklsts(void) } list_blklsts_print_title(); - for (i = 0; i < table->num_services; i++) { + for (i = 0; i < table->count; i++) { list_blklst(table->entrytable[i].af, &table->entrytable[i].addr, table->entrytable[i].port, table->entrytable[i].proto); } @@ -2413,17 +2413,17 @@ static int list_whtlst(int af, const union inet_addr *addr, uint16_t port, uint1 static int list_all_whtlsts(void) { - dpvs_service_table_t* table; + dpvs_agent_services_front_t* table; int i; - table = (dpvs_service_table_t*)malloc(sizeof(dpvs_service_table_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); + table = (dpvs_agent_services_front_t*)malloc(sizeof(dpvs_agent_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); if (!table) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); } table->index = ce.index; - table->num_services = g_ipvs_info.num_services; + table->count = g_ipvs_info.num_services; if (!dpvs_get_services(table)) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); @@ -2431,7 +2431,7 @@ static int list_all_whtlsts(void) } list_whtlsts_print_title(); - for (i = 0; i < table->num_services; i++) { + for (i = 0; i < table->count; i++) { list_whtlst(table->entrytable[i].af, &table->entrytable[i].addr, table->entrytable[i].port, table->entrytable[i].proto); } @@ -2458,20 +2458,20 @@ static void list_service(dpvs_service_compat_t *svc, unsigned int format) static void list_all(unsigned int format) { int i; - dpvs_service_table_t* table; + dpvs_agent_services_front_t* table; if (!(format & FMT_RULE)) printf("IP Virtual Server version %d.%d.%d (size=%d)\n", NVERSION(g_ipvs_info.version), g_ipvs_info.size); - table = (dpvs_service_table_t*)malloc(sizeof(dpvs_service_table_t) + sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); + table = (dpvs_agent_services_front_t*)malloc(sizeof(dpvs_agent_services_front_t) + sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); if (!table) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); } table->index = ce.index; - table->num_services = g_ipvs_info.num_services; + table->count = (uint16_t)g_ipvs_info.num_services; if (!dpvs_get_services(table)) { free(table); @@ -2483,7 +2483,7 @@ static void list_all(unsigned int format) } print_title(format); - for (i = 0; i < table->num_services; i++) { + for (i = 0; i < table->count; i++) { print_service_entry(&table->entrytable[i], format); } diff --git a/tools/keepalived/keepalived/check/libipvs.c b/tools/keepalived/keepalived/check/libipvs.c index fa7ce1660..67fed7180 100644 --- a/tools/keepalived/keepalived/check/libipvs.c +++ b/tools/keepalived/keepalived/check/libipvs.c @@ -420,8 +420,8 @@ int dpvs_stop_daemon(ipvs_daemon_t *dm) (char *)&dm, sizeof(dm)); } -dpvs_service_table_t* dpvs_get_services(dpvs_service_table_t* svcs) { - dpvs_service_table_t* rcv; +dpvs_agent_services_front_t* dpvs_get_services(dpvs_agent_services_front_t* svcs) { + dpvs_agent_services_front_t* rcv; size_t lrcv, len; dpvs_ctrl_func = dpvs_get_services; @@ -429,11 +429,11 @@ dpvs_service_table_t* dpvs_get_services(dpvs_service_table_t* svcs) { assert(svcs); if (ESOCKOPT_OK != dpvs_getsockopt(DPVS_SO_GET_SERVICES, svcs, - sizeof(dpvs_service_table_t), (void**)&rcv, &lrcv)) { + sizeof(dpvs_agent_services_front_t), (void**)&rcv, &lrcv)) { return NULL; } - len = svcs->num_services * sizeof(dpvs_service_compat_t) + sizeof(dpvs_service_table_t); + len = svcs->count * sizeof(dpvs_service_compat_t) + sizeof(dpvs_agent_services_front_t); memcpy(svcs, rcv, len < lrcv ? len : lrcv); @@ -531,9 +531,9 @@ dpvs_cmp_dests(dpvs_dest_compat_t *d1, dpvs_dest_compat_t *d2) return ntohs(d1->port) - ntohs(d2->port); } -void dpvs_sort_services(dpvs_service_table_t *s, dpvs_service_cmp_t f) +void dpvs_sort_services(dpvs_agent_services_front_t *s, dpvs_service_cmp_t f) { - qsort(s->entrytable, s->num_services, + qsort(s->entrytable, s->count, sizeof(dpvs_service_compat_t), (qsort_cmp_t)f); } diff --git a/tools/keepalived/keepalived/include/libipvs.h b/tools/keepalived/keepalived/include/libipvs.h index 8955de1e3..870884b9c 100644 --- a/tools/keepalived/keepalived/include/libipvs.h +++ b/tools/keepalived/keepalived/include/libipvs.h @@ -138,7 +138,7 @@ extern int dpvs_start_daemon(ipvs_daemon_t *dm); extern int dpvs_stop_daemon(ipvs_daemon_t *dm); /* get all the ipvs services */ -extern dpvs_service_table_t *dpvs_get_services(dpvs_service_table_t *t); +extern dpvs_agent_services_front_t *dpvs_get_services(dpvs_agent_services_front_t *t); /* get the destination array of the specified service */ extern dpvs_dest_table_t* dpvs_get_dests(dpvs_dest_table_t* table); @@ -166,7 +166,7 @@ extern int dpvs_set_ipaddr(struct inet_addr_param *param, int cmd); extern struct dp_vs_blklst_conf_array *dpvs_get_blklsts(void); typedef int (*dpvs_service_cmp_t)(dpvs_service_compat_t *,dpvs_service_compat_t*); -extern void dpvs_sort_services(dpvs_service_table_t *s, dpvs_service_cmp_t f); +extern void dpvs_sort_services(dpvs_agent_services_front_t *s, dpvs_service_cmp_t f); extern int dpvs_cmp_services(dpvs_service_compat_t *s1, dpvs_service_compat_t *s2); typedef int (*dpvs_dest_cmp_t)(dpvs_dest_compat_t*, dpvs_dest_compat_t*); From 73d5de0ef5b242539583ceeb54a41777278b815b Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 6 Mar 2023 18:49:17 +0800 Subject: [PATCH 004/105] deregister agent_ifa_sockopts in inetaddr.init error return --- src/inetaddr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/inetaddr.c b/src/inetaddr.c index 53e1281c6..ee73fb4b2 100644 --- a/src/inetaddr.c +++ b/src/inetaddr.c @@ -2070,6 +2070,7 @@ int inet_addr_init(void) break; } } + sockopt_unregister(&agent_ifa_sockopts); sockopt_unregister(&ifa_sockopts); return err; } From c2d0a2b24804018752d927ef1f13930b0e46ec47 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 6 Mar 2023 20:36:38 +0800 Subject: [PATCH 005/105] deregister dest lcore unicast msg of init error and term --- src/ipvs/ip_vs_dest.c | 74 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 10 deletions(-) diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index cf4c907d3..7e5209201 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -173,12 +173,12 @@ dp_vs_dest_edit(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest) uint32_t old_weight; if (udest->weight < 0) { - RTE_LOG(DEBUG, SERVICE,"%s(): server weight less than zero\n", __func__); + RTE_LOG(DEBUG, SERVICE, "%s(): server weight less than zero\n", __func__); return EDPVS_INVAL; } if (udest->min_conn > udest->max_conn) { - RTE_LOG(DEBUG, SERVICE,"%s(): lower threshold is higher than upper threshold\n", + RTE_LOG(DEBUG, SERVICE, "%s(): lower threshold is higher than upper threshold\n", __func__); return EDPVS_INVAL; } @@ -191,7 +191,7 @@ dp_vs_dest_edit(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest) dest = dp_vs_dest_lookup(udest->af, svc, &daddr, dport); if (dest == NULL) { - RTE_LOG(DEBUG, SERVICE,"%s(): dest doesn't exist\n", __func__); + RTE_LOG(DEBUG, SERVICE, "%s(): dest doesn't exist\n", __func__); return EDPVS_NOTEXIST; } @@ -489,19 +489,23 @@ static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void ** return EDPVS_NOTEXIST; } - size = sizeof(*insvc) + getsvc->num_dests*sizeof(struct dp_vs_dest_detail); + if (getsvc->num_dests != insvc->num_dests) { + msg_destroy(&msg); + return EDPVS_INVAL; + } + *out = rte_zmalloc("get_dests", size, 0); if (!*out) { msg_destroy(&msg); return EDPVS_NOMEM; } - rte_memcpy(*out, insvc, sizeof(insvc)); + rte_memcpy(*out, insvc, sizeof(*insvc)); outsvc = (struct dp_vs_dest_front*)*out; outsvc->cid = rte_lcore_id(); outsvc->index = g_lcore_id2index[outsvc->cid]; outsvc->num_dests = getsvc->num_dests; - outdest = (struct dp_vs_dest_detail*)(*out + sizeof(outsvc)); + outdest = (struct dp_vs_dest_detail*)(*out + sizeof(*outsvc)); list_for_each_entry(dest, &getsvc->dests, n_list) { outdest->af = dest->af; @@ -526,7 +530,7 @@ static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void ** list_for_each_entry(cur, &reply->mq, mq_node) { slave_dest = (struct dp_vs_dest_detail*)(cur->data + sizeof(struct dp_vs_dest_front)); - outdest = (struct dp_vs_dest_detail*)(*out + sizeof(outsvc)); + outdest = (struct dp_vs_dest_detail*)(*out + sizeof(*outsvc)); for (i = 0; i < outsvc->num_dests; i++) { outdest->max_conn += slave_dest->max_conn; outdest->min_conn += slave_dest->min_conn; @@ -554,6 +558,7 @@ static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void ** front = (struct dp_vs_dest_front*)cur->data; if (cid == front->cid) { rte_memcpy(*out, cur->data, size); + break; } } *outlen = size; @@ -612,10 +617,54 @@ static int dp_vs_dests_get_uc_cb(struct dpvs_msg *msg) return EDPVS_OK; } +static int dest_unregister_msg_cb(void) +{ + struct dpvs_msg_type msg_type; + int err = EDPVS_OK; + + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_ADD_DESTS; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = adddest_msg_cb; + err = msg_type_mc_unregister(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to unregister msg.\n", __func__); + return err; + } + + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_DEL_DESTS; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = deldest_msg_cb; + err = msg_type_mc_unregister(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } + + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_GET_DESTS; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_LOW; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = dp_vs_dests_get_uc_cb; + err = msg_type_mc_register(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } + + return EDPVS_OK; +} + int dp_vs_dest_init(void) { - int err; struct dpvs_msg_type msg_type; + int err = EDPVS_OK; memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_ADD_DESTS; @@ -644,7 +693,7 @@ int dp_vs_dest_init(void) memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_GET_DESTS; msg_type.mode = DPVS_MSG_MULTICAST; - msg_type.prio = MSG_PRIO_NORM; + msg_type.prio = MSG_PRIO_LOW; msg_type.cid = rte_lcore_id(); msg_type.unicast_msg_cb = dp_vs_dests_get_uc_cb; err = msg_type_mc_register(&msg_type); @@ -653,10 +702,15 @@ int dp_vs_dest_init(void) return err; } - return sockopt_register(&sockopts_dest); + if ((err = sockopt_register(&sockopts_dest)) != EDPVS_OK) { + dest_unregister_msg_cb(); + return err; + } + return err; } int dp_vs_dest_term(void) { + dest_unregister_msg_cb(); return sockopt_unregister(&sockopts_dest); } From 9103d89fd25e1b7b36c350b7f5501633ebef7a74 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Tue, 7 Mar 2023 13:22:18 +0800 Subject: [PATCH 006/105] remove useless code --- src/ipvs/ip_vs_laddr.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/ipvs/ip_vs_laddr.c b/src/ipvs/ip_vs_laddr.c index 2f3a2a78b..d35b13d49 100644 --- a/src/ipvs/ip_vs_laddr.c +++ b/src/ipvs/ip_vs_laddr.c @@ -501,13 +501,7 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) if (cid == rte_get_main_lcore()) { struct dpvs_msg *msg; - if (opt == DPVSAGENT_VS_ADD_LADDR) { - msg = msg_make(MSG_TYPE_AGENT_ADD_LADDR, laddr_msg_seq(), DPVS_MSG_MULTICAST, cid, size, conf); - } else if (opt == DPVSAGENT_VS_DEL_LADDR) { - msg = msg_make(MSG_TYPE_AGENT_DEL_LADDR, laddr_msg_seq(), DPVS_MSG_MULTICAST, cid, size, conf); - } else { - msg = msg_make(set_opt_so2msg(opt), laddr_msg_seq(), DPVS_MSG_MULTICAST, cid, size, conf); - } + msg = msg_make(set_opt_so2msg(opt), laddr_msg_seq(), DPVS_MSG_MULTICAST, cid, size, conf); if (!msg) return EDPVS_NOMEM; @@ -528,7 +522,6 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) fwmark = (uint32_t)laddr_front->fwmark; addr = &laddr_front->addr; match = &laddr_front->match; - details = (struct dp_vs_laddr_detail*)((char*)conf + sizeof(struct dp_vs_laddr_front)); } else { af = (int)laddr_conf->af_s; proto = (uint16_t)laddr_conf->proto; @@ -825,10 +818,14 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, laddr_front = conf; if (!conf || size != sizeof(*laddr_front)) return EDPVS_INVAL; + msg = msg_make(MSG_TYPE_AGENT_GET_LADDR, 0, DPVS_MSG_MULTICAST, rte_lcore_id(), sizeof(struct dp_vs_laddr_front), laddr_front); if (!msg) return EDPVS_NOMEM; + if (rte_lcore_id() != rte_get_main_lcore()) + return EDPVS_INVAL; + err = multicast_msg_send(msg, 0, &reply); if (err != EDPVS_OK) { msg_destroy(&msg); @@ -876,6 +873,7 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, msg_destroy(&msg); rte_free(*out); *out = NULL; + RTE_LOG(ERR, SERVICE, "%s: The count(%d) of laddr in core(id = %d) not equal as main core laddr count(%d)\n", __func__, iter_front->count, iter_front->cid, out_front->count); return EDPVS_INVAL; } for (i = 0; i < out_front->count; i++) { From 3e0b545bf2858b54c20403ad0a9781e18412a642 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 20 Mar 2023 13:56:48 +0800 Subject: [PATCH 007/105] dpvs-agent not put the count of realserver in sockopt DPVSAGENT_VS_GET_DESTS, we had set outlen after hit the vs --- src/ipvs/ip_vs_dest.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 7e5209201..a76d5bc50 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -482,17 +482,12 @@ static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void ** } if (cid == rte_get_main_lcore()) { - // getsvc = dp_vs_service_get_lcore(&outsvc, cid); getsvc = dp_vs_service_lookup(insvc->af, insvc->proto, &insvc->addr, insvc->port, insvc->fwmark, NULL, &insvc->match, NULL, cid); if (!getsvc) { msg_destroy(&msg); return EDPVS_NOTEXIST; } - - if (getsvc->num_dests != insvc->num_dests) { - msg_destroy(&msg); - return EDPVS_INVAL; - } + size = sizeof(*insvc) + getsvc->num_dests*sizeof(struct dp_vs_dest_detail); *out = rte_zmalloc("get_dests", size, 0); if (!*out) { @@ -594,10 +589,6 @@ static int dp_vs_dests_get_uc_cb(struct dpvs_msg *msg) svc = dp_vs_service_lookup(get->af, get->proto, &get->addr, get->port, get->fwmark, NULL, &get->match, NULL, cid); if (!svc) return EDPVS_NOTEXIST; - if (svc->num_dests != get->num_dests) { - RTE_LOG(ERR, SERVICE, "%s: dests number not match in cid=%d.\n", __func__, cid); - return EDPVS_INVAL; - } size = sizeof(*get) + sizeof(struct dp_vs_dest_detail) * (svc->num_dests); output = msg_reply_alloc(size); From 76815f96af01086216ee3d7d97c302e04e1d249e Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 20 Mar 2023 15:27:49 +0800 Subject: [PATCH 008/105] consistency with dpvs agent memory layout --- include/conf/blklst.h | 9 +++++---- include/conf/netif.h | 18 ++++++++++-------- include/conf/whtlst.h | 9 +++++---- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/conf/blklst.h b/include/conf/blklst.h index 7b10d868b..2b2c9a044 100644 --- a/include/conf/blklst.h +++ b/include/conf/blklst.h @@ -31,14 +31,15 @@ struct dp_vs_blklst_entry { typedef struct dp_vs_blklst_conf { /* identify service */ - int af; - uint8_t proto; + union inet_addr blklst; union inet_addr vaddr; - uint16_t vport; + int af; uint32_t fwmark; + uint16_t vport; + uint8_t proto; + uint8_t padding; /* for set */ - union inet_addr blklst; } dpvs_blklst_t; struct dp_vs_blklst_conf_array { diff --git a/include/conf/netif.h b/include/conf/netif.h index dd0d3a7e4..e405124ae 100644 --- a/include/conf/netif.h +++ b/include/conf/netif.h @@ -90,17 +90,18 @@ typedef struct netif_nic_list_get /* basic nic info specified by port_id */ typedef struct netif_nic_basic_get { - portid_t port_id; - char name[32]; + char name[0x20]; + char addr[0x20]; + char link_status[0x10]; + char link_duplex[0x10]; + char link_autoneg[0x10]; + uint32_t link_speed; /* ETH_SPEED_NUM_ */ uint8_t nrxq; uint8_t ntxq; - char addr[32]; + uint8_t padding[0x3]; uint8_t socket_id; + portid_t port_id; uint16_t mtu; - uint32_t link_speed; /* ETH_SPEED_NUM_ */ - char link_status[16]; - char link_duplex[16]; - char link_autoneg[16]; uint16_t promisc:1; /* promiscuous mode */ uint16_t fwd2kni:1; uint16_t tc_egress:1; @@ -113,7 +114,6 @@ typedef struct netif_nic_basic_get /* nic statistics specified by port_id */ typedef struct netif_nic_stats_get { - portid_t port_id; uint32_t mbuf_avail;/* Number of available mbuf in pktmempool */ uint32_t mbuf_inuse;/* Number of used mbuf in pktmempool */ uint64_t ipackets; /* Total number of successfully received packets. */ @@ -136,6 +136,8 @@ typedef struct netif_nic_stats_get { /* Total number of successfully transmitted queue bytes. */ uint64_t q_errors[RTE_ETHDEV_QUEUE_STAT_CNTRS]; /* Total number of queue packets received that are dropped. */ + uint16_t padding[0x3]; + portid_t port_id; } netif_nic_stats_get_t; /* dev info specified by port_id */ diff --git a/include/conf/whtlst.h b/include/conf/whtlst.h index a66ecd741..8da9f4d57 100644 --- a/include/conf/whtlst.h +++ b/include/conf/whtlst.h @@ -29,14 +29,15 @@ struct dp_vs_whtlst_entry { typedef struct dp_vs_whtlst_conf { /* identify service */ - int af; - uint8_t proto; + union inet_addr whtlst; union inet_addr vaddr; - uint16_t vport; + int af; uint32_t fwmark; + uint16_t vport; + uint8_t proto; + uint8_t padding; /* for set */ - union inet_addr whtlst; } dpvs_whtlst_t; struct dp_vs_whtlst_conf_array { From 27e066f962e7d2acfe2e5fd3ba0da85a31c65428 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 10 May 2023 16:14:38 +0800 Subject: [PATCH 009/105] add config macro CONFIG_DPVS_AGENT to enable/disable dpvs-agent on compiling, and fix some bugs Signed-off-by: ywc689 --- include/conf/dest.h | 10 ++- include/conf/inetaddr.h | 2 + include/conf/laddr.h | 2 + include/conf/service.h | 4 +- include/conf/sockopts.h | 20 ++--- include/ctrl.h | 4 +- src/config.mk | 1 + src/inetaddr.c | 28 +++++- src/ipv6/route6.c | 16 +++- src/ipvs/ip_vs_dest.c | 78 +++++++++-------- src/ipvs/ip_vs_laddr.c | 75 ++++++++++------ src/ipvs/ip_vs_service.c | 85 +++++++------------ src/route.c | 14 ++- tools/dpip/route.c | 9 +- tools/ipvsadm/ipvsadm.c | 16 ++-- tools/keepalived/keepalived/check/libipvs.c | 10 +-- tools/keepalived/keepalived/include/libipvs.h | 4 +- 17 files changed, 214 insertions(+), 164 deletions(-) diff --git a/include/conf/dest.h b/include/conf/dest.h index 36fadde09..827dcd77e 100644 --- a/include/conf/dest.h +++ b/include/conf/dest.h @@ -90,6 +90,11 @@ typedef struct dp_vs_dest_table { dpvs_dest_compat_t entrytable[0]; } dpvs_dest_table_t; +#define dp_vs_get_dests dp_vs_dest_table +#define dp_vs_dest_entry dp_vs_dest_compat +#define dp_vs_dest_conf dp_vs_dest_compat + +#ifdef CONFIG_DPVS_AGENT typedef struct dp_vs_dest_front { uint32_t af; uint16_t proto; @@ -101,10 +106,7 @@ typedef struct dp_vs_dest_front { uint32_t cid; uint32_t index; } dpvs_dest_front_t; - -#define dp_vs_get_dests dp_vs_dest_table -#define dp_vs_dest_entry dp_vs_dest_compat -#define dp_vs_dest_conf dp_vs_dest_compat #define dp_vs_dest_detail dp_vs_dest_compat +#endif #endif /* __DPVS_DEST_CONF_H__ */ diff --git a/include/conf/inetaddr.h b/include/conf/inetaddr.h index 7f9eb5abc..f97994f86 100644 --- a/include/conf/inetaddr.h +++ b/include/conf/inetaddr.h @@ -86,6 +86,7 @@ struct inet_addr_data_array { struct inet_addr_data addrs[0]; } __attribute__((__packed__)); +#ifdef CONFIG_DPVS_AGENT struct inet_addr_stats_detail { union inet_addr addr; uint32_t sa_used; @@ -97,5 +98,6 @@ struct inet_addr_front { int count; int data[0]; }; +#endif /* CONFIG_DPVS_AGENT */ #endif /* __DPVS_INETADDR_CONF_H__ */ diff --git a/include/conf/laddr.h b/include/conf/laddr.h index bebe51b4e..98b73cbe7 100644 --- a/include/conf/laddr.h +++ b/include/conf/laddr.h @@ -56,6 +56,7 @@ typedef struct dp_vs_laddr_conf { struct dp_vs_laddr_entry laddrs[0]; } dpvs_laddr_table_t; +#ifdef CONFIG_DPVS_AGENT typedef struct dp_vs_laddr_detail { uint32_t af; uint32_t conns; @@ -75,5 +76,6 @@ typedef struct dp_vs_laddr_front { struct dp_vs_match match; struct dp_vs_laddr_detail laddrs[0]; } dpvs_laddr_front_t; +#endif /* CONFIG_DPVS_AGENT */ #endif /* __DPVS_LADDR_CONF_H__ */ diff --git a/include/conf/service.h b/include/conf/service.h index c50908e18..12ae409b3 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -74,12 +74,12 @@ typedef struct dp_vs_service_compat { #define dp_vs_service_entry dp_vs_service_compat #define dp_vs_service_user dp_vs_service_compat -typedef struct dp_vs_agent_services_front { +typedef struct dp_vs_services_front { lcoreid_t cid; lcoreid_t index; uint16_t count; dpvs_service_compat_t entrytable[0]; -} dpvs_agent_services_front_t; +} dpvs_services_front_t; struct dp_vs_getinfo { unsigned int version; diff --git a/include/conf/sockopts.h b/include/conf/sockopts.h index 36067053e..9a0a7e035 100644 --- a/include/conf/sockopts.h +++ b/include/conf/sockopts.h @@ -55,6 +55,16 @@ DPVSMSG(DPVSAGENT_VS_ADD_DESTS) \ DPVSMSG(DPVSAGENT_VS_DEL_DESTS) \ \ + DPVSMSG(SOCKOPT_SET_ROUTE_ADD) \ + DPVSMSG(SOCKOPT_SET_ROUTE_DEL) \ + DPVSMSG(SOCKOPT_SET_ROUTE_SET) \ + DPVSMSG(SOCKOPT_SET_ROUTE_FLUSH)\ + DPVSMSG(SOCKOPT_GET_ROUTE_SHOW) \ + \ + DPVSMSG(SOCKOPT_SET_ROUTE6_ADD_DEL) \ + DPVSMSG(SOCKOPT_SET_ROUTE6_FLUSH) \ + DPVSMSG(SOCKOPT_GET_ROUTE6_SHOW) \ + \ DPVSMSG(DPVSAGENT_ROUTE_GET) \ DPVSMSG(DPVSAGENT_ROUTE_ADD) \ DPVSMSG(DPVSAGENT_ROUTE_DEL) \ @@ -68,12 +78,6 @@ DPVSMSG(DPVSAGENT_IFADDR_ADD) \ DPVSMSG(DPVSAGENT_IFADDR_DEL) \ \ - DPVSMSG(SOCKOPT_SET_ROUTE_ADD) \ - DPVSMSG(SOCKOPT_SET_ROUTE_DEL) \ - DPVSMSG(SOCKOPT_SET_ROUTE_SET) \ - DPVSMSG(SOCKOPT_SET_ROUTE_FLUSH)\ - DPVSMSG(SOCKOPT_GET_ROUTE_SHOW) \ - \ DPVSMSG(SOCKOPT_SET_IFADDR_ADD) \ DPVSMSG(SOCKOPT_SET_IFADDR_DEL) \ DPVSMSG(SOCKOPT_SET_IFADDR_SET) \ @@ -140,10 +144,6 @@ DPVSMSG(SOCKOPT_GET_IPSET_TEST) \ DPVSMSG(SOCKOPT_GET_IPSET_LIST) \ \ - DPVSMSG(SOCKOPT_SET_ROUTE6_ADD_DEL) \ - DPVSMSG(SOCKOPT_SET_ROUTE6_FLUSH) \ - DPVSMSG(SOCKOPT_GET_ROUTE6_SHOW) \ - \ DPVSMSG(SOCKOPT_SET_IFTRAF_ADD) \ DPVSMSG(SOCKOPT_SET_IFTRAF_DEL) \ DPVSMSG(SOCKOPT_GET_IFTRAF_SHOW)\ diff --git a/include/ctrl.h b/include/ctrl.h index 9162bdea1..eb383df13 100644 --- a/include/ctrl.h +++ b/include/ctrl.h @@ -230,13 +230,15 @@ enum { MSG_TYPE_SVC_GET_SERVICES, MSG_TYPE_SVC_GET_SERVICE, MSG_TYPE_SVC_GET_DESTS, - MSG_TYPE_AGENT_GET_DESTS, MSG_TYPE_LADDR_GET_ALL, +#ifdef CONFIG_DPVS_AGENT + MSG_TYPE_AGENT_GET_DESTS, MSG_TYPE_AGENT_GET_LADDR, MSG_TYPE_AGENT_ADD_LADDR, MSG_TYPE_AGENT_DEL_LADDR, MSG_TYPE_AGENT_ADD_DESTS, MSG_TYPE_AGENT_DEL_DESTS, +#endif }; #define MSG_TYPE_SVC_SET_BASE MSG_TYPE_SVC_SET_FLUSH diff --git a/src/config.mk b/src/config.mk index 9c291739a..0d9c47f06 100644 --- a/src/config.mk +++ b/src/config.mk @@ -29,6 +29,7 @@ CFLAGS += -D DPVS_MAX_LCORE=64 CFLAGS += -D CONFIG_DPVS_LOG #CFLAGS += -D CONFIG_ICMP_REDIRECT_CORE +#CFLAGS += -D CONFIG_DPVS_AGENT #CFLAGS += -D CONFIG_DPVS_NEIGH_DEBUG #CFLAGS += -D CONFIG_RECORD_BIG_LOOP diff --git a/src/inetaddr.c b/src/inetaddr.c index ee73fb4b2..4f47dcabb 100644 --- a/src/inetaddr.c +++ b/src/inetaddr.c @@ -1121,6 +1121,7 @@ static void fill_ifaddr_entry(lcoreid_t cid, const struct inet_ifaddr *ifa, stru } } +#ifdef CONFIG_DPVS_AGENT static void fill_ifaddr_basic(lcoreid_t cid, const struct inet_ifaddr *ifa, struct inet_addr_entry *entry) { entry->af = ifa->af; @@ -1167,6 +1168,7 @@ static int agent_copy_lcore_entries(const struct inet_device *idev, struct inet_ } return EDPVS_OK; } +#endif /* CONFIG_DPVS_AGENT */ static int copy_lcore_entries(const struct inet_device *idev, int max_entries, struct inet_addr_data_array *array) @@ -1526,6 +1528,8 @@ static int inet_addr_sync(const struct ifaddr_action *param) return err; } + +#ifdef CONFIG_DPVS_AGENT static int ifaddr_agent_get_basic(struct inet_device *idev, struct inet_addr_front** parray, int *plen) { lcoreid_t cid; @@ -1558,6 +1562,7 @@ static int ifaddr_agent_get_basic(struct inet_device *idev, struct inet_addr_fro *plen = len; return EDPVS_OK; } +#endif /* CONFIG_DPVS_AGENT */ static int ifaddr_get_basic(struct inet_device *idev, struct inet_addr_data_array **parray, int *plen) { @@ -1590,6 +1595,7 @@ static int ifaddr_get_basic(struct inet_device *idev, struct inet_addr_data_arra return EDPVS_OK; } +#ifdef CONFIG_DPVS_AGENT static int ifaddr_agent_get_stats(struct inet_device *idev, struct inet_addr_front **parray, int *plen) { int err, i; @@ -1656,6 +1662,7 @@ static int ifaddr_agent_get_stats(struct inet_device *idev, struct inet_addr_fro } return err; } +#endif /* CONFIG_DPVS_AGENT */ static int ifaddr_get_stats(struct inet_device *idev, struct inet_addr_data_array **parray, int *plen) { @@ -1799,8 +1806,12 @@ static int ifa_sockopt_set(sockoptid_t opt, const void *conf, size_t size) if (opt >= SOCKOPT_SET_IFADDR_ADD && opt <= SOCKOPT_SET_IFADDR_FLUSH) entry = ¶m->ifa_entry; +#ifdef CONFIG_DPVS_AGENT else if (opt >= DPVSAGENT_IFADDR_ADD && opt <= DPVSAGENT_IFADDR_DEL) entry = conf; +#endif + else + return EDPVS_INVAL; if (opt != SOCKOPT_SET_IFADDR_FLUSH) { if (!ifa_prefix_check(entry->af, @@ -1821,8 +1832,10 @@ static int ifa_sockopt_set(sockoptid_t opt, const void *conf, size_t size) } switch (opt) { +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_IFADDR_ADD: /*fallthrough*/ +#endif case SOCKOPT_SET_IFADDR_ADD: return inet_addr_add(entry->af, dev, &entry->addr, @@ -1832,9 +1845,10 @@ static int ifa_sockopt_set(sockoptid_t opt, const void *conf, size_t size) entry->prefered_lft, entry->scope, entry->flags); - +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_IFADDR_DEL: /*fallthrough*/ +#endif case SOCKOPT_SET_IFADDR_DEL: return inet_addr_del(entry->af, dev, &entry->addr, @@ -1852,7 +1866,6 @@ static int ifa_sockopt_set(sockoptid_t opt, const void *conf, size_t size) case SOCKOPT_SET_IFADDR_FLUSH: return inet_addr_flush(entry->af, dev); - default: return EDPVS_NOTSUPP; } @@ -1860,6 +1873,7 @@ static int ifa_sockopt_set(sockoptid_t opt, const void *conf, size_t size) return EDPVS_OK; } +#ifdef CONFIG_DPVS_AGENT static int ifa_sockopt_agent_get(sockoptid_t opt, const void *conf, size_t size, void **out, size_t *outsize) { struct netif_port *dev; struct inet_device *idev = NULL; @@ -1907,6 +1921,7 @@ static int ifa_sockopt_agent_get(sockoptid_t opt, const void *conf, size_t size, *outsize = len; return EDPVS_OK; } +#endif /* CONFIG_DPVS_AGENT */ static int ifa_sockopt_get(sockoptid_t opt, const void *conf, size_t size, void **out, size_t *outsize) @@ -1996,6 +2011,7 @@ static struct dpvs_msg_type ifa_msg_types[] = { } }; +#ifdef CONFIG_DPVS_AGENT static struct dpvs_sockopts agent_ifa_sockopts = { .version = SOCKOPT_VERSION, .set_opt_min = DPVSAGENT_IFADDR_ADD, @@ -2005,6 +2021,7 @@ static struct dpvs_sockopts agent_ifa_sockopts = { .get_opt_max = DPVSAGENT_IFADDR_GET_VERBOSE, .get = ifa_sockopt_agent_get, }; +#endif static struct dpvs_sockopts ifa_sockopts = { .version = SOCKOPT_VERSION, @@ -2038,12 +2055,14 @@ int inet_addr_init(void) return err; } +#ifdef CONFIG_DPVS_AGENT if ((err = sockopt_register(&agent_ifa_sockopts)) != EDPVS_OK) { RTE_LOG(ERR, IFA, "%s: fail to register agent_ifa_sockopts -- %s\n", __func__, dpvs_strerror(err)); sockopt_unregister(&ifa_sockopts); return err; } +#endif for (ii = 0; ii < NELEMS(ifa_msg_types); ii++) { switch (ifa_msg_types[ii].mode) { @@ -2070,7 +2089,9 @@ int inet_addr_init(void) break; } } +#ifdef CONFIG_DPVS_AGENT sockopt_unregister(&agent_ifa_sockopts); +#endif sockopt_unregister(&ifa_sockopts); return err; } @@ -2084,10 +2105,13 @@ int inet_addr_term(void) int ii, err = EDPVS_OK; /* TODO: flush all address */ + +#ifdef CONFIG_DPVS_AGENT if ((err = sockopt_unregister(&agent_ifa_sockopts)) != EDPVS_OK) { RTE_LOG(ERR, IFA, "%s: fail to unregister ifa_sockopts -- %s\n", __func__, dpvs_strerror(err)); } +#endif if ((err = sockopt_unregister(&ifa_sockopts)) != EDPVS_OK) { RTE_LOG(ERR, IFA, "%s: fail to unregister ifa_sockopts -- %s\n", diff --git a/src/ipv6/route6.c b/src/ipv6/route6.c index c06b36514..0c3d06d79 100644 --- a/src/ipv6/route6.c +++ b/src/ipv6/route6.c @@ -345,9 +345,11 @@ static bool rt6_conf_check(const struct dp_vs_route6_conf *rt6_cfg) static int rt6_sockopt_set(sockoptid_t opt, const void *in, size_t inlen) { const struct dp_vs_route6_conf *rt6_cfg_in = in; - const struct dp_vs_route_detail *detail = in; struct dp_vs_route6_conf rt6_cfg; +#ifdef CONFIG_DPVS_AGENT + const struct dp_vs_route_detail *detail = in; + if (opt == DPVSAGENT_ROUTE6_ADD || opt == DPVSAGENT_ROUTE6_DEL) { memcpy(&rt6_cfg.dst, &detail->dst, sizeof(rt_addr_t)); memcpy(&rt6_cfg.src, &detail->src, sizeof(rt_addr_t)); @@ -360,19 +362,24 @@ static int rt6_sockopt_set(sockoptid_t opt, const void *in, size_t inlen) rt6_zero_prefix_tail(&rt6_cfg.dst); } else { +#endif if (!rt6_conf_check(rt6_cfg_in)) { RTE_LOG(INFO, RT6, "%s: invalid route6 sockopt!\n", __func__); return EDPVS_INVAL; } rt6_cfg_zero_prefix_tail(rt6_cfg_in, &rt6_cfg); +#ifdef CONFIG_DPVS_AGENT } +#endif switch (opt) { +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_ROUTE6_ADD: /*fallthrough*/ case DPVSAGENT_ROUTE6_DEL: /*fallthrough*/ +#endif case SOCKOPT_SET_ROUTE6_ADD_DEL: return rt6_add_del(&rt6_cfg); case SOCKOPT_SET_ROUTE6_FLUSH: @@ -391,6 +398,7 @@ static int rt6_sockopt_get(sockoptid_t opt, const void *in, size_t inlen, return EDPVS_OK; } +#ifdef CONFIG_DPVS_AGENT static struct dpvs_sockopts agent_route6_sockopts = { .version = SOCKOPT_VERSION, .set_opt_min = DPVSAGENT_ROUTE6_ADD, @@ -400,6 +408,7 @@ static struct dpvs_sockopts agent_route6_sockopts = { .get_opt_max = DPVSAGENT_ROUTE6_GET, .get = rt6_sockopt_get, }; +#endif static struct dpvs_sockopts route6_sockopts = { .version = SOCKOPT_VERSION, @@ -467,11 +476,12 @@ int route6_init(void) return err; } +#ifdef CONFIG_DPVS_AGENT if ((err = sockopt_register(&agent_route6_sockopts)) != EDPVS_OK) { RTE_LOG(ERR, RT6, "%s: fail to register route6 sockopt!\n", __func__); return err; } - +#endif return EDPVS_OK; } @@ -484,8 +494,10 @@ int route6_term(void) rt6_method_term(); +#ifdef CONFIG_DPVS_AGENT if ((err = sockopt_unregister(&agent_route6_sockopts)) != EDPVS_OK) RTE_LOG(WARNING, RT6, "%s: fail to unregister route6 sockopt!\n", __func__); +#endif if ((err = sockopt_unregister(&route6_sockopts)) != EDPVS_OK) RTE_LOG(WARNING, RT6, "%s: fail to unregister route6 sockopt!\n", __func__); diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index a76d5bc50..34a1fc46c 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -322,13 +322,14 @@ int dp_vs_dest_get_entries(const struct dp_vs_service *svc, return ret; } +#ifdef CONFIG_DPVS_AGENT static int dp_vs_dest_get_details(const struct dp_vs_service *svc, struct dp_vs_dest_front *uptr) { int ret = 0; int count = 0; struct dp_vs_dest *dest; - struct dp_vs_dest_entry entry, *detail; + struct dp_vs_dest_entry *detail; uptr->cid = rte_lcore_id(); uptr->index = g_lcore_id2index[uptr->cid]; @@ -338,22 +339,20 @@ static int dp_vs_dest_get_details(const struct dp_vs_service *svc, list_for_each_entry(dest, &svc->dests, n_list){ if(count >= svc->num_dests) break; - memset(&entry, 0, sizeof(entry)); - entry.af = dest->af; - entry.addr = dest->addr; - entry.port = dest->port; - entry.conn_flags = dest->fwdmode; - entry.weight = rte_atomic16_read(&dest->weight); - entry.max_conn = dest->max_conn; - entry.min_conn = dest->min_conn; - entry.actconns = rte_atomic32_read(&dest->actconns); - entry.inactconns = rte_atomic32_read(&dest->inactconns); - entry.persistconns = rte_atomic32_read(&dest->persistconns); - ret = dp_vs_stats_add(&(entry.stats), &dest->stats); - if (ret != EDPVS_OK) + memset(detail, 0, sizeof(*detail)); + detail->af = dest->af; + detail->addr = dest->addr; + detail->port = dest->port; + detail->conn_flags = dest->fwdmode; + detail->weight = rte_atomic16_read(&dest->weight); + detail->max_conn = dest->max_conn; + detail->min_conn = dest->min_conn; + detail->actconns = rte_atomic32_read(&dest->actconns); + detail->inactconns = rte_atomic32_read(&dest->inactconns); + detail->persistconns = rte_atomic32_read(&dest->persistconns); + ret = dp_vs_stats_add(&detail->stats, &dest->stats); + if (unlikely(ret != EDPVS_OK)) break; - - memcpy(detail, &entry, sizeof(entry)); detail += 1; count++; } @@ -361,19 +360,6 @@ static int dp_vs_dest_get_details(const struct dp_vs_service *svc, return ret; } -static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len); -static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void **out, size_t *outlen); - -struct dpvs_sockopts sockopts_dest = { - .version = SOCKOPT_VERSION, - .set_opt_min = DPVSAGENT_VS_ADD_DESTS, - .set_opt_max = DPVSAGENT_VS_DEL_DESTS, - .set = dp_vs_dest_set, - .get_opt_min = DPVSAGENT_VS_GET_DESTS, - .get_opt_max = DPVSAGENT_VS_GET_DESTS, - .get = dp_vs_dest_get, -}; - static int dest_msg_seq(void) { static uint32_t seq = 0; return seq++; @@ -453,6 +439,8 @@ static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void ** struct dpvs_multicast_queue *reply = NULL; lcoreid_t cid; + *out = NULL; + *outlen = 0; switch (opt) { case DPVSAGENT_VS_GET_DESTS: insvc = (struct dp_vs_dest_front*)user; @@ -611,7 +599,7 @@ static int dp_vs_dests_get_uc_cb(struct dpvs_msg *msg) static int dest_unregister_msg_cb(void) { struct dpvs_msg_type msg_type; - int err = EDPVS_OK; + int err, rterr = EDPVS_OK; memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_ADD_DESTS; @@ -622,7 +610,7 @@ static int dest_unregister_msg_cb(void) err = msg_type_mc_unregister(&msg_type); if (err != EDPVS_OK) { RTE_LOG(ERR, SERVICE, "%s: fail to unregister msg.\n", __func__); - return err; + rterr = err; } memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); @@ -634,7 +622,8 @@ static int dest_unregister_msg_cb(void) err = msg_type_mc_unregister(&msg_type); if (err != EDPVS_OK) { RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); - return err; + if (rterr == EDPVS_OK) + rterr = err; } memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); @@ -646,16 +635,30 @@ static int dest_unregister_msg_cb(void) err = msg_type_mc_register(&msg_type); if (err != EDPVS_OK) { RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); - return err; + if (rterr == EDPVS_OK) + rterr = err; } - return EDPVS_OK; + return rterr; } +struct dpvs_sockopts sockopts_dest = { + .version = SOCKOPT_VERSION, + .set_opt_min = DPVSAGENT_VS_ADD_DESTS, + .set_opt_max = DPVSAGENT_VS_DEL_DESTS, + .set = dp_vs_dest_set, + .get_opt_min = DPVSAGENT_VS_GET_DESTS, + .get_opt_max = DPVSAGENT_VS_GET_DESTS, + .get = dp_vs_dest_get, +}; + +#endif /* CONFIG_DPVS_AGENT */ + int dp_vs_dest_init(void) { - struct dpvs_msg_type msg_type; int err = EDPVS_OK; +#ifdef CONFIG_DPVS_AGENT + struct dpvs_msg_type msg_type; memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_ADD_DESTS; @@ -697,11 +700,16 @@ int dp_vs_dest_init(void) dest_unregister_msg_cb(); return err; } +#endif /* CONFIG_DPVS_AGENT */ return err; } int dp_vs_dest_term(void) { +#ifdef CONFIG_DPVS_AGENT dest_unregister_msg_cb(); return sockopt_unregister(&sockopts_dest); +#else + return EDPVS_OK; +#endif } diff --git a/src/ipvs/ip_vs_laddr.c b/src/ipvs/ip_vs_laddr.c index d35b13d49..bd8bf2367 100644 --- a/src/ipvs/ip_vs_laddr.c +++ b/src/ipvs/ip_vs_laddr.c @@ -361,6 +361,7 @@ int dp_vs_laddr_del(struct dp_vs_service *svc, int af, const union inet_addr *ad return err; } +#ifdef CONFIG_DPVS_AGENT static int dpvs_agent_laddr_getall(struct dp_vs_service *svc, struct dp_vs_laddr_detail **addrs, size_t *naddr) { @@ -393,6 +394,7 @@ static int dpvs_agent_laddr_getall(struct dp_vs_service *svc, return EDPVS_OK; } +#endif /* CONFIG_DPVS_AGENT */ /* if success, it depend on caller to free @addrs by rte_free() */ static int dp_vs_laddr_getall(struct dp_vs_service *svc, @@ -470,12 +472,14 @@ static inline sockoptid_t set_opt_so2msg(int opt) return MSG_TYPE_LADDR_SET_FLUSH; case SOCKOPT_GET_LADDR_GETALL: return MSG_TYPE_LADDR_GET_ALL; +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_VS_ADD_LADDR: return MSG_TYPE_AGENT_ADD_LADDR; case DPVSAGENT_VS_DEL_LADDR: return MSG_TYPE_AGENT_DEL_LADDR; case DPVSAGENT_VS_GET_LADDR: return MSG_TYPE_AGENT_GET_LADDR; +#endif default: return -1; } @@ -484,16 +488,17 @@ static inline sockoptid_t set_opt_so2msg(int opt) static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) { const struct dp_vs_laddr_conf *laddr_conf = conf; - const struct dp_vs_laddr_front *laddr_front = conf; - struct dp_vs_laddr_detail *details, *detail; struct dp_vs_service *svc; - int err = EDPVS_INVAL; - - int af; + int err, af; uint16_t proto, port; - uint32_t fwmark, i; + uint32_t fwmark; const struct dp_vs_match *match; const union inet_addr *addr; +#ifdef CONFIG_DPVS_AGENT + uint32_t i; + const struct dp_vs_laddr_front *laddr_front = conf; + struct dp_vs_laddr_detail *details, *detail; +#endif lcoreid_t cid = rte_lcore_id(); @@ -515,6 +520,7 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) if (!conf && size < sizeof(*laddr_conf)) return EDPVS_INVAL; +#ifdef CONFIG_DPVS_AGENT if (opt == DPVSAGENT_VS_ADD_LADDR || opt == DPVSAGENT_VS_DEL_LADDR) { af = (int)laddr_front->af; proto = (uint16_t)laddr_front->proto; @@ -523,13 +529,16 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) addr = &laddr_front->addr; match = &laddr_front->match; } else { +#endif af = (int)laddr_conf->af_s; proto = (uint16_t)laddr_conf->proto; port = (uint16_t)laddr_conf->vport; fwmark = (uint32_t)laddr_conf->fwmark; addr = &laddr_conf->vaddr; match = &laddr_conf->match; +#ifdef CONFIG_DPVS_AGENT } +#endif svc = dp_vs_service_lookup(af, proto, addr, port, @@ -549,18 +558,15 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) case SOCKOPT_SET_LADDR_FLUSH: err = dp_vs_laddr_flush(svc); break; +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_VS_ADD_LADDR: details = (struct dp_vs_laddr_detail*)((char*)conf + sizeof(struct dp_vs_laddr_front)); for (i = 0; i < laddr_front->count; i++) { detail = (struct dp_vs_laddr_detail*)((char*)details + sizeof(struct dp_vs_laddr_detail) * i); - err = dp_vs_laddr_add(svc, - detail->af, - &detail->addr, - detail->ifname); + err = dp_vs_laddr_add(svc, detail->af, &detail->addr, detail->ifname); if (err != EDPVS_OK) { - if (err == EDPVS_EXIST) { + if (err == EDPVS_EXIST) continue; - } break; } } @@ -569,17 +575,14 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) details = (struct dp_vs_laddr_detail*)((char*)conf + sizeof(struct dp_vs_laddr_front)); for (i = 0; i < laddr_front->count; i++) { detail = (struct dp_vs_laddr_detail*)((char*)details + sizeof(struct dp_vs_laddr_detail) * i); - err = dp_vs_laddr_del(svc, - detail->af, - &detail->addr); - if (err != EDPVS_OK) { - if (err == EDPVS_NOTEXIST) { + err = dp_vs_laddr_del(svc, detail->af, &detail->addr); if (err != EDPVS_OK) { + if (err == EDPVS_NOTEXIST) continue; - } break; } } break; +#endif default: err = EDPVS_NOTSUPP; break; @@ -589,6 +592,7 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) } +#ifdef CONFIG_DPVS_AGENT static int agent_get_msg_cb(struct dpvs_msg *msg) { lcoreid_t cid = rte_lcore_id(); @@ -639,6 +643,7 @@ static int agent_get_msg_cb(struct dpvs_msg *msg) msg->reply.data = (void *)laddrs; return EDPVS_OK; } +#endif static int get_msg_cb(struct dpvs_msg *msg) { @@ -708,11 +713,13 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, { const struct dp_vs_laddr_conf *laddr_conf = conf; struct dp_vs_laddr_conf *laddrs, *get_msg; +#ifdef CONFIG_DPVS_AGENT const struct dp_vs_laddr_front *laddr_front; struct dp_vs_laddr_front *out_front, *iter_front; + struct dp_vs_laddr_detail *details; +#endif struct dp_vs_service *svc; struct dp_vs_laddr_entry *addrs; - struct dp_vs_laddr_detail *details; size_t naddr, i; int err; struct dpvs_multicast_queue *reply = NULL; @@ -814,6 +821,7 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, msg_destroy(&msg); return EDPVS_NOTEXIST; } +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_VS_GET_LADDR: laddr_front = conf; if (!conf || size != sizeof(*laddr_front)) @@ -883,11 +891,23 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, } msg_destroy(&msg); return EDPVS_OK; +#endif /* CONFIG_DPVS_AGENT */ default: return EDPVS_NOTSUPP; } } +static struct dpvs_sockopts laddr_sockopts = { + .version = SOCKOPT_VERSION, + .set_opt_min = SOCKOPT_SET_LADDR_ADD, + .set_opt_max = SOCKOPT_SET_LADDR_FLUSH, + .set = laddr_sockopt_set, + .get_opt_min = SOCKOPT_GET_LADDR_GETALL, + .get_opt_max = SOCKOPT_GET_LADDR_MAX, + .get = laddr_sockopt_get, +}; + +#ifdef CONFIG_DPVS_AGENT static struct dpvs_sockopts agent_laddr_sockopts = { .version = SOCKOPT_VERSION, .set_opt_min = DPVSAGENT_VS_ADD_LADDR, @@ -898,15 +918,6 @@ static struct dpvs_sockopts agent_laddr_sockopts = { .get = laddr_sockopt_get, }; -static struct dpvs_sockopts laddr_sockopts = { - .version = SOCKOPT_VERSION, - .set_opt_min = SOCKOPT_SET_LADDR_ADD, - .set_opt_max = SOCKOPT_SET_LADDR_FLUSH, - .set = laddr_sockopt_set, - .get_opt_min = SOCKOPT_GET_LADDR_GETALL, - .get_opt_max = SOCKOPT_GET_LADDR_MAX, - .get = laddr_sockopt_get, -}; static int agent_add_msg_cb(struct dpvs_msg *msg) { return laddr_sockopt_set(DPVSAGENT_VS_ADD_LADDR, msg->data, msg->len); @@ -916,6 +927,7 @@ static int agent_del_msg_cb(struct dpvs_msg *msg) { return laddr_sockopt_set(DPVSAGENT_VS_DEL_LADDR, msg->data, msg->len); } +#endif /* CONFIG_DPVS_AGENT */ static int add_msg_cb(struct dpvs_msg *msg) { @@ -984,6 +996,8 @@ int dp_vs_laddr_init(void) RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); return err; } + +#ifdef CONFIG_DPVS_AGENT memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_GET_LADDR; msg_type.mode = DPVS_MSG_MULTICAST; @@ -1019,12 +1033,15 @@ int dp_vs_laddr_init(void) RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); return err; } +#endif if ((err = sockopt_register(&laddr_sockopts)) != EDPVS_OK) return err; +#ifdef CONFIG_DPVS_AGENT if ((err = sockopt_register(&agent_laddr_sockopts)) != EDPVS_OK) return err; +#endif return EDPVS_OK; } @@ -1033,8 +1050,10 @@ int dp_vs_laddr_term(void) { int err; +#ifdef CONFIG_DPVS_AGENT if ((err = sockopt_unregister(&agent_laddr_sockopts)) != EDPVS_OK) return err; +#endif if ((err = sockopt_unregister(&laddr_sockopts)) != EDPVS_OK) return err; diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index 7341b3151..5a9cb6cf4 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -669,7 +669,7 @@ dp_vs_service_copy(struct dp_vs_service_entry *dst, struct dp_vs_service *src) } static int dp_vs_service_get_entries(int num_services, - dpvs_agent_services_front_t *uptr, + dpvs_services_front_t *uptr, lcoreid_t cid) { int idx, count = 0; @@ -964,8 +964,8 @@ static int dp_vs_service_set(sockoptid_t opt, const void *user, size_t len) } /* copy service/dest/stats */ -static int dp_vs_services_copy_percore_stats(dpvs_agent_services_front_t *master_svcs, - dpvs_agent_services_front_t *slave_svcs) +static int dp_vs_services_copy_percore_stats(dpvs_services_front_t *master_svcs, + dpvs_services_front_t *slave_svcs) { int i; if (master_svcs->count!= slave_svcs->count) @@ -998,11 +998,11 @@ static int dp_vs_services_get_uc_cb(struct dpvs_msg *msg) { lcoreid_t cid = rte_lcore_id(); size_t size; - dpvs_agent_services_front_t *get, *output; + dpvs_services_front_t *get, *output; int ret; /* service may be changed */ - get = (dpvs_agent_services_front_t*)msg->data; + get = (dpvs_services_front_t*)msg->data; if (get->count != rte_atomic16_read(&dp_vs_num_services[cid])) { RTE_LOG(ERR, SERVICE, "%s: svc number %d not match %d in cid=%d.\n", __func__, get->count, rte_atomic16_read(&dp_vs_num_services[cid]), cid); @@ -1151,23 +1151,16 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void *outlen = sizeof(struct dp_vs_getinfo); return EDPVS_OK; } +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_SO_GET_SERVICES: { - dpvs_agent_services_front_t msg_data, *get, *real_output, *get_msg, *tmp; + dpvs_services_front_t msg_data, *get, *real_output, *get_msg; struct dpvs_msg *msg, *cur; struct dpvs_multicast_queue *reply = NULL; - int size, real_size; - - get = (dpvs_agent_services_front_t*)user; - get->count = rte_atomic16_read(&dp_vs_num_services[get->cid]); - - msg_data.count = get->count; - msg_data.cid = get->cid; - msg_data.index = get->index; - - real_size = sizeof(*get) + \ - sizeof(struct dp_vs_service_entry) * msg_data.count; + size_t real_size; + /* get slave core svc */ + get = (dpvs_services_front_t*)user; if (len != sizeof(*get)) { *outlen = 0; return EDPVS_INVAL; @@ -1178,14 +1171,16 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void *outlen = 0; return EDPVS_INVAL; } + get->count = rte_atomic16_read(&dp_vs_num_services[cid]); + real_size = sizeof(*get) + sizeof(struct dp_vs_service_entry) * get->count; - /* get slave core svc */ + msg_data.count = get->count; + msg_data.cid = get->cid; + msg_data.index = get->index; msg = msg_make(MSG_TYPE_SVC_GET_SERVICES, 0, DPVS_MSG_MULTICAST, rte_lcore_id(), sizeof(msg_data), &msg_data); - if (unlikely(!msg)) { + if (unlikely(!msg)) return EDPVS_NOMEM; - } - ret = multicast_msg_send(msg, 0, &reply); if (ret != EDPVS_OK) { msg_destroy(&msg); @@ -1193,62 +1188,43 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void return EDPVS_MSG_FAIL; } - if (cid == rte_get_main_lcore()) { - - size = sizeof(msg_data) + \ - sizeof(struct dp_vs_service_entry) * msg_data.count; - tmp = rte_zmalloc("get_services", size, 0); - if (unlikely(NULL == tmp)) { + if (cid == g_master_lcore_id) { + real_output = rte_zmalloc("agent_get_services", real_size, 0); + if (unlikely(NULL == real_output)) { msg_destroy(&msg); return EDPVS_NOMEM; } - ret = dp_vs_service_get_entries(get->count, tmp, cid); + ret = dp_vs_service_get_entries(get->count, real_output, cid); if (ret != EDPVS_OK) { msg_destroy(&msg); - rte_free(tmp); + rte_free(real_output); return ret; } list_for_each_entry(cur, &reply->mq, mq_node) { - get_msg = (dpvs_agent_services_front_t*)(cur->data); - ret = dp_vs_services_copy_percore_stats(tmp, get_msg); + get_msg = (dpvs_services_front_t*)(cur->data); + ret = dp_vs_services_copy_percore_stats(real_output, get_msg); if (ret != EDPVS_OK) { msg_destroy(&msg); - rte_free(tmp); + rte_free(real_output); return ret; } } - real_output = rte_zmalloc("agent_get_services", real_size, 0); - if (!real_output) { - msg_destroy(&msg); - rte_free(tmp); - return EDPVS_NOMEM; - } - - rte_memcpy(real_output, get, sizeof(*get)); - rte_memcpy(((char*)real_output)+sizeof(*get), ((char*)tmp)+sizeof(msg_data), real_size-sizeof(*get)); *out = real_output; *outlen = real_size; - - rte_free(tmp); msg_destroy(&msg); return EDPVS_OK; } else { - size = sizeof(msg_data) + \ - sizeof(struct dp_vs_service_entry) * msg_data.count; - list_for_each_entry(cur, &reply->mq, mq_node) { - get_msg = (dpvs_agent_services_front_t*)(cur->data); - if (get_msg->cid == cid) { - // FIXME: + get_msg = (dpvs_services_front_t*)(cur->data); + if (unlikely(get_msg->cid == cid)) { real_output = rte_zmalloc("agent_get_services", real_size, 0); if (unlikely(NULL == real_output)) { msg_destroy(&msg); return EDPVS_NOMEM; } - // rte_memcpy(tmp, get_msg, size); rte_memcpy(real_output, get, sizeof(*get)); rte_memcpy(((char*)real_output)+sizeof(*get), ((char*)get_msg)+sizeof(msg_data), real_size-sizeof(*get)); *out = real_output; @@ -1262,14 +1238,15 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void return EDPVS_NOTEXIST; } } +#endif /* CONFIG_DPVS_AGENT */ case DPVS_SO_GET_SERVICES: { - dpvs_agent_services_front_t *get, *get_msg, *output; + dpvs_services_front_t *get, *get_msg, *output; struct dpvs_msg *msg, *cur; struct dpvs_multicast_queue *reply = NULL; int size; - get = (dpvs_agent_services_front_t*)user; + get = (dpvs_services_front_t*)user; size = sizeof(*get) + \ sizeof(struct dp_vs_service_entry) * (get->count); if (len != sizeof(*get)){ @@ -1311,7 +1288,7 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void return ret; } list_for_each_entry(cur, &reply->mq, mq_node) { - get_msg = (dpvs_agent_services_front_t*)(cur->data); + get_msg = (dpvs_services_front_t*)(cur->data); ret = dp_vs_services_copy_percore_stats(output, get_msg); if (ret != EDPVS_OK) { msg_destroy(&msg); @@ -1325,7 +1302,7 @@ static int dp_vs_service_get(sockoptid_t opt, const void *user, size_t len, void return EDPVS_OK; } else { list_for_each_entry(cur, &reply->mq, mq_node) { - get_msg = (dpvs_agent_services_front_t*)(cur->data); + get_msg = (dpvs_services_front_t*)(cur->data); if (get_msg->cid == cid) { output = rte_zmalloc("get_services", size, 0); if (unlikely(NULL == output)) { diff --git a/src/route.c b/src/route.c index a05e59e49..7a8115df3 100644 --- a/src/route.c +++ b/src/route.c @@ -543,14 +543,18 @@ static int route_sockopt_set(sockoptid_t opt, const void *conf, size_t size) return EDPVS_INVAL; switch (opt) { +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_ROUTE_ADD: /*fallthrough*/ +#endif case SOCKOPT_SET_ROUTE_ADD: return route_add(&dst->in, plen, flags, &gw->in, dev, &src->in, mtu, metric); +#ifdef CONFIG_DPVS_AGENT case DPVSAGENT_ROUTE_DEL: /*fallthrough*/ +#endif case SOCKOPT_SET_ROUTE_DEL: return route_del(&dst->in, plen, flags, &gw->in, dev, &src->in, mtu, metric); @@ -593,7 +597,7 @@ static int route_sockopt_get(sockoptid_t opt, const void *conf, size_t size, struct netif_port *port = NULL; int off = 0; char *ifname = ((struct dp_vs_route_detail*)conf)->ifname; - if (conf && strlen(ifname)) { + if (ifname[0] != '\0') { port = netif_port_get_by_name(ifname); if (!port) { RTE_LOG(WARNING, ROUTE, "%s: no such device: %s\n", @@ -603,9 +607,7 @@ static int route_sockopt_get(sockoptid_t opt, const void *conf, size_t size, } nroute = rte_atomic32_read(&this_num_routes); - *outsize = sizeof(struct dp_vs_route_conf_array) + nroute * sizeof(struct dp_vs_route_detail); - *out = rte_calloc(NULL, 1, *outsize, 0); if (!(*out)) return EDPVS_NOMEM; @@ -687,6 +689,7 @@ static int route_del_msg_cb(struct dpvs_msg *msg) return route_msg_process(false, msg); } +#ifdef CONFIG_DPVS_AGENT static struct dpvs_sockopts agent_route_sockopts = { .version = SOCKOPT_VERSION, .set_opt_min = DPVSAGENT_ROUTE_ADD, @@ -696,6 +699,7 @@ static struct dpvs_sockopts agent_route_sockopts = { .get_opt_max = DPVSAGENT_ROUTE_GET, .get = route_sockopt_get, }; +#endif static struct dpvs_sockopts route_sockopts = { .version = SOCKOPT_VERSION, @@ -775,8 +779,10 @@ int route_init(void) if ((err = sockopt_register(&route_sockopts)) != EDPVS_OK) return err; +#ifdef CONFIG_DPVS_AGENT if ((err = sockopt_register(&agent_route_sockopts)) != EDPVS_OK) return err; +#endif return EDPVS_OK; } @@ -786,8 +792,10 @@ int route_term(void) int err; lcoreid_t cid; +#ifdef CONFIG_DPVS_AGENT if ((err = sockopt_unregister(&agent_route_sockopts)) != EDPVS_OK) return err; +#endif if ((err = sockopt_unregister(&route_sockopts)) != EDPVS_OK) return err; diff --git a/tools/dpip/route.c b/tools/dpip/route.c index 9951051b5..d89e40939 100644 --- a/tools/dpip/route.c +++ b/tools/dpip/route.c @@ -35,12 +35,8 @@ static void route_help(void) "Parameters:\n" " ROUTE := PREFIX [ via ADDR ] [ dev IFNAME ] [ OPTIONS ]\n" " PREFIX := { ADDR/PLEN | ADDR | default }\n" - " OPTIONS := [ SCOPE | mtu MTU | src ADDR | tos TOS\n" - " | metric NUM | PROTOCOL | FLAGS ]\n" + " OPTIONS := [ SCOPE | mtu MTU | src ADDR | metric NUM ]\n" " SCOPE := [ scope { host | link | global | NUM } ]\n" - " PROTOCOL := [ proto { auto | boot | static | ra | NUM } ]\n" - " FLAGS := [ onlink | local ]\n" - " TABLE := [ table outwall ]\n" "Examples:\n" " dpip route show\n" " dpip route add default via 10.0.0.1\n" @@ -51,9 +47,6 @@ static void route_help(void) " dpip route del 172.0.0.0/16\n" " dpip route set 172.0.0.0/16 via 172.0.0.1\n" " dpip route flush\n" - " dpip route show table outwall\n" - " dpip route add default via 10.0.0.1 dev dpdk1 table outwall\n" - " dpip route del default via 10.0.0.1 dev dpdk1 table outwall\n" ); } diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index daad672be..7df33aa3c 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -2219,10 +2219,10 @@ static int list_laddrs(dpvs_service_compat_t* desc) static int list_all_laddrs(lcoreid_t index) { int i; - dpvs_agent_services_front_t* table; + dpvs_services_front_t* table; struct ip_vs_get_laddrs *d = NULL; - table = (dpvs_agent_services_front_t*)malloc(sizeof(dpvs_agent_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); + table = (dpvs_services_front_t*)malloc(sizeof(dpvs_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); if (!table) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); @@ -2325,9 +2325,9 @@ static int list_blklst(int af, const union inet_addr *addr, uint16_t port, uint1 static int list_all_blklsts(void) { int i; - dpvs_agent_services_front_t* table; + dpvs_services_front_t* table; - table = (dpvs_agent_services_front_t*)malloc(sizeof(dpvs_agent_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); + table = (dpvs_services_front_t*)malloc(sizeof(dpvs_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); if (!table) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); @@ -2413,10 +2413,10 @@ static int list_whtlst(int af, const union inet_addr *addr, uint16_t port, uint1 static int list_all_whtlsts(void) { - dpvs_agent_services_front_t* table; + dpvs_services_front_t* table; int i; - table = (dpvs_agent_services_front_t*)malloc(sizeof(dpvs_agent_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); + table = (dpvs_services_front_t*)malloc(sizeof(dpvs_services_front_t)+sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); if (!table) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); @@ -2458,13 +2458,13 @@ static void list_service(dpvs_service_compat_t *svc, unsigned int format) static void list_all(unsigned int format) { int i; - dpvs_agent_services_front_t* table; + dpvs_services_front_t* table; if (!(format & FMT_RULE)) printf("IP Virtual Server version %d.%d.%d (size=%d)\n", NVERSION(g_ipvs_info.version), g_ipvs_info.size); - table = (dpvs_agent_services_front_t*)malloc(sizeof(dpvs_agent_services_front_t) + sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); + table = (dpvs_services_front_t*)malloc(sizeof(dpvs_services_front_t) + sizeof(dpvs_service_compat_t)*g_ipvs_info.num_services); if (!table) { fprintf(stderr, "%s\n", ipvs_strerror(errno)); exit(1); diff --git a/tools/keepalived/keepalived/check/libipvs.c b/tools/keepalived/keepalived/check/libipvs.c index 67fed7180..ee65fa547 100644 --- a/tools/keepalived/keepalived/check/libipvs.c +++ b/tools/keepalived/keepalived/check/libipvs.c @@ -420,8 +420,8 @@ int dpvs_stop_daemon(ipvs_daemon_t *dm) (char *)&dm, sizeof(dm)); } -dpvs_agent_services_front_t* dpvs_get_services(dpvs_agent_services_front_t* svcs) { - dpvs_agent_services_front_t* rcv; +dpvs_services_front_t* dpvs_get_services(dpvs_services_front_t* svcs) { + dpvs_services_front_t* rcv; size_t lrcv, len; dpvs_ctrl_func = dpvs_get_services; @@ -429,11 +429,11 @@ dpvs_agent_services_front_t* dpvs_get_services(dpvs_agent_services_front_t* svcs assert(svcs); if (ESOCKOPT_OK != dpvs_getsockopt(DPVS_SO_GET_SERVICES, svcs, - sizeof(dpvs_agent_services_front_t), (void**)&rcv, &lrcv)) { + sizeof(dpvs_services_front_t), (void**)&rcv, &lrcv)) { return NULL; } - len = svcs->count * sizeof(dpvs_service_compat_t) + sizeof(dpvs_agent_services_front_t); + len = svcs->count * sizeof(dpvs_service_compat_t) + sizeof(dpvs_services_front_t); memcpy(svcs, rcv, len < lrcv ? len : lrcv); @@ -531,7 +531,7 @@ dpvs_cmp_dests(dpvs_dest_compat_t *d1, dpvs_dest_compat_t *d2) return ntohs(d1->port) - ntohs(d2->port); } -void dpvs_sort_services(dpvs_agent_services_front_t *s, dpvs_service_cmp_t f) +void dpvs_sort_services(dpvs_services_front_t *s, dpvs_service_cmp_t f) { qsort(s->entrytable, s->count, sizeof(dpvs_service_compat_t), (qsort_cmp_t)f); diff --git a/tools/keepalived/keepalived/include/libipvs.h b/tools/keepalived/keepalived/include/libipvs.h index 870884b9c..056834e45 100644 --- a/tools/keepalived/keepalived/include/libipvs.h +++ b/tools/keepalived/keepalived/include/libipvs.h @@ -138,7 +138,7 @@ extern int dpvs_start_daemon(ipvs_daemon_t *dm); extern int dpvs_stop_daemon(ipvs_daemon_t *dm); /* get all the ipvs services */ -extern dpvs_agent_services_front_t *dpvs_get_services(dpvs_agent_services_front_t *t); +extern dpvs_services_front_t *dpvs_get_services(dpvs_services_front_t *t); /* get the destination array of the specified service */ extern dpvs_dest_table_t* dpvs_get_dests(dpvs_dest_table_t* table); @@ -166,7 +166,7 @@ extern int dpvs_set_ipaddr(struct inet_addr_param *param, int cmd); extern struct dp_vs_blklst_conf_array *dpvs_get_blklsts(void); typedef int (*dpvs_service_cmp_t)(dpvs_service_compat_t *,dpvs_service_compat_t*); -extern void dpvs_sort_services(dpvs_agent_services_front_t *s, dpvs_service_cmp_t f); +extern void dpvs_sort_services(dpvs_services_front_t *s, dpvs_service_cmp_t f); extern int dpvs_cmp_services(dpvs_service_compat_t *s1, dpvs_service_compat_t *s2); typedef int (*dpvs_dest_cmp_t)(dpvs_dest_compat_t*, dpvs_dest_compat_t*); From c93a1a2e8060ec5aeb7cc0f7a5c7694dc79b5ec0 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 8 Mar 2023 14:50:03 +0800 Subject: [PATCH 010/105] netif: add supports for extended statistics of an ethernet device Signed-off-by: ywc689 --- include/conf/netif.h | 12 ++++++ include/netif.h | 3 ++ src/netif.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ tools/dpip/link.c | 25 ++++++++++++ 4 files changed, 136 insertions(+) diff --git a/include/conf/netif.h b/include/conf/netif.h index e405124ae..298a62385 100644 --- a/include/conf/netif.h +++ b/include/conf/netif.h @@ -140,6 +140,18 @@ typedef struct netif_nic_stats_get { portid_t port_id; } netif_nic_stats_get_t; +struct netif_nic_xstats_entry { + uint64_t id; + uint64_t val; + char name[64]; +}; + +typedef struct netif_nic_xstats_get { + portid_t pid; + uint16_t nentries; + struct netif_nic_xstats_entry entries[0]; +} netif_nic_xstats_get_t; + /* dev info specified by port_id */ struct netif_nic_dev_get { diff --git a/include/netif.h b/include/netif.h index bc6a64256..05dfe2e73 100644 --- a/include/netif.h +++ b/include/netif.h @@ -25,6 +25,7 @@ #include "global_data.h" #include "timer.h" #include "tc/tc.h" +#include "conf/netif.h" #define RTE_LOGTYPE_NETIF RTE_LOGTYPE_USER1 @@ -200,6 +201,7 @@ struct netif_ops { int (*op_get_link)(struct netif_port *dev, struct rte_eth_link *link); int (*op_get_promisc)(struct netif_port *dev, bool *promisc); int (*op_get_stats)(struct netif_port *dev, struct rte_eth_stats *stats); + int (*op_get_xstats)(struct netif_port *dev, netif_nic_xstats_get_t **xstats); }; struct netif_hw_addr { @@ -299,6 +301,7 @@ int netif_get_queue(struct netif_port *port, lcoreid_t id, queueid_t *qid); int netif_get_link(struct netif_port *dev, struct rte_eth_link *link); int netif_get_promisc(struct netif_port *dev, bool *promisc); int netif_get_stats(struct netif_port *dev, struct rte_eth_stats *stats); +int netif_get_xstats(struct netif_port *dev, netif_nic_xstats_get_t **xstats); struct netif_port *netif_alloc(size_t priv_size, const char *namefmt, unsigned int nrxq, unsigned int ntxq, void (*setup)(struct netif_port *)); diff --git a/src/netif.c b/src/netif.c index ff501485c..fbcd299fb 100644 --- a/src/netif.c +++ b/src/netif.c @@ -3313,13 +3313,71 @@ static int dpdk_set_mc_list(struct netif_port *dev) return EDPVS_OK; } +static int netif_op_get_xstats(struct netif_port *dev, netif_nic_xstats_get_t **pget) +{ + int i, nentries, err; + struct rte_eth_xstat *xstats = NULL; + struct rte_eth_xstat_name *xstats_names = NULL; + netif_nic_xstats_get_t *get = NULL; + + nentries = rte_eth_xstats_get(dev->id, NULL, 0); + if (nentries < 0) + return EDPVS_DPDKAPIFAIL; + + get = rte_calloc("xstats_get", 1, nentries * sizeof(struct netif_nic_xstats_entry), 0); + if (unlikely(!get)) + return EDPVS_NOMEM; + xstats = rte_calloc("xstats", 1, nentries * sizeof(struct rte_eth_xstat), 0); + if (unlikely(!xstats)) { + err = EDPVS_NOMEM; + goto errout; + } + xstats_names = rte_calloc("xstats_names", 1, nentries * sizeof(struct rte_eth_xstat_name), 0); + if (unlikely(!xstats_names)) { + err = EDPVS_NOMEM; + goto errout; + } + + err = rte_eth_xstats_get(dev->id, xstats, nentries); + if (err < 0 || err != nentries) + goto errout; + err = rte_eth_xstats_get_names(dev->id, xstats_names, nentries); + if (err < 0 || err != nentries) + goto errout; + get->pid = dev->id; + get->nentries = nentries; + for (i = 0; i < nentries; i++) { + get->entries[i].id = xstats[i].id; + get->entries[i].val = xstats[i].value; + rte_memcpy(get->entries[i].name, xstats_names[i].name, sizeof(get->entries[i].name)-1); + } + + *pget = get; + rte_free(xstats); + rte_free(xstats_names); + return EDPVS_OK; +errout: + if (xstats) + rte_free(xstats); + if (xstats_names) + rte_free(xstats_names); + if (get) + rte_free(get); + if (err == EDPVS_OK) + err = EDPVS_RESOURCE; + *pget = NULL; + return err; +} + static struct netif_ops dpdk_netif_ops = { .op_set_mc_list = dpdk_set_mc_list, + .op_get_xstats = netif_op_get_xstats, }; static struct netif_ops bond_netif_ops = { .op_update_addr = update_bond_macaddr, .op_set_mc_list = bond_set_mc_list, + .op_get_xstats = netif_op_get_xstats, }; static inline void setup_dev_of_flags(struct netif_port *port) @@ -3537,6 +3595,16 @@ int netif_get_stats(struct netif_port *dev, struct rte_eth_stats *stats) return EDPVS_OK; } +int netif_get_xstats(struct netif_port *dev, netif_nic_xstats_get_t **xstats) +{ + assert (dev && dev->netif_ops && xstats); + + if (dev->netif_ops->op_get_xstats) + return dev->netif_ops->op_get_xstats(dev, xstats); + + return EDPVS_NOTSUPP; +} + int netif_port_conf_get(struct netif_port *port, struct rte_eth_conf *eth_conf) { @@ -4908,6 +4976,25 @@ static int get_port_stats(struct netif_port *port, void **out, size_t *out_len) return EDPVS_OK; } +static int get_port_xstats(struct netif_port *port, void **out, size_t *out_len) +{ + int err; + assert(out && out_len); + + netif_nic_xstats_get_t *get; + err = netif_get_xstats(port, &get); + if (err != EDPVS_OK) { + if (err == EDPVS_NOTSUPP) + return EDPVS_OK; + return err; + } + + *out = get; + *out_len = sizeof(netif_nic_xstats_get_t) + get->nentries * sizeof(struct netif_nic_xstats_entry); + + return EDPVS_OK; +} + static int get_bond_status(struct netif_port *port, void **out, size_t *out_len) { bool is_active; @@ -5032,6 +5119,15 @@ static int netif_sockopt_get(sockoptid_t opt, const void *in, size_t inlen, return EDPVS_NOTEXIST; ret = get_port_stats(port, out, outlen); break; + case SOCKOPT_NETIF_GET_PORT_XSTATS: + if (!in) + return EDPVS_INVAL; + name = (char *)in; + port = netif_port_get_by_name(name); + if (!port) + return EDPVS_NOTEXIST; + ret = get_port_xstats(port, out, outlen); + break; case SOCKOPT_NETIF_GET_PORT_EXT_INFO: if (!in) return EDPVS_INVAL; diff --git a/tools/dpip/link.c b/tools/dpip/link.c index 666bc0415..2dfb1c99a 100644 --- a/tools/dpip/link.c +++ b/tools/dpip/link.c @@ -301,6 +301,28 @@ static int dump_nic_stats(char *name, int namelen) return EDPVS_OK; } +static void dump_nic_xstats(char *name, int namelen) +{ + int i, err; + size_t len = 0; + netif_nic_xstats_get_t *get = NULL; + + printf(" xstats list:\n"); + err = dpvs_getsockopt(SOCKOPT_NETIF_GET_PORT_XSTATS, name, namelen, + (void **)&get, &len); + if (err != EDPVS_OK || !get || !len) { + printf(" not supported\n"); + return; + } + + for (i = 0; i < get->nentries; i++) { + printf(" %-6lu%s: %lu\n", get->entries[i].id, get->entries[i].name, + get->entries[i].val); + } + + dpvs_sockopt_msg_free(get); +} + static int dump_nic_verbose(char *name, int namelen) { int err; @@ -647,6 +669,9 @@ static int link_nic_show(struct link_param *param) param->stats.interval, param->stats.count)) != EDPVS_OK) return err; } + if (param->verbose) { + dump_nic_xstats(param->dev_name, sizeof(param->dev_name)); + } } if (param->verbose) if ((err = dump_nic_verbose(param->dev_name, From 2b4aca32acb99c969d013c32276b83eaf2c4b155 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 8 Mar 2023 15:57:04 +0800 Subject: [PATCH 011/105] cfgfile: remove the stale config "ipc_msg/unix_domain" The config file block "ipc_msg/unix_domain" was replaced with command option "-p, --pid-file FILE" in commit 6ce4dd9479. Signed-off-by: ywc689 --- conf/dpvs.bond.conf.sample | 3 --- conf/dpvs.conf.items | 3 --- conf/dpvs.conf.sample | 3 --- conf/dpvs.conf.single-bond.sample | 3 --- conf/dpvs.conf.single-nic.sample | 3 --- include/conf/sockopts.h | 1 + src/ctrl.c | 33 +------------------------------ 7 files changed, 2 insertions(+), 47 deletions(-) diff --git a/conf/dpvs.bond.conf.sample b/conf/dpvs.bond.conf.sample index 6e0e37137..01eb785ec 100644 --- a/conf/dpvs.bond.conf.sample +++ b/conf/dpvs.bond.conf.sample @@ -309,9 +309,6 @@ ctrl_defs { sync_msg_timeout_us 20000 priority_level low } - ipc_msg { - unix_domain /var/run/dpvs_ctrl - } } ! ipvs config diff --git a/conf/dpvs.conf.items b/conf/dpvs.conf.items index 315fe87c0..fb6b79326 100644 --- a/conf/dpvs.conf.items +++ b/conf/dpvs.conf.items @@ -211,9 +211,6 @@ ctrl_defs { sync_msg_timeout_us 2000 <2000, 1-∞> priority_level low } - ipc_msg { - unix_domain /var/run/dpvs_ctrl - } } ! ipvs config diff --git a/conf/dpvs.conf.sample b/conf/dpvs.conf.sample index 04a423257..dd34b07d4 100644 --- a/conf/dpvs.conf.sample +++ b/conf/dpvs.conf.sample @@ -275,9 +275,6 @@ ctrl_defs { sync_msg_timeout_us 20000 priority_level low } - ipc_msg { - unix_domain /var/run/dpvs_ctrl - } } ! ipvs config diff --git a/conf/dpvs.conf.single-bond.sample b/conf/dpvs.conf.single-bond.sample index db72362ec..5ae4cd07e 100644 --- a/conf/dpvs.conf.single-bond.sample +++ b/conf/dpvs.conf.single-bond.sample @@ -216,9 +216,6 @@ ctrl_defs { sync_msg_timeout_us 20000 priority_level low } - ipc_msg { - unix_domain /var/run/dpvs_ctrl - } } ! ipvs config diff --git a/conf/dpvs.conf.single-nic.sample b/conf/dpvs.conf.single-nic.sample index 753b15348..8f9397bc9 100644 --- a/conf/dpvs.conf.single-nic.sample +++ b/conf/dpvs.conf.single-nic.sample @@ -191,9 +191,6 @@ ctrl_defs { sync_msg_timeout_us 20000 priority_level low } - ipc_msg { - unix_domain /var/run/dpvs_ctrl - } } ! ipvs config diff --git a/include/conf/sockopts.h b/include/conf/sockopts.h index 9a0a7e035..3f658ede0 100644 --- a/include/conf/sockopts.h +++ b/include/conf/sockopts.h @@ -94,6 +94,7 @@ DPVSMSG(SOCKOPT_NETIF_GET_PORT_LIST) \ DPVSMSG(SOCKOPT_NETIF_GET_PORT_BASIC) \ DPVSMSG(SOCKOPT_NETIF_GET_PORT_STATS) \ + DPVSMSG(SOCKOPT_NETIF_GET_PORT_XSTATS) \ DPVSMSG(SOCKOPT_NETIF_GET_PORT_EXT_INFO) \ DPVSMSG(SOCKOPT_NETIF_GET_BOND_STATUS) \ DPVSMSG(SOCKOPT_NETIF_GET_MAX) \ diff --git a/src/ctrl.c b/src/ctrl.c index 1b89a69ed..b01b12d6e 100644 --- a/src/ctrl.c +++ b/src/ctrl.c @@ -1152,7 +1152,7 @@ static inline int msg_term(void) /////////////////////////////// sockopt process msg /////////////////////////////////////////// -char ipc_unix_domain[256]; +static char ipc_unix_domain[256]; static struct list_head sockopt_list; @@ -1601,38 +1601,11 @@ static void msg_priority_level_handler(vector_t tokens) FREE_PTR(str); } -static void ipc_unix_domain_handler(vector_t tokens) -{ - char *str, *dup_str; - size_t slen; - - str = set_value(tokens); - slen = strlen(str); - - dup_str = strdup(str); - dirname(dup_str); - memset(ipc_unix_domain, 0, sizeof(ipc_unix_domain)); - - if (slen > 0 && slen < sizeof(ipc_unix_domain) && - access(dup_str, F_OK) == 0) { - RTE_LOG(INFO, MSGMGR, "ipc_unix_domain = %s\n", str); - strncpy(ipc_unix_domain, str, sizeof(ipc_unix_domain) - 1); - } else { - RTE_LOG(WARNING, MSGMGR, "invalid ipc_unix_domain %s, using default %s\n", - str, dpvs_ipc_file); - strncpy(ipc_unix_domain, dpvs_ipc_file, sizeof(ipc_unix_domain) - 1); - } - - free(dup_str); - FREE_PTR(str); -} - void control_keyword_value_init(void) { if (dpvs_state_get() == DPVS_STATE_INIT) { /* KW_TYPE_INIT keyword */ msg_ring_size = DPVS_MSG_RING_SIZE_DEF; - strncpy(ipc_unix_domain, dpvs_ipc_file, sizeof(ipc_unix_domain) - 1); } /* KW_TYPE_NORMAL keyword */ g_msg_timeout = MSG_TIMEOUT_US; @@ -1648,8 +1621,4 @@ void install_control_keywords(void) install_keyword("sync_msg_timeout_us", msg_timeout_handler, KW_TYPE_NORMAL); install_keyword("priority_level", msg_priority_level_handler, KW_TYPE_NORMAL); install_sublevel_end(); - install_keyword("ipc_msg", NULL, KW_TYPE_INIT); - install_sublevel(); - install_keyword("unix_domain", ipc_unix_domain_handler, KW_TYPE_INIT); - install_sublevel_end(); } From bae7f1d8f441876ffb58e276090329c45aa73930 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 26 Apr 2023 13:49:51 +0800 Subject: [PATCH 012/105] netif: set nic multicast ether address from master lcore only It takes long for some nics to update multicast ether addresses. The per-cpu process of per-cpu inetaddr causes mc ether address updating from both slave lcores and master lcore, which is nonsense but a dramatic hurt for performacne. So just do it once on master lcore. Signed-off-by: ywc689 --- src/inetaddr.c | 55 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/inetaddr.c b/src/inetaddr.c index 4f47dcabb..10c317eca 100644 --- a/src/inetaddr.c +++ b/src/inetaddr.c @@ -175,7 +175,7 @@ static int idev_mc_del(int af, struct inet_device *idev, return EDPVS_OK; } -static int ifa_add_del_mcast(struct inet_ifaddr *ifa, bool add) +static int ifa_add_del_mcast(struct inet_ifaddr *ifa, bool add, bool is_master) { int err; union inet_addr iaddr; @@ -194,19 +194,23 @@ static int ifa_add_del_mcast(struct inet_ifaddr *ifa, bool add) err = idev_mc_add(ifa->af, ifa->idev, &iaddr); if (err && err != EDPVS_EXIST && err != EDPVS_NOTEXIST) return err; - err = netif_mc_add(ifa->idev->dev, &eaddr); - if (err && err != EDPVS_EXIST && err != EDPVS_NOTEXIST) { - idev_mc_del(ifa->af, ifa->idev, &iaddr); - return err; + if (is_master) { + err = netif_mc_add(ifa->idev->dev, &eaddr); + if (err && err != EDPVS_EXIST && err != EDPVS_NOTEXIST) { + idev_mc_del(ifa->af, ifa->idev, &iaddr); + return err; + } } } else { err = idev_mc_del(ifa->af, ifa->idev, &iaddr); if (err && err != EDPVS_EXIST && err != EDPVS_NOTEXIST) return err; - err = netif_mc_del(ifa->idev->dev, &eaddr); - if (err && err != EDPVS_EXIST && err != EDPVS_NOTEXIST) { - idev_mc_add(ifa->af, ifa->idev, &iaddr); - return err; + if (is_master) { + err = netif_mc_del(ifa->idev->dev, &eaddr); + if (err && err != EDPVS_EXIST && err != EDPVS_NOTEXIST) { + idev_mc_add(ifa->af, ifa->idev, &iaddr); + return err; + } } } @@ -220,6 +224,7 @@ int idev_add_mcast_init(void *args) struct inet_device *idev; union inet_addr all_nodes, all_routers; struct rte_ether_addr eaddr_nodes, eaddr_routers; + bool is_master = (rte_lcore_id() == g_master_lcore_id); struct netif_port *dev = (struct netif_port *) args; @@ -238,17 +243,21 @@ int idev_add_mcast_init(void *args) if (err != EDPVS_OK) goto errout; - err = netif_mc_add(idev->dev, &eaddr_nodes); - if (err != EDPVS_OK) - goto free_idev_nodes; + if (is_master) { + err = netif_mc_add(idev->dev, &eaddr_nodes); + if (err != EDPVS_OK) + goto free_idev_nodes; + } err = idev_mc_add(AF_INET6, idev, &all_routers); if (err != EDPVS_OK) goto free_netif_nodes; - err = netif_mc_add(idev->dev, &eaddr_routers); - if (err != EDPVS_OK) - goto free_idev_routers; + if (is_master) { + err = netif_mc_add(idev->dev, &eaddr_routers); + if (err != EDPVS_OK) + goto free_idev_routers; + } idev_put(idev); return EDPVS_OK; @@ -256,7 +265,8 @@ int idev_add_mcast_init(void *args) free_idev_routers: idev_mc_del(AF_INET6, idev, &all_routers); free_netif_nodes: - netif_mc_del(idev->dev, &eaddr_nodes); + if (is_master) + netif_mc_del(idev->dev, &eaddr_nodes); free_idev_nodes: idev_mc_del(AF_INET6, idev, &all_nodes); errout: @@ -783,7 +793,7 @@ static int ifa_entry_add(const struct ifaddr_action *param) struct inet_device *idev; struct inet_ifaddr *ifa; struct timeval timeo = { 0 }; - bool is_master = (rte_lcore_id() == rte_get_main_lcore()); + bool is_master = (rte_lcore_id() == g_master_lcore_id); if (!param || !param->dev || !ifa_prefix_check(param->af, ¶m->addr, param->plen)) @@ -839,7 +849,7 @@ static int ifa_entry_add(const struct ifaddr_action *param) dpvs_time_now(&ifa->tstemp, is_master); /* mod time */ dpvs_time_now(&ifa->cstemp, is_master); /* create time */ - err = ifa_add_del_mcast(ifa, true); + err = ifa_add_del_mcast(ifa, true, is_master); if (err != EDPVS_OK) goto free_ifa; @@ -883,7 +893,7 @@ static int ifa_entry_add(const struct ifaddr_action *param) del_route: ifa_del_route(ifa); del_mc: - ifa_add_del_mcast(ifa, false); + ifa_add_del_mcast(ifa, false, is_master); free_ifa: rte_free(ifa); errout: @@ -900,7 +910,7 @@ static int ifa_entry_mod(const struct ifaddr_action *param) struct inet_device *idev; struct inet_ifaddr *ifa; struct timeval timeo = { 0 }; - bool is_master = (rte_lcore_id() == rte_get_main_lcore()); + bool is_master = (rte_lcore_id() == g_master_lcore_id); if (!param || !param->dev || !ifa_prefix_check(param->af, ¶m->addr, param->plen)) @@ -1034,6 +1044,7 @@ static void ifa_free(struct inet_ifaddr **ifa_p) char ipstr[64]; struct inet_ifaddr *ifa; lcoreid_t cid = rte_lcore_id(); + bool is_master = (cid == g_master_lcore_id); assert(ifa_p != NULL && *ifa_p != NULL); ifa = *ifa_p; @@ -1041,7 +1052,7 @@ static void ifa_free(struct inet_ifaddr **ifa_p) /* remove @ifa from @ifa_expired_list */ list_del_init(&ifa->h_list); - if (cid == rte_get_main_lcore()) { + if (is_master) { /* it's safe to cancel timer not pending but zeroed */ dpvs_timer_cancel(&ifa->dad_timer, true); dpvs_timer_cancel(&ifa->timer, true); @@ -1052,7 +1063,7 @@ static void ifa_free(struct inet_ifaddr **ifa_p) * If sapool destroyed here, the ifa would not be freed. * */ - ifa_add_del_mcast(ifa, false); + ifa_add_del_mcast(ifa, false, is_master); ifa_del_route(ifa); /* release @idev held by @ifa */ From fe0e2e2a3f12b0ccac722857c648eab89e8dbc0b Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 26 Apr 2023 14:14:48 +0800 Subject: [PATCH 013/105] netif: fix crash problem by ether address list buffer overflow Signed-off-by: ywc689 --- src/netif_addr.c | 2 +- tools/dpip/link.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/netif_addr.c b/src/netif_addr.c index da93f2e7e..9859e7810 100644 --- a/src/netif_addr.c +++ b/src/netif_addr.c @@ -311,7 +311,7 @@ int __netif_mc_print(struct netif_port *dev, if (err != EDPVS_OK) goto errout; - for (i = 0; i < naddr; i++) { + for (i = 0; i < naddr && *len > strlen; i++) { err = snprintf(buf + strlen, *len - strlen, " link %02x:%02x:%02x:%02x:%02x:%02x\n", addrs[i].addr_bytes[0], addrs[i].addr_bytes[1], diff --git a/tools/dpip/link.c b/tools/dpip/link.c index 666bc0415..7ca50d02a 100644 --- a/tools/dpip/link.c +++ b/tools/dpip/link.c @@ -350,16 +350,20 @@ static int dump_nic_verbose(char *name, int namelen) ext_get->dev_info.speed_capa); if (ext_get->cfg_queues.data_len) { - assert(ext_get->cfg_queues.data_len == strlen(ext_get->data + - ext_get->cfg_queues.data_offset)); printf(" Queue Configuration:\n%s", ext_get->data + ext_get->cfg_queues.data_offset); + if (ext_get->cfg_queues.data_len > strlen(ext_get->data + + ext_get->cfg_queues.data_offset)) { + printf(" ... (truncated)"); + } } if (ext_get->mc_list.data_len) { - assert(ext_get->mc_list.data_len == strlen(ext_get->data + - ext_get->mc_list.data_offset)); printf(" HW mcast list:\n%s", ext_get->data + ext_get->mc_list.data_offset); + if (ext_get->mc_list.data_len > strlen(ext_get->data + + ext_get->mc_list.data_offset)) { + printf(" ... (truncated)"); + } } dpvs_sockopt_msg_free(ext_get); From 61bcd36fcb7006b550047509a71397fac29d31a1 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 26 Apr 2023 16:19:27 +0800 Subject: [PATCH 014/105] netif: multicast ether address setting improvements It has been noted that rte_eth_dev_set_mc_addr_list is of some restrictions: * The Api may be slow and take hundreds miliseconds. * Support only a very limited multicast ether address number. For instance of 25G Meallnox CX5, its PMD driver for rte_eth_dev_set_mc_addr_list supports only 128 multicast ether addresses for each port, and it takes about 250ms for rte_eth_dev_set_mc_addr_list to finish its work. Hence we make the following improvements: 1. Enable allmulitcast when rte_eth_dev_set_mc_addr_list failed, 2. Do not call rte_eth_dev_set_mc_addr_list when allmulitcast enabled. In next commmit, allmulticast can be configured at start of DPVS, which can solve the rte_eth_dev_set_mc_addr_list slow problem totally. Signed-off-by: ywc689 --- src/inetaddr.c | 8 ++++++-- src/netif.c | 20 ++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/inetaddr.c b/src/inetaddr.c index 10c317eca..d878ce06f 100644 --- a/src/inetaddr.c +++ b/src/inetaddr.c @@ -192,7 +192,9 @@ static int ifa_add_del_mcast(struct inet_ifaddr *ifa, bool add, bool is_master) if (add) { err = idev_mc_add(ifa->af, ifa->idev, &iaddr); - if (err && err != EDPVS_EXIST && err != EDPVS_NOTEXIST) + if (EDPVS_EXIST == err) + return EDPVS_OK; + if (err) return err; if (is_master) { err = netif_mc_add(ifa->idev->dev, &eaddr); @@ -203,7 +205,9 @@ static int ifa_add_del_mcast(struct inet_ifaddr *ifa, bool add, bool is_master) } } else { err = idev_mc_del(ifa->af, ifa->idev, &iaddr); - if (err && err != EDPVS_EXIST && err != EDPVS_NOTEXIST) + if (EDPVS_NOTEXIST == err) + return EDPVS_OK; + if (err) return err; if (is_master) { err = netif_mc_del(ifa->idev->dev, &eaddr); diff --git a/src/netif.c b/src/netif.c index ff501485c..eb0402e3a 100644 --- a/src/netif.c +++ b/src/netif.c @@ -3289,25 +3289,21 @@ static int dpdk_set_mc_list(struct netif_port *dev) { struct rte_ether_addr addrs[NETIF_MAX_HWADDR]; int err; - int ret; size_t naddr = NELEMS(addrs); + if (rte_eth_allmulticast_get(dev->id) == 1) + return EDPVS_OK; + err = __netif_mc_dump(dev, addrs, &naddr); if (err != EDPVS_OK) return err; - ret = rte_eth_dev_set_mc_addr_list((uint8_t)dev->id, addrs, naddr); - if (ret == -ENOTSUP) { - /* If nic doesn't support to set multicast filter, enable all. */ - RTE_LOG(WARNING, NETIF, "%s: rte_eth_dev_set_mc_addr_list is not supported, " - "enable all multicast.\n", __func__); + err = rte_eth_dev_set_mc_addr_list(dev->id, addrs, naddr); + if (err) { + RTE_LOG(WARNING, NETIF, "%s: rte_eth_dev_set_mc_addr_list failed -- %s," + "enable all multicast\n", dev->name, rte_strerror(-err)); rte_eth_allmulticast_enable(dev->id); - return EDPVS_OK; - } - if (ret) { - RTE_LOG(WARNING, NETIF, "%s: rte_eth_dev_set_mc_addr_list failed -- %s", - dev->name, rte_strerror(ret)); - return EDPVS_DPDKAPIFAIL; + return EDPVS_OK; } return EDPVS_OK; From 5e5a618c5aa47a77dcea66b5bca9e83d14eea774 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 26 Apr 2023 18:01:56 +0800 Subject: [PATCH 015/105] netif: add config file and dpip supports for allmulticast of netif devices Signed-off-by: ywc689 --- conf/dpvs.bond.conf.sample | 4 ++ conf/dpvs.conf.items | 2 + conf/dpvs.conf.sample | 2 + conf/dpvs.conf.single-bond.sample | 2 + conf/dpvs.conf.single-nic.sample | 1 + include/conf/netif.h | 3 ++ include/ip_tunnel.h | 1 + include/netif.h | 2 + src/ip_gre.c | 11 ++--- src/ip_tunnel.c | 12 ++++++ src/ipip.c | 9 ++-- src/netif.c | 71 ++++++++++++++++++++++++++----- src/vlan.c | 9 ++++ tools/dpip/link.c | 30 +++++++++++-- 14 files changed, 136 insertions(+), 23 deletions(-) diff --git a/conf/dpvs.bond.conf.sample b/conf/dpvs.bond.conf.sample index 6e0e37137..64d4d73cb 100644 --- a/conf/dpvs.bond.conf.sample +++ b/conf/dpvs.bond.conf.sample @@ -37,6 +37,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast ! kni_name dpdk0.kni } @@ -52,6 +53,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast ! kni_name dpdk1.kni } @@ -68,6 +70,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast ! kni_name dpdk2.kni } @@ -83,6 +86,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast ! kni_name dpdk3.kni } diff --git a/conf/dpvs.conf.items b/conf/dpvs.conf.items index 315fe87c0..d2a388937 100644 --- a/conf/dpvs.conf.items +++ b/conf/dpvs.conf.items @@ -40,6 +40,7 @@ netif_defs { } ! mtu 1500 <1500,0-9000> ! promisc_mode + ! allmulticast ! kni_name dpdk0.kni } @@ -56,6 +57,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast ! kni_name dpdk1.kni } diff --git a/conf/dpvs.conf.sample b/conf/dpvs.conf.sample index 04a423257..4e9beb735 100644 --- a/conf/dpvs.conf.sample +++ b/conf/dpvs.conf.sample @@ -37,6 +37,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast kni_name dpdk0.kni } @@ -52,6 +53,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast kni_name dpdk1.kni } diff --git a/conf/dpvs.conf.single-bond.sample b/conf/dpvs.conf.single-bond.sample index db72362ec..f3d44e2d5 100644 --- a/conf/dpvs.conf.single-bond.sample +++ b/conf/dpvs.conf.single-bond.sample @@ -35,6 +35,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast ! kni_name dpdk0.kni } @@ -50,6 +51,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast ! kni_name dpdk2.kni } diff --git a/conf/dpvs.conf.single-nic.sample b/conf/dpvs.conf.single-nic.sample index 753b15348..a90dbfc2a 100644 --- a/conf/dpvs.conf.single-nic.sample +++ b/conf/dpvs.conf.single-nic.sample @@ -35,6 +35,7 @@ netif_defs { } ! mtu 1500 ! promisc_mode + ! allmulticast kni_name dpdk0.kni } } diff --git a/include/conf/netif.h b/include/conf/netif.h index e405124ae..38379b311 100644 --- a/include/conf/netif.h +++ b/include/conf/netif.h @@ -103,6 +103,7 @@ typedef struct netif_nic_basic_get portid_t port_id; uint16_t mtu; uint16_t promisc:1; /* promiscuous mode */ + uint16_t allmulticast:1; uint16_t fwd2kni:1; uint16_t tc_egress:1; uint16_t tc_ingress:1; @@ -224,6 +225,8 @@ typedef struct netif_nic_set { char macaddr[18]; uint16_t promisc_on:1; uint16_t promisc_off:1; + uint16_t allmulticast_on:1; + uint16_t allmulticast_off:1; uint16_t link_status_up:1; uint16_t link_status_down:1; uint16_t forward2kni_on:1; diff --git a/include/ip_tunnel.h b/include/ip_tunnel.h index ed775934c..499aefb69 100644 --- a/include/ip_tunnel.h +++ b/include/ip_tunnel.h @@ -101,6 +101,7 @@ int ip_tunnel_pull_header(struct rte_mbuf *mbuf, int hlen, __be16 in_proto); int ip_tunnel_get_link(struct netif_port *dev, struct rte_eth_link *link); int ip_tunnel_get_stats(struct netif_port *dev, struct rte_eth_stats *stats); int ip_tunnel_get_promisc(struct netif_port *dev, bool *promisc); +int ip_tunnel_get_allmulticast(struct netif_port *dev, bool *allmulticast); int ipip_init(void); int ipip_term(void); diff --git a/include/netif.h b/include/netif.h index bc6a64256..57d07b689 100644 --- a/include/netif.h +++ b/include/netif.h @@ -199,6 +199,7 @@ struct netif_ops { int (*op_get_queue)(struct netif_port *dev, lcoreid_t cid, queueid_t *qid); int (*op_get_link)(struct netif_port *dev, struct rte_eth_link *link); int (*op_get_promisc)(struct netif_port *dev, bool *promisc); + int (*op_get_allmulticast)(struct netif_port *dev, bool *allmulticast); int (*op_get_stats)(struct netif_port *dev, struct rte_eth_stats *stats); }; @@ -298,6 +299,7 @@ int __netif_set_mc_list(struct netif_port *port); int netif_get_queue(struct netif_port *port, lcoreid_t id, queueid_t *qid); int netif_get_link(struct netif_port *dev, struct rte_eth_link *link); int netif_get_promisc(struct netif_port *dev, bool *promisc); +int netif_get_allmulticast(struct netif_port *dev, bool *allmulticast); int netif_get_stats(struct netif_port *dev, struct rte_eth_stats *stats); struct netif_port *netif_alloc(size_t priv_size, const char *namefmt, unsigned int nrxq, unsigned int ntxq, diff --git a/src/ip_gre.c b/src/ip_gre.c index a0219846c..43fd31b8b 100644 --- a/src/ip_gre.c +++ b/src/ip_gre.c @@ -237,11 +237,12 @@ static int gre_dev_init(struct netif_port *dev) } static struct netif_ops gre_dev_ops = { - .op_init = gre_dev_init, - .op_xmit = gre_xmit, - .op_get_link = ip_tunnel_get_link, - .op_get_stats = ip_tunnel_get_stats, - .op_get_promisc = ip_tunnel_get_promisc, + .op_init = gre_dev_init, + .op_xmit = gre_xmit, + .op_get_link = ip_tunnel_get_link, + .op_get_stats = ip_tunnel_get_stats, + .op_get_promisc = ip_tunnel_get_promisc, + .op_get_allmulticast = ip_tunnel_get_allmulticast, }; static void gre_setup(struct netif_port *dev) diff --git a/src/ip_tunnel.c b/src/ip_tunnel.c index 62acbcd6c..8b6cd9668 100644 --- a/src/ip_tunnel.c +++ b/src/ip_tunnel.c @@ -934,3 +934,15 @@ int ip_tunnel_get_promisc(struct netif_port *dev, bool *promisc) return EDPVS_OK; } } + +int ip_tunnel_get_allmulticast(struct netif_port *dev, bool *allmulticast) +{ + struct ip_tunnel *tnl = netif_priv(dev); + + if (tnl->link) { + return netif_get_allmulticast(tnl->link, allmulticast); + } else { + *allmulticast = false; + return EDPVS_OK; + } +} diff --git a/src/ipip.c b/src/ipip.c index 2b4e0dcbd..8b25f0c8e 100644 --- a/src/ipip.c +++ b/src/ipip.c @@ -46,10 +46,11 @@ static int ipip_xmit(struct rte_mbuf *mbuf, struct netif_port *dev) } static struct netif_ops ipip_dev_ops = { - .op_xmit = ipip_xmit, - .op_get_link = ip_tunnel_get_link, - .op_get_stats = ip_tunnel_get_stats, - .op_get_promisc = ip_tunnel_get_promisc, + .op_xmit = ipip_xmit, + .op_get_link = ip_tunnel_get_link, + .op_get_stats = ip_tunnel_get_stats, + .op_get_promisc = ip_tunnel_get_promisc, + .op_get_allmulticast = ip_tunnel_get_allmulticast, }; /* dummy packet info for ipip tunnel. */ diff --git a/src/netif.c b/src/netif.c index eb0402e3a..d2d8b1520 100644 --- a/src/netif.c +++ b/src/netif.c @@ -104,6 +104,7 @@ struct port_conf_stream { int tx_desc_nb; bool promisc_mode; + bool allmulticast; struct list_head port_list_node; }; @@ -297,6 +298,7 @@ static void device_handler(vector_t tokens) port_cfg->mtu = NETIF_DEFAULT_ETH_MTU; port_cfg->promisc_mode = false; + port_cfg->allmulticast = false; strncpy(port_cfg->rss, "tcp", sizeof(port_cfg->rss)); list_add(&port_cfg->port_list_node, &port_list); @@ -420,6 +422,13 @@ static void promisc_mode_handler(vector_t tokens) current_device->promisc_mode = true; } +static void allmulticast_handler(vector_t tokens) +{ + struct port_conf_stream *current_device = list_entry(port_list.next, + struct port_conf_stream, port_list_node); + current_device->allmulticast = true; +} + static void custom_mtu_handler(vector_t tokens) { char *str = set_value(tokens); @@ -897,6 +906,7 @@ void install_netif_keywords(void) install_keyword("descriptor_number", tx_desc_nb_handler, KW_TYPE_INIT); install_sublevel_end(); install_keyword("promisc_mode", promisc_mode_handler, KW_TYPE_INIT); + install_keyword("allmulticast", allmulticast_handler, KW_TYPE_INIT); install_keyword("mtu", custom_mtu_handler,KW_TYPE_INIT); install_keyword("kni_name", kni_name_handler, KW_TYPE_INIT); install_sublevel_end(); @@ -3514,7 +3524,18 @@ int netif_get_promisc(struct netif_port *dev, bool *promisc) if (dev->netif_ops->op_get_promisc) return dev->netif_ops->op_get_promisc(dev, promisc); - *promisc = rte_eth_promiscuous_get((uint8_t)dev->id) ? true : false; + *promisc = rte_eth_promiscuous_get(dev->id) ? true : false; + return EDPVS_OK; +} + +int netif_get_allmulticast(struct netif_port *dev, bool *allmulticast) +{ + assert(dev && dev->netif_ops && allmulticast); + + if (dev->netif_ops->op_get_allmulticast) + return dev->netif_ops->op_get_allmulticast(dev, allmulticast); + + *allmulticast = rte_eth_allmulticast_get(dev->id) ? true : false; return EDPVS_OK; } @@ -3642,7 +3663,7 @@ static void adapt_device_conf(portid_t port_id, uint64_t *rss_hf, /* fill in rx/tx queue configurations, including queue number, * decriptor number, bonding device's rss */ -static void fill_port_config(struct netif_port *port, char *promisc_on) +static void fill_port_config(struct netif_port *port, char *promisc_on, char *allmulticast) { assert(port); @@ -3737,6 +3758,12 @@ static void fill_port_config(struct netif_port *port, char *promisc_on) else *promisc_on = 0; } + if (allmulticast) { + if (cfg_stream && cfg_stream->allmulticast) + *allmulticast = 1; + else + *allmulticast = 0; + } } static int add_bond_slaves(struct netif_port *port) @@ -3807,7 +3834,7 @@ int netif_port_start(struct netif_port *port) int ii, ret; lcoreid_t cid; queueid_t qid; - char promisc_on; + char promisc_on, allmulticast; char buf[512]; struct rte_eth_txconf txconf; struct rte_eth_link link; @@ -3817,7 +3844,7 @@ int netif_port_start(struct netif_port *port) if (unlikely(NULL == port)) return EDPVS_INVAL; - fill_port_config(port, &promisc_on); + fill_port_config(port, &promisc_on, &allmulticast); if (!port->nrxq && !port->ntxq) { RTE_LOG(WARNING, NETIF, "%s: no queues to setup for %s\n", __func__, port->name); return EDPVS_DPDKAPIFAIL; @@ -3936,6 +3963,12 @@ int netif_port_start(struct netif_port *port) rte_eth_promiscuous_enable(port->id); } + // enable allmulticast mode if configured + if (allmulticast) { + RTE_LOG(INFO, NETIF, "allmulticast enabled for device %s\n", port->name); + rte_eth_allmulticast_enable(port->id); + } + /* update mac addr to netif_port and netif_kni after start */ if (port->netif_ops->op_update_addr) port->netif_ops->op_update_addr(port); @@ -4655,6 +4688,7 @@ static int get_port_basic(struct netif_port *port, void **out, size_t *out_len) struct rte_eth_link link; netif_nic_basic_get_t *get; bool promisc; + bool allmulticast; int err; get = rte_zmalloc(NULL, sizeof(netif_nic_basic_get_t), @@ -4713,6 +4747,13 @@ static int get_port_basic(struct netif_port *port, void **out, size_t *out_len) } get->promisc = promisc ? 1 : 0; + err = netif_get_allmulticast(port, &allmulticast); + if (err != EDPVS_OK) { + rte_free(get); + return err; + } + get->allmulticast = allmulticast ? 1 : 0; + if (port->flag & NETIF_PORT_FLAG_FORWARD2KNI) get->fwd2kni = 1; if (port->flag & NETIF_PORT_FLAG_TC_EGRESS) @@ -5073,17 +5114,25 @@ static int set_port(struct netif_port *port, const netif_nic_set_t *port_cfg) assert(port_cfg); if (port_cfg->promisc_on) { - if (!rte_eth_promiscuous_get(port->id)) { + if (rte_eth_promiscuous_get(port->id) != 1) rte_eth_promiscuous_enable(port->id); - RTE_LOG(INFO, NETIF, "[%s] promiscuous mode for %s enabled\n", - __func__, port_cfg->pname); - } + RTE_LOG(INFO, NETIF, "[%s] promiscuous mode for %s enabled\n", __func__, port_cfg->pname); } else if (port_cfg->promisc_off) { - if (rte_eth_promiscuous_get(port->id)) { + if (rte_eth_promiscuous_get(port->id) != 0) rte_eth_promiscuous_disable(port->id); - RTE_LOG(INFO, NETIF, "[%s] promiscuous mode for %s disabled\n", - __func__, port_cfg->pname); + RTE_LOG(INFO, NETIF, "[%s] promiscuous mode for %s disabled\n", __func__, port_cfg->pname); + } + + if (port_cfg->allmulticast_on) { + if (rte_eth_allmulticast_get(port->id) != 1) + rte_eth_allmulticast_enable(port->id); + RTE_LOG(INFO, NETIF, "[%s] allmulticast for %s enabled\n", __func__, port_cfg->pname); + } else if (port_cfg->allmulticast_off) { + if (rte_eth_allmulticast_get(port->id) != 0) { + rte_eth_allmulticast_disable(port->id); + netif_set_mc_list(port); } + RTE_LOG(INFO, NETIF, "[%s] allmulticast for %s disabled\n", __func__, port_cfg->pname); } if (port_cfg->forward2kni_on) { diff --git a/src/vlan.c b/src/vlan.c index 65c27d884..1b06aea3b 100644 --- a/src/vlan.c +++ b/src/vlan.c @@ -154,6 +154,14 @@ static int vlan_get_promisc(struct netif_port *dev, bool *promisc) return netif_get_promisc(vlan->real_dev, promisc); } +static int vlan_get_allmulticast(struct netif_port *dev, bool *allmulticast) +{ + struct vlan_dev_priv *vlan = netif_priv(dev); + assert(vlan && vlan->real_dev); + + return netif_get_allmulticast(vlan->real_dev, allmulticast); +} + static int vlan_get_stats(struct netif_port *dev, struct rte_eth_stats *stats) { struct vlan_dev_priv *vlan = netif_priv(dev); @@ -168,6 +176,7 @@ static struct netif_ops vlan_netif_ops = { .op_get_queue = vlan_get_queue, .op_get_link = vlan_get_link, .op_get_promisc = vlan_get_promisc, + .op_get_allmulticast = vlan_get_allmulticast, .op_get_stats = vlan_get_stats, }; diff --git a/tools/dpip/link.c b/tools/dpip/link.c index 7ca50d02a..df518bc4a 100644 --- a/tools/dpip/link.c +++ b/tools/dpip/link.c @@ -126,7 +126,7 @@ static void link_help(void) " dpip link set DEV-NAME ITEM VALUE\n" " ---supported items---\n" " promisc [on|off], forward2kni [on|off], link [up|down],\n" - " tc-egress [on|off], tc-ingress [on|off], addr, \n" + " allmulticast [on|off], tc-egress [on|off], tc-ingress [on|off], addr, \n" " bond-[mode|slave|primary|xmit-policy|monitor-interval|link-up-prop|" "link-down-prop]\n" @@ -246,6 +246,9 @@ static int dump_nic_basic(char *name, int namelen) if (get.promisc) printf("promisc "); + if (get.allmulticast) + printf("allmulticast "); + if (get.fwd2kni) printf("foward2kni "); @@ -354,7 +357,7 @@ static int dump_nic_verbose(char *name, int namelen) ext_get->cfg_queues.data_offset); if (ext_get->cfg_queues.data_len > strlen(ext_get->data + ext_get->cfg_queues.data_offset)) { - printf(" ... (truncated)"); + printf(" ... (truncated)\n"); } } @@ -362,7 +365,7 @@ static int dump_nic_verbose(char *name, int namelen) printf(" HW mcast list:\n%s", ext_get->data + ext_get->mc_list.data_offset); if (ext_get->mc_list.data_len > strlen(ext_get->data + ext_get->mc_list.data_offset)) { - printf(" ... (truncated)"); + printf(" ... (truncated)\n"); } } @@ -819,6 +822,25 @@ static int link_nic_set_promisc(const char *name, const char *value) return dpvs_setsockopt(SOCKOPT_NETIF_SET_PORT, &cfg, sizeof(netif_nic_set_t)); } +static int link_nic_set_allmulticast(const char *name, const char *value) +{ + assert(value); + + netif_nic_set_t cfg; + memset(&cfg, 0, sizeof(cfg)); + strncpy(cfg.pname, name, sizeof(cfg.pname) - 1); + if (strcmp(value, "on") == 0) + cfg.allmulticast_on = 1; + else if(strcmp(value, "off") == 0) + cfg.allmulticast_off = 1; + else { + fprintf(stderr, "invalid arguement value for 'allmulticast'\n"); + return EDPVS_INVAL; + } + + return dpvs_setsockopt(SOCKOPT_NETIF_SET_PORT, &cfg, sizeof(netif_nic_set_t)); +} + static int link_nic_set_forward2kni(const char *name, const char *value) { assert(value); @@ -1118,6 +1140,8 @@ static int link_set(struct link_param *param) { if (strcmp(param->item, "promisc") == 0) link_nic_set_promisc(param->dev_name, param->value); + else if (strcmp(param->item, "allmulticast") == 0) + link_nic_set_allmulticast(param->dev_name, param->value); else if (strcmp(param->item, "forward2kni") == 0) link_nic_set_forward2kni(param->dev_name, param->value); else if (strcmp(param->item, "link") == 0) From 7eb3c58b5f7f3d364859acd9f274259756852ecc Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 27 Apr 2023 09:24:13 +0800 Subject: [PATCH 016/105] netif: fix divided by zero crash problem when bonding slaves sending packets out Signed-off-by: ywc689 --- src/netif.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/netif.c b/src/netif.c index d2d8b1520..3ba0bafbe 100644 --- a/src/netif.c +++ b/src/netif.c @@ -2212,7 +2212,7 @@ static inline int validate_xmit_mbuf(struct rte_mbuf *mbuf, int netif_hard_xmit(struct rte_mbuf *mbuf, struct netif_port *dev) { lcoreid_t cid; - int pid, qindex; + int pid, qindex, ntxq; struct netif_queue_conf *txq; struct netif_ops *ops; int ret = EDPVS_OK; @@ -2268,9 +2268,15 @@ int netif_hard_xmit(struct rte_mbuf *mbuf, struct netif_port *dev) /* port id is determined by routing */ pid = dev->id; + ntxq = lcore_conf[lcore2index[cid]].pqs[port2index[cid][pid]].ntxq; + if (unlikely(ntxq <= 0)) { + RTE_LOG(WARNING, NETIF, "%s: no txq on device %s, drop the sending packet\n", __func__, dev->name); + rte_pktmbuf_free(mbuf); + lcore_stats[cid].dropped++; + return EDPVS_RESOURCE; + } /* qindex is hashed by physical address of mbuf */ - qindex = (((uint32_t) mbuf->buf_iova) >> 8) % - (lcore_conf[lcore2index[cid]].pqs[port2index[cid][pid]].ntxq); + qindex = (((uint32_t) mbuf->buf_iova) >> 8) % ntxq; //RTE_LOG(DEBUG, NETIF, "tx-queue hash(%x) = %d\n", ((uint32_t)mbuf->buf_iova) >> 8, qindex); txq = &lcore_conf[lcore2index[cid]].pqs[port2index[cid][pid]].txqs[qindex]; From 4fc35b74324f5c8a5a55cf0cd6adf62a0c4ca2d2 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 27 Apr 2023 18:45:51 +0800 Subject: [PATCH 017/105] netif: fix invalid port problem when getting nic extra info Signed-off-by: ywc689 --- src/netif.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/netif.c b/src/netif.c index 3ba0bafbe..1b773bad8 100644 --- a/src/netif.c +++ b/src/netif.c @@ -160,6 +160,16 @@ static struct list_head port_ntab[NETIF_PORT_TABLE_BUCKETS]; /* hashed by name * /* function declarations */ static void kni_lcore_loop(void *dummy); +static inline bool is_physical_port(portid_t pid) +{ + return pid >= phy_pid_base && pid < phy_pid_end; +} + +static inline bool is_bond_port(portid_t pid) +{ + return pid >= bond_pid_base && pid < bond_pid_end; +} + bool is_lcore_id_valid(lcoreid_t cid) { if (unlikely(cid >= DPVS_MAX_LCORE)) @@ -3152,7 +3162,7 @@ static inline int port_name_alloc(portid_t pid, char *pname, size_t buflen) { assert(pname && buflen > 0); memset(pname, 0, buflen); - if (pid >= phy_pid_base && pid < phy_pid_end) { + if (is_physical_port(pid)) { struct port_conf_stream *current_cfg; list_for_each_entry_reverse(current_cfg, &port_list, port_list_node) { if (current_cfg->port_id < 0) { @@ -3166,7 +3176,7 @@ static inline int port_name_alloc(portid_t pid, char *pname, size_t buflen) } RTE_LOG(ERR, NETIF, "%s: not enough ports configured in dpvs.conf\n", __func__); return EDPVS_NOTEXIST; - } else if (pid >= bond_pid_base && pid < bond_pid_end) { + } else if (is_bond_port(pid)) { struct bond_conf_stream *current_cfg; list_for_each_entry_reverse(current_cfg, &bond_list, bond_list_node) { if (current_cfg->port_id == pid) { @@ -3396,10 +3406,10 @@ static struct netif_port* netif_rte_port_alloc(portid_t id, int nrxq, port->id = id; port->bond = (union netif_bond *)(port + 1); - if (id >= phy_pid_base && id < phy_pid_end) { + if (is_physical_port(id)) { port->type = PORT_TYPE_GENERAL; /* update later in netif_rte_port_alloc */ port->netif_ops = &dpdk_netif_ops; - } else if (id >= bond_pid_base && id < bond_pid_end) { + } else if (is_bond_port(id)) { port->type = PORT_TYPE_BOND_MASTER; port->netif_ops = &bond_netif_ops; } else { @@ -4831,7 +4841,7 @@ static int get_port_ext_info(struct netif_port *port, void **out, size_t *out_le { assert(out || out_len); - struct rte_eth_dev_info dev_info; + struct rte_eth_dev_info dev_info = { 0 }; netif_nic_ext_get_t *get, *new; char ctrlbuf[NETIF_CTRL_BUFFER_LEN]; int len, naddr, err; @@ -4844,8 +4854,10 @@ static int get_port_ext_info(struct netif_port *port, void **out, size_t *out_le get->port_id = port->id; /* dev info */ - rte_eth_dev_info_get(port->id, &dev_info); - copy_dev_info(&get->dev_info, &dev_info); + if (is_physical_port( port->id) || is_bond_port(port->id)) { + rte_eth_dev_info_get(port->id, &dev_info); + copy_dev_info(&get->dev_info, &dev_info); + } /* cfg_queues */ if (port->type == PORT_TYPE_GENERAL || From 50a863d7c50d211c92fa47cb7d636d2b6de300a1 Mon Sep 17 00:00:00 2001 From: roykingz Date: Tue, 16 May 2023 20:44:35 +0800 Subject: [PATCH 018/105] keepalived: don't delete and re-add vs/rs when update at reload when update vs/rs configuration parameters at keepalived reload, it's no need to delete and re-add vs/rs, which will result in traffic interruption of the vs/rs. --- .../keepalived/keepalived/check/ipvswrapper.c | 8 +- tools/keepalived/keepalived/check/ipwrapper.c | 177 +++++++++++++++--- 2 files changed, 152 insertions(+), 33 deletions(-) diff --git a/tools/keepalived/keepalived/check/ipvswrapper.c b/tools/keepalived/keepalived/check/ipvswrapper.c index ce9b5f97b..c69e0a913 100755 --- a/tools/keepalived/keepalived/check/ipvswrapper.c +++ b/tools/keepalived/keepalived/check/ipvswrapper.c @@ -778,7 +778,7 @@ static void ipvs_set_srule(int cmd, dpvs_service_compat_t *srule, virtual_server } if (vs->persistence_timeout && - (cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_DEL)) { + (cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_DEL || cmd == IP_VS_SO_SET_EDIT)) { srule->timeout = vs->persistence_timeout; srule->flags |= IP_VS_SVC_F_PERSISTENT; @@ -832,7 +832,11 @@ ipvs_set_drule(int cmd, dpvs_dest_compat_t *drule, real_server_t * rs) drule->port = inet_sockaddrport(&rs->addr); drule->conn_flags = rs->forwarding_method; - drule->weight = rs->weight; + /*Do not change dead rs weight in dpvs at reload*/ + if (cmd == IP_VS_SO_SET_EDITDEST && rs->reloaded && rs->set && !ISALIVE(rs)) + drule->weight = 0; + else + drule->weight = rs->weight; drule->max_conn = rs->u_threshold; drule->min_conn = rs->l_threshold; #ifdef _HAVE_IPVS_TUN_TYPE_ diff --git a/tools/keepalived/keepalived/check/ipwrapper.c b/tools/keepalived/keepalived/check/ipwrapper.c index 915fb940b..0a3ff916d 100755 --- a/tools/keepalived/keepalived/check/ipwrapper.c +++ b/tools/keepalived/keepalived/check/ipwrapper.c @@ -37,6 +37,32 @@ #include "smtp.h" #include "check_daemon.h" +static bool __attribute((pure)) +vs_iseq(const virtual_server_t *vs_a, const virtual_server_t *vs_b) +{ + if (!vs_a->vsgname != !vs_b->vsgname) + return false; + + if (vs_a->vsgname) { + /* Should we check the vsg entries match? */ + if (inet_sockaddrport(&vs_a->addr) != inet_sockaddrport(&vs_b->addr)) + return false; + + return !strcmp(vs_a->vsgname, vs_b->vsgname); + } else if (vs_a->af != vs_b->af) + return false; + else if (vs_a->vfwmark) { + if (vs_a->vfwmark != vs_b->vfwmark) + return false; + } else { + if (vs_a->service_type != vs_b->service_type || + !sockstorage_equal(&vs_a->addr, &vs_b->addr)) + return false; + } + + return true; +} + static bool __attribute((pure)) vsge_iseq(const virtual_server_group_entry_t *vsge_a, const virtual_server_group_entry_t *vsge_b) { @@ -53,13 +79,11 @@ vsge_iseq(const virtual_server_group_entry_t *vsge_a, const virtual_server_group return true; } -#if 0 static bool __attribute((pure)) rs_iseq(const real_server_t *rs_a, const real_server_t *rs_b) { return sockstorage_equal(&rs_a->addr, &rs_b->addr); } -#endif /* Returns the sum of all alive RS weight in a virtual server. */ static unsigned long __attribute__ ((pure)) @@ -836,7 +860,7 @@ vs_exist(virtual_server_t * old_vs) virtual_server_t *vs; LIST_FOREACH(check_data->vs, vs, e) { - if (VS_ISEQ(old_vs, vs)) + if (vs_iseq(old_vs, vs)) return vs; } @@ -854,7 +878,7 @@ rs_exist(real_server_t * old_rs, list l) return NULL; LIST_FOREACH(l, rs, e) { - if (RS_ISEQ(rs, old_rs)) + if (rs_iseq(rs, old_rs)) return rs; } @@ -979,7 +1003,11 @@ clear_diff_rs(virtual_server_t *old_vs, virtual_server_t *new_vs, list old_check migrate_checkers(new_vs, rs, new_rs, old_checkers_queue); /* Do we need to update the RS configuration? */ - if (false || + /* RS without inhibit flag may already be deleted by keepalived because + * of failed healthcheck, we only edit rs if rs exists in dpvs at reload. + * When RS without inhibit flag becomes alive , keepalived will re-adds it in dpvs. + */ + if (new_rs->set && (false || #ifdef _HAVE_IPVS_TUN_TYPE_ rs->tun_type != new_rs->tun_type || rs->tun_port != new_rs->tun_port || @@ -987,7 +1015,10 @@ clear_diff_rs(virtual_server_t *old_vs, virtual_server_t *new_vs, list old_check rs->tun_flags != new_rs->tun_flags || #endif #endif - rs->forwarding_method != new_rs->forwarding_method) + rs->forwarding_method != new_rs->forwarding_method|| + /* no need to check rs weight, because rs weight will be updated by init_service_rs */ + rs->u_threshold != new_rs->u_threshold || + rs->l_threshold != new_rs->l_threshold)) ipvs_cmd(LVS_CMD_EDIT_DEST, new_vs, new_rs); } } @@ -1068,9 +1099,24 @@ clear_diff_laddr_entry(list old, list new, virtual_server_t * old_vs) return 1; } +/* clear all local address entry of the vs */ +static int +clear_all_laddr_entry(list l, virtual_server_t * vs) +{ + element e; + local_addr_entry *laddr_entry; + + LIST_FOREACH(l, laddr_entry, e) { + if (!ipvs_laddr_remove_entry(vs, laddr_entry)) + return 0; + } + + return 1; +} + /* Clear the diff local address of the old vs */ static int -clear_diff_laddr(virtual_server_t * old_vs) +clear_diff_laddr(virtual_server_t * old_vs, virtual_server_t * new_vs) { local_addr_group *old; local_addr_group *new; @@ -1079,15 +1125,27 @@ clear_diff_laddr(virtual_server_t * old_vs) * If old vs was not in fulllnat mod or didn't own local address group, * then do nothing and return */ + /*Fixme: Can we change laddr of vs in SNAT mode ?*/ if ((old_vs->forwarding_method != IP_VS_CONN_F_FULLNAT) || !old_vs->local_addr_gname) return 1; - - /* Fetch local address group */ - old = ipvs_get_laddr_group_by_name(old_vs->local_addr_gname, - old_check_data->laddr_group); - new = ipvs_get_laddr_group_by_name(old_vs->local_addr_gname, - check_data->laddr_group); + else + /* Fetch old_vs local address group */ + old = ipvs_get_laddr_group_by_name(old_vs->local_addr_gname, + old_check_data->laddr_group); + + /* if new_vs has no local address group, delete all local address from old_vs */ + if (!new_vs->local_addr_gname) { + if (!clear_all_laddr_entry(old->addr_ip, old_vs)) + return 0; + if (!clear_all_laddr_entry(old->range, old_vs)) + return 0; + return 1; + } + else + /* Fetch new_vs local address group */ + new = ipvs_get_laddr_group_by_name(new_vs->local_addr_gname, + check_data->laddr_group); if (!clear_diff_laddr_entry(old->addr_ip, new->addr_ip, old_vs)) return 0; @@ -1134,9 +1192,24 @@ clear_diff_blklst_entry(list old, list new, virtual_server_t * old_vs) return 1; } +/* clear all blacklist address entry of the vs */ +static int +clear_all_blklst_entry(list l, virtual_server_t * vs) +{ + element e; + blklst_addr_entry *blklst_entry; + + LIST_FOREACH(l, blklst_entry, e) { + if (!ipvs_blklst_remove_entry(vs, blklst_entry)) + return 0; + } + + return 1; +} + /* Clear the diff blacklist address of the old vs */ static int -clear_diff_blklst(virtual_server_t * old_vs) +clear_diff_blklst(virtual_server_t * old_vs, virtual_server_t * new_vs) { blklst_addr_group *old; blklst_addr_group *new; @@ -1147,12 +1220,23 @@ clear_diff_blklst(virtual_server_t * old_vs) */ if (!old_vs->blklst_addr_gname) return 1; - - /* Fetch blacklist address group */ - old = ipvs_get_blklst_group_by_name(old_vs->blklst_addr_gname, - old_check_data->blklst_group); - new = ipvs_get_blklst_group_by_name(old_vs->blklst_addr_gname, - check_data->blklst_group); + else + /* Fetch old_vs blacklist address group */ + old = ipvs_get_blklst_group_by_name(old_vs->blklst_addr_gname, + old_check_data->blklst_group); + + /* if new_vs has no blacklist group, delete all blklst address from old_vs */ + if (!new_vs->blklst_addr_gname) { + if (!clear_all_blklst_entry(old->addr_ip, old_vs)) + return 0; + if (!clear_all_blklst_entry(old->range, old_vs)) + return 0; + return 1; + } + else + /* Fetch new_vs blacklist address group */ + new = ipvs_get_blklst_group_by_name(new_vs->blklst_addr_gname, + check_data->blklst_group); if (!clear_diff_blklst_entry(old->addr_ip, new->addr_ip, old_vs)) return 0; @@ -1201,9 +1285,24 @@ clear_diff_whtlst_entry(list old, list new, virtual_server_t * old_vs) return 1; } +/* clear all whitelist address entry of the vs */ +static int +clear_all_whtlst_entry(list l, virtual_server_t * vs) +{ + element e; + whtlst_addr_entry *whtlst_entry; + + LIST_FOREACH(l, whtlst_entry, e) { + if (!ipvs_whtlst_remove_entry(vs, whtlst_entry)) + return 0; + } + + return 1; +} + /* Clear the diff whitelist address of the old vs */ static int -clear_diff_whtlst(virtual_server_t * old_vs) +clear_diff_whtlst(virtual_server_t * old_vs, virtual_server_t * new_vs) { whtlst_addr_group *old; whtlst_addr_group *new; @@ -1213,12 +1312,22 @@ clear_diff_whtlst(virtual_server_t * old_vs) */ if (!old_vs->whtlst_addr_gname) return 1; - - /* Fetch whitelist address group */ - old = ipvs_get_whtlst_group_by_name(old_vs->whtlst_addr_gname, - old_check_data->whtlst_group); - new = ipvs_get_whtlst_group_by_name(old_vs->whtlst_addr_gname, - check_data->whtlst_group); + else + /* Fetch whitelist address group */ + old = ipvs_get_whtlst_group_by_name(old_vs->whtlst_addr_gname, + old_check_data->whtlst_group); + /* if new_vs has no whitelist group, delete all whtlst address from old_vs */ + if (!new_vs->whtlst_addr_gname) { + if (!clear_all_whtlst_entry(old->addr_ip, old_vs)) + return 0; + if (!clear_all_whtlst_entry(old->range, old_vs)) + return 0; + return 1; + } + else + /* Fetch new_vs whitelist address group */ + new = ipvs_get_whtlst_group_by_name(new_vs->whtlst_addr_gname, + check_data->whtlst_group); if (!clear_diff_whtlst_entry(old->addr_ip, new->addr_ip, old_vs)) return 0; @@ -1269,7 +1378,13 @@ clear_diff_services(list old_checkers_queue) if (strcmp(vs->sched, new_vs->sched) || vs->flags != new_vs->flags || vs->persistence_granularity != new_vs->persistence_granularity || - vs->persistence_timeout != new_vs->persistence_timeout) { + vs->persistence_timeout != new_vs->persistence_timeout || + vs->conn_timeout != new_vs->conn_timeout || + vs->bps != new_vs->bps || vs->limit_proportion != new_vs->limit_proportion || + vs->hash_target != new_vs->hash_target || vs->syn_proxy != new_vs->syn_proxy || + vs->expire_quiescent_conn != new_vs->expire_quiescent_conn || + strcmp(vs->srange, new_vs->srange) || strcmp(vs->drange, new_vs->drange) || + strcmp(vs->iifname, new_vs->iifname) || strcmp(vs->oifname, new_vs->oifname)) { ipvs_cmd(IP_VS_SO_SET_EDIT, new_vs, NULL); } @@ -1279,13 +1394,13 @@ clear_diff_services(list old_checkers_queue) update_alive_counts(vs, new_vs); /* perform local address diff */ - if (!clear_diff_laddr(vs)) + if (!clear_diff_laddr(vs, new_vs)) return; /* perform blacklist address diff */ - if (!clear_diff_blklst(vs)) + if (!clear_diff_blklst(vs, new_vs)) return; /* perform whitelist address diff */ - if (!clear_diff_whtlst(vs)) + if (!clear_diff_whtlst(vs, new_vs)) return; } From fe470654d43c190b7e06ad8b1b8ae686eba8e9ca Mon Sep 17 00:00:00 2001 From: huangyichen Date: Tue, 16 May 2023 14:19:42 +0800 Subject: [PATCH 019/105] unregister msg MSG_TYPE_AGENT_GET_DESTS callback --- src/ipvs/ip_vs_dest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 34a1fc46c..4e2c3ce0e 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -632,7 +632,7 @@ static int dest_unregister_msg_cb(void) msg_type.prio = MSG_PRIO_LOW; msg_type.cid = rte_lcore_id(); msg_type.unicast_msg_cb = dp_vs_dests_get_uc_cb; - err = msg_type_mc_register(&msg_type); + err = msg_type_mc_unregister(&msg_type); if (err != EDPVS_OK) { RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); if (rterr == EDPVS_OK) From f194cec4d43b98ad8f323fcedd37da535e0fc1d6 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Tue, 16 May 2023 20:31:26 +0800 Subject: [PATCH 020/105] return laddr device name to dpvs-agent --- src/ipvs/ip_vs_laddr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ipvs/ip_vs_laddr.c b/src/ipvs/ip_vs_laddr.c index bd8bf2367..2389c7224 100644 --- a/src/ipvs/ip_vs_laddr.c +++ b/src/ipvs/ip_vs_laddr.c @@ -385,6 +385,7 @@ static int dpvs_agent_laddr_getall(struct dp_vs_service *svc, (*addrs)[i].af = laddr->af; (*addrs)[i].addr = laddr->addr; (*addrs)[i].conns = rte_atomic32_read(&laddr->conn_counts); + rte_strlcpy((*addrs)[i].ifname, laddr->iface->name, IFNAMSIZ); i++; } } else { @@ -633,6 +634,7 @@ static int agent_get_msg_cb(struct dpvs_msg *msg) laddrs->laddrs[i].af = addrs[i].af; laddrs->laddrs[i].addr = addrs[i].addr; /* TODO: nport_conflict & nconns */ + rte_memcpy(laddrs->laddrs[i].ifname, addrs[i].ifname, IFNAMSIZ); laddrs->laddrs[i].nport_conflict = 0; laddrs->laddrs[i].conns = addrs[i].conns; } @@ -870,6 +872,7 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, for (i = 0; i < naddr; i++) { out_front->laddrs[i].af = details[i].af; out_front->laddrs[i].addr = details[i].addr; + rte_strlcpy(out_front->laddrs[i].ifname, details[i].ifname, IFNAMSIZ); out_front->laddrs[i].nport_conflict = 0; out_front->laddrs[i].conns = details[i].conns; } From 27e8ffdc579039e89dc90ab6530c72577743d1a6 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 22 May 2023 18:50:54 +0800 Subject: [PATCH 021/105] add dest edit --- include/conf/sockopts.h | 1 + include/ctrl.h | 1 + src/ipvs/ip_vs_dest.c | 53 ++++++++++++++++++++++++++++++++++++----- src/ipvs/ip_vs_laddr.c | 3 ++- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/include/conf/sockopts.h b/include/conf/sockopts.h index 9a0a7e035..57d5c36e4 100644 --- a/include/conf/sockopts.h +++ b/include/conf/sockopts.h @@ -53,6 +53,7 @@ \ DPVSMSG(DPVSAGENT_VS_GET_DESTS) \ DPVSMSG(DPVSAGENT_VS_ADD_DESTS) \ + DPVSMSG(DPVSAGENT_VS_EDIT_DESTS) \ DPVSMSG(DPVSAGENT_VS_DEL_DESTS) \ \ DPVSMSG(SOCKOPT_SET_ROUTE_ADD) \ diff --git a/include/ctrl.h b/include/ctrl.h index eb383df13..221cdc786 100644 --- a/include/ctrl.h +++ b/include/ctrl.h @@ -237,6 +237,7 @@ enum { MSG_TYPE_AGENT_ADD_LADDR, MSG_TYPE_AGENT_DEL_LADDR, MSG_TYPE_AGENT_ADD_DESTS, + MSG_TYPE_AGENT_EDIT_DESTS, MSG_TYPE_AGENT_DEL_DESTS, #endif }; diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 4e2c3ce0e..40bd384e4 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -373,6 +373,7 @@ static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len) struct dpvs_msg *msg; struct dp_vs_service *getsvc; int i, ret = EDPVS_INVAL; + msgid_t msg_id = MSG_TYPE_IPVS_RANGE_START; lcoreid_t cid; insvc = (struct dp_vs_dest_front*)user; @@ -387,13 +388,20 @@ static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len) } if (cid == rte_get_main_lcore()) { - if (opt == DPVSAGENT_VS_ADD_DESTS) { - msg = msg_make(MSG_TYPE_AGENT_ADD_DESTS, dest_msg_seq(), DPVS_MSG_MULTICAST, cid, len, user); - } else if (opt == DPVSAGENT_VS_DEL_DESTS) { - msg = msg_make(MSG_TYPE_AGENT_DEL_DESTS, dest_msg_seq(), DPVS_MSG_MULTICAST, cid, len, user); - } else { - return EDPVS_NOTSUPP; + switch (opt) { + case DPVSAGENT_VS_ADD_DESTS: + msg_id = MSG_TYPE_AGENT_ADD_DESTS; + break; + case DPVSAGENT_VS_DEL_DESTS: + msg_id = MSG_TYPE_AGENT_DEL_DESTS; + break; + case DPVSAGENT_VS_EDIT_DESTS: + msg_id = MSG_TYPE_AGENT_EDIT_DESTS; + break; + default: + return EDPVS_NOTSUPP; } + msg = msg_make(msg_id, dest_msg_seq(), DPVS_MSG_MULTICAST, cid, len, user); if (!msg) return EDPVS_NOMEM; @@ -418,6 +426,9 @@ static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len) if (ret == EDPVS_EXIST) ret = dp_vs_dest_edit(getsvc, &udest); break; + case DPVSAGENT_VS_EDIT_DESTS: + ret = dp_vs_dest_edit(getsvc, &udest); + break; case DPVSAGENT_VS_DEL_DESTS: ret = dp_vs_dest_del(getsvc, &udest); break; @@ -565,6 +576,11 @@ static int deldest_msg_cb(struct dpvs_msg *msg) return dp_vs_dest_set(DPVSAGENT_VS_DEL_DESTS, msg->data, msg->len); } +static int editdest_msg_cb(struct dpvs_msg *msg) +{ + return dp_vs_dest_set(DPVSAGENT_VS_EDIT_DESTS, msg->data, msg->len); +} + static int dp_vs_dests_get_uc_cb(struct dpvs_msg *msg) { lcoreid_t cid = rte_lcore_id(); @@ -626,6 +642,19 @@ static int dest_unregister_msg_cb(void) rterr = err; } + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_EDIT_DESTS; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = editdest_msg_cb; + err = msg_type_mc_unregister(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + if (rterr == EDPVS_OK) + rterr = err; + } + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_GET_DESTS; msg_type.mode = DPVS_MSG_MULTICAST; @@ -684,6 +713,18 @@ int dp_vs_dest_init(void) return err; } + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); + msg_type.type = MSG_TYPE_AGENT_EDIT_DESTS; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = rte_lcore_id(); + msg_type.unicast_msg_cb = editdest_msg_cb; + err = msg_type_mc_register(&msg_type); + if (err != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + return err; + } + memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_GET_DESTS; msg_type.mode = DPVS_MSG_MULTICAST; diff --git a/src/ipvs/ip_vs_laddr.c b/src/ipvs/ip_vs_laddr.c index 2389c7224..080c9e260 100644 --- a/src/ipvs/ip_vs_laddr.c +++ b/src/ipvs/ip_vs_laddr.c @@ -576,7 +576,8 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) details = (struct dp_vs_laddr_detail*)((char*)conf + sizeof(struct dp_vs_laddr_front)); for (i = 0; i < laddr_front->count; i++) { detail = (struct dp_vs_laddr_detail*)((char*)details + sizeof(struct dp_vs_laddr_detail) * i); - err = dp_vs_laddr_del(svc, detail->af, &detail->addr); if (err != EDPVS_OK) { + err = dp_vs_laddr_del(svc, detail->af, &detail->addr); + if (err != EDPVS_OK) { if (err == EDPVS_NOTEXIST) continue; break; From a5ce22251b3616a56287443c48ba0785269fe30e Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 14 Apr 2023 21:03:34 +0800 Subject: [PATCH 022/105] ipvs: backend passive health check It works only for TCP by checking if syn-ack is replied from the backend, and if not, inhibit scheduling the backend for a period. The inhibiting period is gained/lost exponentially after successive checking failed/succeeded. Signed-off-by: ywc689 --- include/conf/dest.h | 5 +- include/conf/service.h | 1 + include/ctrl.h | 2 + include/ipvs/dest.h | 42 +- include/ipvs/service.h | 1 + src/config.mk | 1 + src/ctrl.c | 2 +- src/ipvs/ip_vs_conn.c | 6 + src/ipvs/ip_vs_dest.c | 446 ++++++++++++++++-- src/ipvs/ip_vs_proto_tcp.c | 9 + src/ipvs/ip_vs_synproxy.c | 2 + tools/ipvsadm/ipvsadm.c | 62 ++- tools/keepalived/keepalived/check/libipvs.c | 10 +- tools/keepalived/keepalived/include/libipvs.h | 5 +- 14 files changed, 535 insertions(+), 59 deletions(-) diff --git a/include/conf/dest.h b/include/conf/dest.h index 827dcd77e..78ad6ff47 100644 --- a/include/conf/dest.h +++ b/include/conf/dest.h @@ -37,8 +37,9 @@ enum dpvs_fwd_mode { }; enum { - DPVS_DEST_F_AVAILABLE = 0x1<<0, - DPVS_DEST_F_OVERLOAD = 0x1<<1, + DPVS_DEST_F_AVAILABLE = 0x1<<0, // dest removed + DPVS_DEST_F_OVERLOAD = 0x1<<1, // too many conns + DPVS_DEST_F_INHIBITED = 0x1<<2, // dest forwarding failure }; typedef struct dp_vs_dest_compat { diff --git a/include/conf/service.h b/include/conf/service.h index 12ae409b3..30fa02c7c 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -40,6 +40,7 @@ #define IP_VS_SVC_F_SIP_HASH 0x0100 /* sip hash target */ #define IP_VS_SVC_F_QID_HASH 0x0200 /* quic cid hash target */ #define IP_VS_SVC_F_MATCH 0x0400 /* snat match */ +#define IP_VS_SVC_F_DEST_CHECK 0x0800 /* inhibit rs on failure */ #define IP_VS_SVC_F_SCHED_SH_FALLBACK IP_VS_SVC_F_SCHED1 /* SH fallback */ #define IP_VS_SVC_F_SCHED_SH_PORT IP_VS_SVC_F_SCHED2 /* SH use port */ diff --git a/include/ctrl.h b/include/ctrl.h index 221cdc786..888113f89 100644 --- a/include/ctrl.h +++ b/include/ctrl.h @@ -211,6 +211,8 @@ int msg_dump(const struct dpvs_msg *msg, char *buf, int len); #define MSG_TYPE_TC_CLS_GET 29 #define MSG_TYPE_TC_CLS_SET 30 #define MSG_TYPE_IPSET_SET 40 +#define MSG_TYPE_DEST_CHECK_NOTIFY_MASTER 41 +#define MSG_TYPE_DEST_CHECK_NOTIFY_SLAVES 42 #define MSG_TYPE_IPVS_RANGE_START 100 /* for svc per_core, refer to service.h*/ diff --git a/include/ipvs/dest.h b/include/ipvs/dest.h index d9545f552..bccb89167 100644 --- a/include/ipvs/dest.h +++ b/include/ipvs/dest.h @@ -24,6 +24,20 @@ #include "conf/common.h" #include "list.h" #include "dpdk.h" +#include "timer.h" + +union dest_check { + struct { + uint16_t origin_weight; + uint16_t down_notice_recvd; // how many DOWN notifications has received + uint32_t inhibit_duration; // inhibited duration on failure, gains/loses exponentially, in seconds + struct dpvs_timer timer; // down-wait-timer in UP state, rs-inhibit-timer in DOWN state + } master; + struct { + uint16_t origin_weight; + uint16_t warm_up_count; // how many UP notifications has sent after state going Up + } slave; +}; struct dp_vs_dest { struct list_head n_list; /* for the dests in the service */ @@ -61,10 +75,12 @@ struct dp_vs_dest { union inet_addr vaddr; /* virtual IP address */ unsigned conn_timeout; /* conn timeout copied from svc*/ unsigned limit_proportion; /* limit copied from svc*/ + + union dest_check dfc; /* failure detection and inhibition */ } __rte_cache_aligned; static inline bool -dp_vs_dest_is_avail(struct dp_vs_dest *dest) +dp_vs_dest_is_avail(const struct dp_vs_dest *dest) { return (dest->flags & DPVS_DEST_F_AVAILABLE) ? true : false; } @@ -82,11 +98,29 @@ dp_vs_dest_clear_avail(struct dp_vs_dest *dest) } static inline bool -dp_vs_dest_is_overload(struct dp_vs_dest *dest) +dp_vs_dest_is_overload(const struct dp_vs_dest *dest) { return (dest->flags & DPVS_DEST_F_OVERLOAD) ? true : false; } +static inline bool +dp_vs_dest_is_inhibited(const struct dp_vs_dest *dest) +{ + return (dest->flags & DPVS_DEST_F_INHIBITED) ? true : false; +} + +static inline void +dp_vs_dest_set_inhibited(struct dp_vs_dest *dest) +{ + dest->flags |= DPVS_DEST_F_INHIBITED; +} + +static inline void +dp_vs_dest_clear_inhibited(struct dp_vs_dest *dest) +{ + dest->flags &= ~DPVS_DEST_F_INHIBITED; +} + static inline int16_t dp_vs_dest_get_weight(struct dp_vs_dest *dest) { @@ -99,6 +133,7 @@ dp_vs_dest_is_valid(struct dp_vs_dest *dest) return (dest && dp_vs_dest_is_avail(dest) && !dp_vs_dest_is_overload(dest) + && !dp_vs_dest_is_inhibited(dest) && dp_vs_dest_get_weight(dest) > 0) ? true : false; } @@ -122,6 +157,9 @@ int dp_vs_dest_del(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest); int dp_vs_dest_get_entries(const struct dp_vs_service *svc, struct dp_vs_get_dests *uptr); +int dp_vs_dest_detected_alive(struct dp_vs_dest *dest); +int dp_vs_dest_detected_dead(struct dp_vs_dest *dest); + int dp_vs_dest_init(void); int dp_vs_dest_term(void); diff --git a/include/ipvs/service.h b/include/ipvs/service.h index 1b8328fd0..336dbda6f 100644 --- a/include/ipvs/service.h +++ b/include/ipvs/service.h @@ -43,6 +43,7 @@ #define DP_VS_SVC_F_SIP_HASH IP_VS_SVC_F_SIP_HASH #define DP_VS_SVC_F_QID_HASH IP_VS_SVC_F_QID_HASH #define DP_VS_SVC_F_MATCH IP_VS_SVC_F_MATCH +#define DP_VS_SVC_F_DEST_CHECK IP_VS_SVC_F_DEST_CHECK /* virtual service */ struct dp_vs_service { diff --git a/src/config.mk b/src/config.mk index 0d9c47f06..78fb68ba4 100644 --- a/src/config.mk +++ b/src/config.mk @@ -35,6 +35,7 @@ CFLAGS += -D CONFIG_DPVS_LOG #CFLAGS += -D CONFIG_RECORD_BIG_LOOP #CFLAGS += -D CONFIG_DPVS_SAPOOL_DEBUG #CFLAGS += -D CONFIG_DPVS_IPVS_DEBUG +#CFLAGS += -D CONFIG_DPVS_SERVICE_DEBUG #CFLAGS += -D CONFIG_SYNPROXY_DEBUG #CFLAGS += -D CONFIG_TIMER_MEASURE #CFLAGS += -D CONFIG_TIMER_DEBUG diff --git a/src/ctrl.c b/src/ctrl.c index 1b89a69ed..b140f10de 100644 --- a/src/ctrl.c +++ b/src/ctrl.c @@ -378,7 +378,7 @@ struct dpvs_msg* msg_make(msgid_t type, uint32_t seq, msg->mode = mode; msg->cid = cid; msg->len = len; - if (len) + if (len && data) rte_memcpy(msg->data, data, len); msg->reply.data = NULL; msg->reply.len = 0; diff --git a/src/ipvs/ip_vs_conn.c b/src/ipvs/ip_vs_conn.c index 131024db5..b94cb6855 100644 --- a/src/ipvs/ip_vs_conn.c +++ b/src/ipvs/ip_vs_conn.c @@ -1412,17 +1412,21 @@ static int __lcore_conn_table_dump(const struct list_head *cplist) } sockopt_fill_conn_entry(conn, &cparr->array[cparr->tail++]); if (cparr->tail >= MAX_CTRL_CONN_GET_ENTRIES) { +#ifdef CONFIG_DPVS_IPVS_STATS_DEBUG RTE_LOG(DEBUG, IPVS, "%s: adding %d elems to conn_to_dump list -- " "%p:%d-%d\n", __func__, cparr->tail - cparr->head, cparr, cparr->head, cparr->tail); +#endif list_add_tail(&cparr->ca_list, &conn_to_dump); } } } if (cparr && cparr->tail < MAX_CTRL_CONN_GET_ENTRIES) { +#ifdef CONFIG_DPVS_IPVS_STATS_DEBUG RTE_LOG(DEBUG, IPVS, "%s: adding %d elems to conn_to_dump list -- " "%p:%d-%d\n", __func__, cparr->tail - cparr->head, cparr, cparr->head, cparr->tail); +#endif list_add_tail(&cparr->ca_list, &conn_to_dump); } return EDPVS_OK; @@ -1438,9 +1442,11 @@ static int sockopt_conn_get_all(const struct ip_vs_conn_req *conn_req, again: list_for_each_entry_safe(larr, next_larr, &conn_to_dump, ca_list) { +#ifdef CONFIG_DPVS_IPVS_STATS_DEBUG RTE_LOG(DEBUG, IPVS, "%s: printing conn_to_dump list(len=%d) --" "%p:%d-%d\n", __func__, list_elems(&conn_to_dump), larr, larr->head, larr->tail); +#endif n = larr->tail - larr->head; assert(n > 0); if (n > MAX_CTRL_CONN_GET_ENTRIES - got) { diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 40bd384e4..a57756551 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -26,6 +26,31 @@ #include "ipvs/conn.h" #include "ctrl.h" +#define DEST_DOWN_NOTICE_DEFAULT 3 +#define DEST_UP_NOTICE_DEFAULT 3 +#define DEST_DOWN_WAIT_DURATION 3 // 3s +#define DEST_INHIBIT_DURATION_MIN 5 // 5s +#define DEST_INHIBIT_DURATION_MAX 3600 // 1h + +enum { + dest_notification_down = 1, + dest_notification_up, + dest_notification_close, + dest_notification_open, +}; + +struct dest_notification { + union inet_addr vaddr; + union inet_addr daddr; + uint16_t af; + uint16_t svc_af; + uint16_t proto; + uint16_t vport; + uint16_t dport; + uint16_t weight; + uint16_t notification; +}; + /* * Trash for destinations */ @@ -53,9 +78,7 @@ static void __dp_vs_dest_update(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest) { int conn_flags; - uint8_t num_lcores; - netif_get_slave_lcores(&num_lcores, NULL); rte_atomic16_set(&dest->weight, udest->weight); conn_flags = udest->conn_flags | DPVS_CONN_F_INACTIVE; rte_atomic16_set(&dest->conn_flags, conn_flags); @@ -64,16 +87,16 @@ static void __dp_vs_dest_update(struct dp_vs_service *svc, if (udest->max_conn == 0 || udest->max_conn > dest->max_conn) dest->flags &= ~DPVS_DEST_F_OVERLOAD; - if (rte_lcore_id() != rte_get_main_lcore()) { - dest->max_conn = udest->max_conn / num_lcores; - dest->min_conn = udest->min_conn / num_lcores; + if (rte_lcore_id() != g_master_lcore_id) { + dest->max_conn = udest->max_conn / g_slave_lcore_num; + dest->min_conn = udest->min_conn / g_slave_lcore_num; } else { /* Ensure that the sum of rs's max_conn in all lcores is equal to the configured max_conn, to prevent the operation of modifying rs from keepalived when reloading. */ - dest->max_conn = udest->max_conn % num_lcores; - dest->min_conn = udest->min_conn % num_lcores; + dest->max_conn = udest->max_conn % g_slave_lcore_num; + dest->min_conn = udest->min_conn % g_slave_lcore_num; } } @@ -224,6 +247,8 @@ void dp_vs_dest_put(struct dp_vs_dest *dest) return; if (rte_atomic32_dec_and_test(&dest->refcnt)) { + if (rte_lcore_id() == g_master_lcore_id) + dpvs_timer_cancel(&dest->dfc.master.timer, true); dp_vs_service_unbind(dest); rte_free(dest); } @@ -322,6 +347,297 @@ int dp_vs_dest_get_entries(const struct dp_vs_service *svc, return ret; } +static int dest_msg_seq(void) { + static uint32_t seq = 0; + return seq++; +} + +static void dest_inhibit_logging(const struct dp_vs_dest *dest, const char *msg) +{ + char str_vaddr[64], str_daddr[64]; + lcoreid_t cid = rte_lcore_id(); + + if (cid == g_master_lcore_id) { + RTE_LOG(INFO, SERVICE, "[cid %02d, %s, svc %s:%d, rs %s:%d, weight %d, inhibited %s," + " down_notice_recvd %d, inhibit_duration %ds, origin_weight %d] %s\n", + cid, + dest->proto == IPPROTO_TCP ? "tcp" : "udp", + inet_ntop(dest->svc->af, &dest->svc->addr, str_vaddr, sizeof(str_vaddr)) ? str_vaddr : "::", + ntohs(dest->svc->port), + inet_ntop(dest->af, &dest->addr, str_daddr, sizeof(str_daddr)) ? str_daddr : "::", + ntohs(dest->port), + rte_atomic16_read(&dest->weight), + dp_vs_dest_is_inhibited(dest) ? "yes" : "no", + dest->dfc.master.down_notice_recvd, + dest->dfc.master.inhibit_duration, + dest->dfc.master.origin_weight, + msg ?: "" + ); + } else { + RTE_LOG(DEBUG, SERVICE, "[cid %02d, %s, svc %s:%d, rs %s:%d, weight %d, inhibited %s, warm_up_count %d] %s\n", + cid, + dest->proto == IPPROTO_TCP ? "tcp" : "udp", + inet_ntop(dest->svc->af, &dest->svc->addr, str_vaddr, sizeof(str_vaddr)) ? str_vaddr : "::", + ntohs(dest->svc->port), + inet_ntop(dest->af, &dest->addr, str_daddr, sizeof(str_daddr)) ? str_daddr : "::", + ntohs(dest->port), + rte_atomic16_read(&dest->weight), + dp_vs_dest_is_inhibited(dest) ? "yes" : "no", + dest->dfc.slave.warm_up_count, + msg ?: "" + ); + } +} + +static inline void dest_notification_fill(const struct dp_vs_dest *dest, struct dest_notification *notice) +{ + notice->vaddr = dest->svc->addr; + notice->daddr = dest->addr; + notice->af = dest->af; + notice->svc_af = dest->svc->af; + notice->proto = dest->proto; + notice->vport = dest->svc->port; + notice->dport = dest->port; + notice->weight = rte_atomic16_read(&dest->weight); +} + +static struct dp_vs_dest *get_dest_from_notification(const struct dest_notification *notice) +{ + struct dp_vs_service *svc; + + svc = dp_vs_service_lookup(notice->svc_af, notice->proto, ¬ice->vaddr, notice->vport, + 0, NULL, NULL, NULL, rte_lcore_id()); + if (!svc) + return NULL; + return dp_vs_dest_lookup(notice->af, svc, ¬ice->daddr, notice->dport); +} + +static int dest_down_wait_timeout(void *arg) +{ + struct dp_vs_dest *dest; + + dest = (struct dp_vs_dest *)arg; + + // This should never happen, just in case! + dp_vs_dest_clear_inhibited(dest); + if (dest->dfc.master.origin_weight > 0 && rte_atomic16_read(&dest->weight) == 0) + rte_atomic16_set(&dest->weight, dest->dfc.master.origin_weight); + dest->dfc.master.origin_weight = 0; + + dest->dfc.master.down_notice_recvd = 0; + return EDPVS_OK; +} + +static int dest_inhibit_timeout(void *arg) +{ + int err; + struct dp_vs_dest *dest; + struct dpvs_msg *msg; + struct dest_notification *notice; + + dest = (struct dp_vs_dest *)arg; + msg = msg_make(MSG_TYPE_DEST_CHECK_NOTIFY_SLAVES, dest_msg_seq(), + DPVS_MSG_MULTICAST, rte_lcore_id(), sizeof(*notice), NULL); + if (unlikely(msg == NULL)) + return EDPVS_NOMEM; + notice = (struct dest_notification *)msg->data; + dest_notification_fill(dest, notice); + notice->weight = dest->dfc.master.origin_weight; + notice->notification = dest_notification_open; + err = multicast_msg_send(msg, DPVS_MSG_F_ASYNC, NULL); + if (err != EDPVS_OK) { + msg_destroy(&msg); + return err; + } + msg_destroy(&msg); + + dest_inhibit_logging(dest, "notify slaves UP"); + dp_vs_dest_clear_inhibited(dest); + rte_atomic16_set(&dest->weight, dest->dfc.master.origin_weight); + dest->dfc.master.origin_weight = 0; + dest->dfc.master.down_notice_recvd = 0; + + return EDPVS_OK; +} + +static int msg_cb_notify_master(struct dpvs_msg *msg) +{ + int err; + struct dp_vs_dest *dest; + struct dest_notification *notice, *notice_sent; + struct timeval delay; + struct dpvs_msg *msg_sent; + + notice = (struct dest_notification *)msg->data; + if (unlikely(notice->notification != dest_notification_down && + notice->notification != dest_notification_up)) { + RTE_LOG(WARNING, SERVICE,"%s:invalid notification %d\n", __func__, notice->notification); + return EDPVS_INVAL; + } + dest = get_dest_from_notification(notice); + if (!dest) + return EDPVS_NOTEXIST; + + if (notice->notification == dest_notification_down) { + if (dp_vs_dest_is_inhibited(dest) || rte_atomic16_read(&dest->weight) == 0) { + return EDPVS_OK; + } + dest->dfc.master.down_notice_recvd++; + + // start down-wait-timer on the first DOWN notice + if (dest->dfc.master.down_notice_recvd == 1 && DEST_DOWN_NOTICE_DEFAULT > 1) { + delay.tv_sec = DEST_DOWN_WAIT_DURATION - 1; + delay.tv_usec = 500000; + dpvs_time_rand_delay(&delay, 1000000); + err = dpvs_timer_sched(&dest->dfc.master.timer, &delay, dest_down_wait_timeout, (void *)dest, true); + if (err != EDPVS_OK) { + // FIXME: reschedule time without changing dfc.master.down_notice_recvd + dest->dfc.master.down_notice_recvd--; + return err; + } + return EDPVS_OK; + } + if (dest->dfc.master.down_notice_recvd < DEST_DOWN_NOTICE_DEFAULT) + return EDPVS_OK; + + // send CLOSE notice to all slaves, remove the dest from service, start rs-inhibit-timer + err = dpvs_timer_cancel(&dest->dfc.master.timer, true); + if (unlikely(err != EDPVS_OK)) + return err; + dp_vs_dest_set_inhibited(dest); + if (dest->dfc.master.inhibit_duration > DEST_INHIBIT_DURATION_MAX) + dest->dfc.master.inhibit_duration = DEST_INHIBIT_DURATION_MAX; + if (dest->dfc.master.inhibit_duration < DEST_INHIBIT_DURATION_MIN) + dest->dfc.master.inhibit_duration = DEST_INHIBIT_DURATION_MIN; + delay.tv_sec = dest->dfc.master.inhibit_duration - 1; + delay.tv_usec = 500000; + dpvs_time_rand_delay(&delay, 1000000); + err = dpvs_timer_sched(&dest->dfc.master.timer, &delay, dest_inhibit_timeout, (void *)dest, true); + if (err != EDPVS_OK) { + dp_vs_dest_clear_inhibited(dest); + return err; + } + msg_sent = msg_make(MSG_TYPE_DEST_CHECK_NOTIFY_SLAVES, dest_msg_seq(), + DPVS_MSG_MULTICAST, rte_lcore_id(), sizeof(*notice), notice); + if (unlikely(msg_sent == NULL)) { + dpvs_timer_cancel(&dest->dfc.master.timer, true); + dp_vs_dest_clear_inhibited(dest); + return EDPVS_NOMEM; + } + notice_sent = (struct dest_notification *)msg_sent->data; + notice_sent->notification = dest_notification_close; + err = multicast_msg_send(msg_sent, DPVS_MSG_F_ASYNC, NULL); + if (err != EDPVS_OK) { + dpvs_timer_cancel(&dest->dfc.master.timer, true); + dp_vs_dest_clear_inhibited(dest); + msg_destroy(&msg_sent); + return err; + } + msg_destroy(&msg_sent); + + dest_inhibit_logging(dest, "notify slaves DOWN"); + if (dest->dfc.master.inhibit_duration < DEST_INHIBIT_DURATION_MAX) + dest->dfc.master.inhibit_duration <<= 1; + dest->dfc.master.origin_weight = rte_atomic16_read(&dest->weight); + rte_atomic16_clear(&dest->weight); + } else { // dest_notification_up + dest->dfc.master.inhibit_duration >>= 1; + if (dest->dfc.master.inhibit_duration < DEST_INHIBIT_DURATION_MIN) + dest->dfc.master.inhibit_duration = DEST_INHIBIT_DURATION_MIN; + } + return EDPVS_OK; +} + +static int msg_cb_notify_slaves(struct dpvs_msg *msg) +{ + struct dp_vs_dest *dest; + struct dest_notification *notice; + + notice = (struct dest_notification *)msg->data; + if (unlikely(notice->notification != dest_notification_close && + notice->notification != dest_notification_open)) { + RTE_LOG(WARNING, SERVICE,"%s:invalid notification %d\n", __func__, notice->notification); + return EDPVS_INVAL; + } + dest = get_dest_from_notification(notice); + if (!dest) + return EDPVS_NOTEXIST; + + if (notice->notification == dest_notification_close) { + dest->dfc.slave.origin_weight = rte_atomic16_read(&dest->weight); + rte_atomic16_clear(&dest->weight); + dp_vs_dest_set_inhibited(dest); + } else { // dest_notification_open + rte_atomic16_set(&dest->weight, dest->dfc.slave.origin_weight); + dp_vs_dest_clear_inhibited(dest); + dest->dfc.slave.warm_up_count = DEST_UP_NOTICE_DEFAULT; + dest->dfc.slave.origin_weight = 0; + } + return EDPVS_OK; +} + +int dp_vs_dest_detected_alive(struct dp_vs_dest *dest) +{ + int err; + struct dpvs_msg *msg; + struct dest_notification *notice; + + if (!(dest->svc->flags & DP_VS_SVC_F_DEST_CHECK)) + return EDPVS_DISABLED; + + if (likely(dest->dfc.slave.warm_up_count == 0)) + return EDPVS_OK; + + msg = msg_make(MSG_TYPE_DEST_CHECK_NOTIFY_MASTER, dest_msg_seq(), + DPVS_MSG_UNICAST, rte_lcore_id(), sizeof(*notice), NULL); + if (unlikely(msg == NULL)) + return EDPVS_NOMEM; + notice = (struct dest_notification *)msg->data; + dest_notification_fill(dest, notice); + notice->notification = dest_notification_up; + + err = msg_send(msg, g_master_lcore_id, DPVS_MSG_F_ASYNC, NULL); + if (err != EDPVS_OK) { + msg_destroy(&msg); + return err; + } + msg_destroy(&msg); + + dest_inhibit_logging(dest, "detect dest UP"); + dest->dfc.slave.warm_up_count--; + return EDPVS_OK; +} + +int dp_vs_dest_detected_dead(struct dp_vs_dest *dest) +{ + int err; + struct dpvs_msg *msg; + struct dest_notification *notice; + + if (!(dest->svc->flags & DP_VS_SVC_F_DEST_CHECK)) + return EDPVS_DISABLED; + + if (dp_vs_dest_is_inhibited(dest) || rte_atomic16_read(&dest->weight) == 0) + return EDPVS_OK; + + msg = msg_make(MSG_TYPE_DEST_CHECK_NOTIFY_MASTER, dest_msg_seq(), + DPVS_MSG_UNICAST, rte_lcore_id(), sizeof(*notice), 0); + if (unlikely(msg == NULL)) + return EDPVS_NOMEM; + notice = (struct dest_notification *)msg->data; + dest_notification_fill(dest, notice); + notice->notification = dest_notification_down; + + err = msg_send(msg, g_master_lcore_id, DPVS_MSG_F_ASYNC, NULL); + if (err != EDPVS_OK) { + msg_destroy(&msg); + return err; + } + msg_destroy(&msg); + dest_inhibit_logging(dest, "detect dest DOWN"); + return EDPVS_OK; +} + #ifdef CONFIG_DPVS_AGENT static int dp_vs_dest_get_details(const struct dp_vs_service *svc, struct dp_vs_dest_front *uptr) @@ -360,11 +676,6 @@ static int dp_vs_dest_get_details(const struct dp_vs_service *svc, return ret; } -static int dest_msg_seq(void) { - static uint32_t seq = 0; - return seq++; -} - static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len) { struct dp_vs_dest_front *insvc; @@ -612,11 +923,46 @@ static int dp_vs_dests_get_uc_cb(struct dpvs_msg *msg) return EDPVS_OK; } +struct dpvs_sockopts sockopts_dest = { + .version = SOCKOPT_VERSION, + .set_opt_min = DPVSAGENT_VS_ADD_DESTS, + .set_opt_max = DPVSAGENT_VS_DEL_DESTS, + .set = dp_vs_dest_set, + .get_opt_min = DPVSAGENT_VS_GET_DESTS, + .get_opt_max = DPVSAGENT_VS_GET_DESTS, + .get = dp_vs_dest_get, +}; + +#endif /* CONFIG_DPVS_AGENT */ + static int dest_unregister_msg_cb(void) { - struct dpvs_msg_type msg_type; int err, rterr = EDPVS_OK; + struct dpvs_msg_type msg_type; + memset(&msg_type, 0, sizeof(msg_type)); + msg_type.type = MSG_TYPE_DEST_CHECK_NOTIFY_MASTER; + msg_type.mode = DPVS_MSG_UNICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = g_master_lcore_id; + msg_type.unicast_msg_cb = msg_cb_notify_master; + if ((err = msg_type_unregister(&msg_type)) != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to unregister MSG_TYPE_DEST_CHECK_NOTIFY_MASTER -- %s\n", + __func__, dpvs_strerror(err)); + } + + memset(&msg_type, 0, sizeof(msg_type)); + msg_type.type = MSG_TYPE_DEST_CHECK_NOTIFY_SLAVES; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.unicast_msg_cb = msg_cb_notify_slaves; + if ((err = msg_type_mc_unregister(&msg_type)) != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to unregister MSG_TYPE_DEST_CHECK_NOTIFY_SLAVES -- %s\n", + __func__, dpvs_strerror(err)); + return err; + } + +#ifdef CONFIG_DPVS_AGENT memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_ADD_DESTS; msg_type.mode = DPVS_MSG_MULTICAST; @@ -625,7 +971,8 @@ static int dest_unregister_msg_cb(void) msg_type.unicast_msg_cb = adddest_msg_cb; err = msg_type_mc_unregister(&msg_type); if (err != EDPVS_OK) { - RTE_LOG(ERR, SERVICE, "%s: fail to unregister msg.\n", __func__); + RTE_LOG(ERR, SERVICE, "%s: fail to unregister MSG_TYPE_AGENT_ADD_DESTS -- %s\n", + __func__, dpvs_strerror(err)); rterr = err; } @@ -637,7 +984,8 @@ static int dest_unregister_msg_cb(void) msg_type.unicast_msg_cb = deldest_msg_cb; err = msg_type_mc_unregister(&msg_type); if (err != EDPVS_OK) { - RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + RTE_LOG(ERR, SERVICE, "%s: fail to register MSG_TYPE_AGENT_DEL_DESTS -- %s\n", + __func__, dpvs_strerror(err)); if (rterr == EDPVS_OK) rterr = err; } @@ -663,32 +1011,44 @@ static int dest_unregister_msg_cb(void) msg_type.unicast_msg_cb = dp_vs_dests_get_uc_cb; err = msg_type_mc_unregister(&msg_type); if (err != EDPVS_OK) { - RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + RTE_LOG(ERR, SERVICE, "%s: fail to register MSG_TYPE_AGENT_GET_DESTS -- %s\n", + __func__, dpvs_strerror(err)); if (rterr == EDPVS_OK) rterr = err; } +#endif return rterr; } -struct dpvs_sockopts sockopts_dest = { - .version = SOCKOPT_VERSION, - .set_opt_min = DPVSAGENT_VS_ADD_DESTS, - .set_opt_max = DPVSAGENT_VS_DEL_DESTS, - .set = dp_vs_dest_set, - .get_opt_min = DPVSAGENT_VS_GET_DESTS, - .get_opt_max = DPVSAGENT_VS_GET_DESTS, - .get = dp_vs_dest_get, -}; +static int dest_register_msg_cb(void) { + int err; + struct dpvs_msg_type msg_type; -#endif /* CONFIG_DPVS_AGENT */ + memset(&msg_type, 0, sizeof(msg_type)); + msg_type.type = MSG_TYPE_DEST_CHECK_NOTIFY_MASTER; + msg_type.mode = DPVS_MSG_UNICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.cid = g_master_lcore_id; + msg_type.unicast_msg_cb = msg_cb_notify_master; + if ((err = msg_type_register(&msg_type)) != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register MSG_TYPE_DEST_CHECK_NOTIFY_MASTER -- %s\n", + __func__, dpvs_strerror(err)); + return err; + } -int dp_vs_dest_init(void) -{ - int err = EDPVS_OK; -#ifdef CONFIG_DPVS_AGENT - struct dpvs_msg_type msg_type; + memset(&msg_type, 0, sizeof(msg_type)); + msg_type.type = MSG_TYPE_DEST_CHECK_NOTIFY_SLAVES; + msg_type.mode = DPVS_MSG_MULTICAST; + msg_type.prio = MSG_PRIO_NORM; + msg_type.unicast_msg_cb = msg_cb_notify_slaves; + if ((err = msg_type_mc_register(&msg_type)) != EDPVS_OK) { + RTE_LOG(ERR, SERVICE, "%s: fail to register MSG_TYPE_DEST_CHECK_NOTIFY_SLAVES -- %s\n", + __func__, dpvs_strerror(err)); + return err; + } +#ifdef CONFIG_DPVS_AGENT memset(&msg_type, 0, sizeof(struct dpvs_msg_type)); msg_type.type = MSG_TYPE_AGENT_ADD_DESTS; msg_type.mode = DPVS_MSG_MULTICAST; @@ -697,7 +1057,8 @@ int dp_vs_dest_init(void) msg_type.unicast_msg_cb = adddest_msg_cb; err = msg_type_mc_register(&msg_type); if (err != EDPVS_OK) { - RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + RTE_LOG(ERR, SERVICE, "%s: fail to register MSG_TYPE_AGENT_ADD_DESTS -- %s\n", + __func__, dpvs_strerror(err)); return err; } @@ -709,7 +1070,8 @@ int dp_vs_dest_init(void) msg_type.unicast_msg_cb = deldest_msg_cb; err = msg_type_mc_register(&msg_type); if (err != EDPVS_OK) { - RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + RTE_LOG(ERR, SERVICE, "%s: fail to register MSG_TYPE_AGENT_DEL_DESTS -- %s\n", + __func__, dpvs_strerror(err)); return err; } @@ -733,7 +1095,8 @@ int dp_vs_dest_init(void) msg_type.unicast_msg_cb = dp_vs_dests_get_uc_cb; err = msg_type_mc_register(&msg_type); if (err != EDPVS_OK) { - RTE_LOG(ERR, SERVICE, "%s: fail to register msg.\n", __func__); + RTE_LOG(ERR, SERVICE, "%s: fail to register MSG_TYPE_AGENT_GET_DESTS -- %s\n", + __func__, dpvs_strerror(err)); return err; } @@ -742,15 +1105,20 @@ int dp_vs_dest_init(void) return err; } #endif /* CONFIG_DPVS_AGENT */ - return err; + return EDPVS_OK; +}; + +int dp_vs_dest_init(void) +{ + dest_register_msg_cb(); + return EDPVS_OK; } int dp_vs_dest_term(void) { -#ifdef CONFIG_DPVS_AGENT dest_unregister_msg_cb(); - return sockopt_unregister(&sockopts_dest); -#else - return EDPVS_OK; +#ifdef CONFIG_DPVS_AGENT + sockopt_unregister(&sockopts_dest); #endif + return EDPVS_OK; } diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index cbb7cb2fe..4d1d71f67 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -912,6 +912,11 @@ static int tcp_state_trans(struct dp_vs_proto *proto, struct dp_vs_conn *conn, dp_vs_conn_set_timeout(conn, proto); + if (new_state == DPVS_TCP_S_CLOSE && conn->old_state == DPVS_TCP_S_SYN_RECV) + dp_vs_dest_detected_dead(conn->dest); // connection reset by dest + else if (new_state == DPVS_TCP_S_ESTABLISHED) + dp_vs_dest_detected_alive(conn->dest); + if (dest) { if (!(conn->flags & DPVS_CONN_F_INACTIVE) && (new_state != DPVS_TCP_S_ESTABLISHED)) { @@ -1157,6 +1162,10 @@ static int tcp_conn_expire(struct dp_vs_proto *proto, RTE_LOG(WARNING, IPVS, "%s: fail RST Client.\n", __func__); } + /* the backend dest went down silently */ + if (DPVS_TCP_S_SYN_RECV == conn->state || DPVS_TCP_S_SYN_SENT == conn->state) + dp_vs_dest_detected_dead(conn->dest); + return EDPVS_OK; } diff --git a/src/ipvs/ip_vs_synproxy.c b/src/ipvs/ip_vs_synproxy.c index 561fe2c3a..339aaca2d 100644 --- a/src/ipvs/ip_vs_synproxy.c +++ b/src/ipvs/ip_vs_synproxy.c @@ -1417,6 +1417,7 @@ int dp_vs_synproxy_synack_rcv(struct rte_mbuf *mbuf, struct dp_vs_conn *cp, rte_atomic32_inc(&dest->actconns); rte_atomic32_dec(&dest->inactconns); cp->flags &= ~DPVS_CONN_F_INACTIVE; + dp_vs_dest_detected_alive(dest); } /* Save tcp sequence for fullnat/nat, inside to outside */ @@ -1484,6 +1485,7 @@ int dp_vs_synproxy_synack_rcv(struct rte_mbuf *mbuf, struct dp_vs_conn *cp, (cp->state == DPVS_TCP_S_SYN_SENT)) { RTE_LOG(DEBUG, IPVS, "%s: get rst from rs, seq = %u ack_seq = %u\n", __func__, ntohl(th->seq), ntohl(th->ack_seq)); + dp_vs_dest_detected_dead(dest); /* Count the delta of seq */ cp->syn_proxy_seq.delta = ntohl(cp->syn_proxy_seq.isn) - ntohl(th->seq); diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index 7df33aa3c..bb7b4be42 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -211,6 +211,9 @@ static const char* optnames[] = { "whtlst-address", }; +static const char* optnames_ext[] = { + "inhibit-on-fail", +}; /* * Table of legal combinations of commands and options. * Key: @@ -331,6 +334,7 @@ enum { TAG_SOCKPAIR, TAG_CPU, TAG_CONN_EXPIRE_QUIESCENT, + TAG_CONN_INHIBIT_ON_FAIL, }; /* various parsing helpers & parsing functions */ @@ -356,6 +360,7 @@ static int parse_match_snat(const char *buf, dpvs_service_compat_t*); static void generic_opt_check(int command, unsigned int options); static void set_command(int *cmd, const int newcmd); static void set_option(unsigned int *options, unsigned int option); +static void set_option_ext(unsigned int *options, unsigned int option); static void tryhelp_exit(const char *program, const int exit_status); static void usage_exit(const char *program, const int exit_status); @@ -411,9 +416,9 @@ int main(int argc, char **argv) } - static int +static int parse_options(int argc, char **argv, struct ipvs_command_entry *ce, - unsigned int *options, unsigned int *format) + unsigned int *options, unsigned int *options_ext, unsigned int *format) { int c, parse; poptContext context; @@ -506,6 +511,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, { "hash-target", 'Y', POPT_ARG_STRING, &optarg, 'Y', NULL, NULL }, { "cpu", '\0', POPT_ARG_STRING, &optarg, TAG_CPU, NULL, NULL }, { "expire-quiescent", '\0', POPT_ARG_NONE, NULL, TAG_CONN_EXPIRE_QUIESCENT, NULL, NULL }, + { "inhibit-on-fail", '\0', POPT_ARG_STRING, &optarg, TAG_CONN_INHIBIT_ON_FAIL, NULL, NULL }, { NULL, 0, 0, NULL, 0, NULL, NULL } }; @@ -906,6 +912,17 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, ce->dpvs_svc.flags = ce->dpvs_svc.flags | IP_VS_CONN_F_EXPIRE_QUIESCENT; break; } + case TAG_CONN_INHIBIT_ON_FAIL: + { + set_option_ext(options_ext, OPT_EXT_INHIBIT_ON_FAIL); + if(!memcmp(optarg , "enable" , strlen("enable"))) { + ce->dpvs_svc.flags = ce->dpvs_svc.flags | IP_VS_SVC_F_DEST_CHECK; + } else if(!memcmp(optarg , "disable" , strlen("disable"))) { + ce->dpvs_svc.flags = ce->dpvs_svc.flags & (~IP_VS_SVC_F_DEST_CHECK); + } else + fail(2 , "inhibit-on-fail switch must be enable or disable\n"); + break; + } default: fail(2, "invalid option `%s'", poptBadOption(context, POPT_BADOPTION_NOALIAS)); @@ -969,7 +986,7 @@ static int restore_table(int argc, char **argv, int reading_stdin) static int process_options(int argc, char **argv, int reading_stdin) { - unsigned int options = OPT_NONE; + unsigned int options = OPT_NONE, options_ext = OPT_EXT_NONE; unsigned int format = FMT_NONE; int result = 0; const struct inet_addr_range zero_range = {}; @@ -985,7 +1002,7 @@ static int process_options(int argc, char **argv, int reading_stdin) /* Set the default cpu be master */ ce.index = 0; - if (parse_options(argc, argv, &ce, &options, &format)) + if (parse_options(argc, argv, &ce, &options, &options_ext, &format)) return -1; generic_opt_check(ce.cmd, options); @@ -1066,7 +1083,7 @@ static int process_options(int argc, char **argv, int reading_stdin) break; case CMD_EDIT: - result = dpvs_update_service_by_options(&ce.dpvs_svc, options); + result = dpvs_update_service_by_options(&ce.dpvs_svc, options, options_ext); break; case CMD_DEL: @@ -1239,7 +1256,7 @@ static int parse_netmask(char *buf, u_int32_t *addr) * SERVICE_ADDR: addr set * SERVICE_PORT: port set */ - static int +static int parse_service(char *buf, dpvs_service_compat_t *dpvs_svc) { char *portp = NULL; @@ -1303,7 +1320,7 @@ parse_service(char *buf, dpvs_service_compat_t *dpvs_svc) * SIP,TIP := dotted-decimal ip address or square-blacketed ip6 address * SPORT,TPORT := range(0, 65535) */ - static int +static int parse_sockpair(char *buf, ipvs_sockpair_t *sockpair) { char *pos = buf, *end; @@ -1472,7 +1489,7 @@ static int parse_match_snat(const char *buf, dpvs_service_compat_t *dpvs_svc) return 0; } - static void +static void generic_opt_check(int command, unsigned int options) { int i, j; @@ -1506,7 +1523,7 @@ generic_opt_check(int command, unsigned int options) } } - static inline const char * +static inline const char * opt2name(int option) { const char **ptr; @@ -1515,7 +1532,7 @@ opt2name(int option) return *ptr; } - static void +static void set_command(int *cmd, const int newcmd) { if (*cmd != CMD_NONE) @@ -1523,7 +1540,7 @@ set_command(int *cmd, const int newcmd) *cmd = newcmd; } - static void +static void set_option(unsigned int *options, unsigned int option) { if (*options & option) @@ -1531,6 +1548,22 @@ set_option(unsigned int *options, unsigned int option) *options |= option; } +static inline const char * +opt2name_ext(int option) +{ + const char **ptr; + for (ptr = optnames_ext; option > 1; option >>= 1, ptr++); + + return *ptr; +} + +static void +set_option_ext(unsigned int *options, unsigned int option) +{ + if (*options & option) + fail(2, "multiple '%s' options specified", opt2name_ext(option)); + *options |= option; +} static void tryhelp_exit(const char *program, const int exit_status) { @@ -1646,7 +1679,8 @@ static void usage_exit(const char *program, const int exit_status) " --match -H MATCH select service by MATCH 'af,proto,srange,drange,iif,oif', af should be defined if no range defined\n" " --hash-target -Y hashtag choose target for conhash (support sip or qid for quic)\n" " --cpu cpu_index specifi cpu (lcore) index to show, 0 for master worker\n" - " --expire-quiescent expire the quiescent connections timely whose realserver went down\n", + " --expire-quiescent expire the quiescent connections timely whose realserver went down\n" + " --inhibit-on-fail enable passive health check, inhibit failed realservers scheduling\n", DEF_SCHED); exit(exit_status); @@ -2082,6 +2116,8 @@ print_service_entry(dpvs_service_compat_t *se, unsigned int format) printf(" conn_timeout %u", se->conn_timeout); if (se->flags & IP_VS_CONN_F_EXPIRE_QUIESCENT) printf(" expire-quiescent"); + if (se->flags & IP_VS_SVC_F_DEST_CHECK) + printf(" inhibit-on-fail"); } printf("\n"); @@ -2616,7 +2652,7 @@ static char * port_to_anyname(unsigned short port, unsigned short proto) } - static char * +static char * addrport_to_anyname(int af, const void *addr, unsigned short port, unsigned short proto, unsigned int format) { diff --git a/tools/keepalived/keepalived/check/libipvs.c b/tools/keepalived/keepalived/check/libipvs.c index ee65fa547..1a35c4d96 100644 --- a/tools/keepalived/keepalived/check/libipvs.c +++ b/tools/keepalived/keepalived/check/libipvs.c @@ -108,7 +108,7 @@ int dpvs_update_service(dpvs_service_compat_t *svc) } -int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int options) +int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int options, unsigned int options_ext) { dpvs_service_compat_t entry; @@ -168,6 +168,14 @@ int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int opti } } + if (options_ext & OPT_EXT_INHIBIT_ON_FAIL) { + if (svc->flags & IP_VS_SVC_F_DEST_CHECK) { + entry.flags |= IP_VS_SVC_F_DEST_CHECK; + } else { + entry.flags &= ~IP_VS_SVC_F_DEST_CHECK; + } + } + return dpvs_update_service(&entry); } diff --git a/tools/keepalived/keepalived/include/libipvs.h b/tools/keepalived/keepalived/include/libipvs.h index 056834e45..6b2db0fe4 100644 --- a/tools/keepalived/keepalived/include/libipvs.h +++ b/tools/keepalived/keepalived/include/libipvs.h @@ -46,6 +46,9 @@ #define OPT_WHTLST_ADDRESS 0x80000000 #define NUMBER_OF_OPT 33 +#define OPT_EXT_NONE 0x00000000 +#define OPT_EXT_INHIBIT_ON_FAIL 0x00000001 + #define MINIMUM_IPVS_VERSION_MAJOR 1 #define MINIMUM_IPVS_VERSION_MINOR 1 #define MINIMUM_IPVS_VERSION_PATCH 4 @@ -99,7 +102,7 @@ extern int dpvs_add_service(dpvs_service_compat_t *svc); extern int dpvs_update_service(dpvs_service_compat_t *svc); /* update a virtual service based on option */ -extern int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int options); +extern int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int options, unsigned int options_ext); /* delete a virtual service */ From 9b961103a1e5ed28e5daa36e19492e9f529ded6d Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 19 Apr 2023 11:37:50 +0800 Subject: [PATCH 023/105] ipvs: make backend passive health check configurable per-service Signed-off-by: ywc689 --- include/conf/dest.h | 1 - include/conf/service.h | 55 ++++++++++- include/ipvs/service.h | 2 +- src/ipvs/ip_vs_dest.c | 36 ++++--- src/ipvs/ip_vs_service.c | 5 + tools/ipvsadm/ipvsadm.c | 99 +++++++++++-------- tools/keepalived/keepalived/check/libipvs.c | 10 +- tools/keepalived/keepalived/include/libipvs.h | 7 +- 8 files changed, 137 insertions(+), 78 deletions(-) diff --git a/include/conf/dest.h b/include/conf/dest.h index 78ad6ff47..29a678c5a 100644 --- a/include/conf/dest.h +++ b/include/conf/dest.h @@ -18,7 +18,6 @@ #ifndef __DPVS_DEST_CONF_H__ #define __DPVS_DEST_CONF_H__ -#include "conf/service.h" #include "conf/match.h" #include "conf/conn.h" diff --git a/include/conf/service.h b/include/conf/service.h index 30fa02c7c..db77d4bf7 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -40,10 +40,27 @@ #define IP_VS_SVC_F_SIP_HASH 0x0100 /* sip hash target */ #define IP_VS_SVC_F_QID_HASH 0x0200 /* quic cid hash target */ #define IP_VS_SVC_F_MATCH 0x0400 /* snat match */ -#define IP_VS_SVC_F_DEST_CHECK 0x0800 /* inhibit rs on failure */ #define IP_VS_SVC_F_SCHED_SH_FALLBACK IP_VS_SVC_F_SCHED1 /* SH fallback */ #define IP_VS_SVC_F_SCHED_SH_PORT IP_VS_SVC_F_SCHED2 /* SH use port */ +#define MAX_ARG_LEN (sizeof(dpvs_service_compat_t) + sizeof(dpvs_dest_compat_t)) + +/* defaults for dest passive health check */ +#define DEST_DOWN_NOTICE_DEFAULT 1 +#define DEST_UP_NOTICE_DEFAULT 1 +#define DEST_DOWN_WAIT_DURATION 3 // 3s +#define DEST_INHIBIT_DURATION_MIN 5 // 5s +#define DEST_INHIBIT_DURATION_MAX 3600 // 1h + +struct dest_check_configs { + uint8_t enabled; + uint8_t dest_down_notice_num; // how many DOWNs detected in `dest_down_wait` before inhibiting the dest + uint8_t dest_up_notice_num; // how many notifications sent when UPs detected after inhibitation + uint8_t dest_down_wait; + uint16_t dest_inhibit_min; // the inhibitation duration range [dest_inhibit_min, dest_inhibit_max] + uint16_t dest_inhibit_max; +}; + typedef struct dp_vs_service_compat { /*base*/ int af; @@ -60,7 +77,7 @@ typedef struct dp_vs_service_compat { char sched_name[DP_VS_SCHEDNAME_MAXLEN]; /*dp_vs_service_user & dp_vs_service_entry*/ - struct dp_vs_match match; + struct dp_vs_match match; /*dp_vs_service_entry*/ unsigned int num_dests; @@ -68,7 +85,7 @@ typedef struct dp_vs_service_compat { lcoreid_t cid; lcoreid_t index; struct dp_vs_stats stats; - + struct dest_check_configs check_conf; } dpvs_service_compat_t; #define dp_vs_service_conf dp_vs_service_compat @@ -89,6 +106,36 @@ struct dp_vs_getinfo { unsigned int num_lcores; }; -#define MAX_ARG_LEN (sizeof(dpvs_service_compat_t) + sizeof(dpvs_dest_compat_t)) +static inline bool +dest_check_configs_sanity(struct dest_check_configs *conf) { + bool res = true; + if (conf->dest_down_notice_num < 1) { + conf->dest_down_notice_num = DEST_DOWN_NOTICE_DEFAULT; + res = false; + } + if (conf->dest_up_notice_num < 1) { + conf->dest_up_notice_num = DEST_UP_NOTICE_DEFAULT; + res = false; + } + if (conf->dest_down_wait < 1) { + conf->dest_down_wait = DEST_DOWN_WAIT_DURATION; + res = false; + } + if (conf->dest_inhibit_min < 1) { + conf->dest_inhibit_min = DEST_INHIBIT_DURATION_MIN; + res = false; + } + if (conf->dest_inhibit_max < 1) { + conf->dest_inhibit_max = DEST_INHIBIT_DURATION_MAX; + res = false; + } + if (conf->dest_inhibit_min > conf->dest_inhibit_max) { + conf->dest_inhibit_min = DEST_INHIBIT_DURATION_MIN; + conf->dest_inhibit_max = DEST_INHIBIT_DURATION_MAX; + res = false; + } + return res; +}; + #endif /* __DPVS_SVC_CONF_H__ */ diff --git a/include/ipvs/service.h b/include/ipvs/service.h index 336dbda6f..a643bb45c 100644 --- a/include/ipvs/service.h +++ b/include/ipvs/service.h @@ -43,7 +43,6 @@ #define DP_VS_SVC_F_SIP_HASH IP_VS_SVC_F_SIP_HASH #define DP_VS_SVC_F_QID_HASH IP_VS_SVC_F_QID_HASH #define DP_VS_SVC_F_MATCH IP_VS_SVC_F_MATCH -#define DP_VS_SVC_F_DEST_CHECK IP_VS_SVC_F_DEST_CHECK /* virtual service */ struct dp_vs_service { @@ -76,6 +75,7 @@ struct dp_vs_service { struct list_head dests; /* real services (dp_vs_dest{}) */ uint32_t num_dests; long weight; /* sum of servers weight */ + struct dest_check_configs check_conf; struct dp_vs_scheduler *scheduler; void *sched_data; diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index a57756551..3c046e424 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -26,12 +26,6 @@ #include "ipvs/conn.h" #include "ctrl.h" -#define DEST_DOWN_NOTICE_DEFAULT 3 -#define DEST_UP_NOTICE_DEFAULT 3 -#define DEST_DOWN_WAIT_DURATION 3 // 3s -#define DEST_INHIBIT_DURATION_MIN 5 // 5s -#define DEST_INHIBIT_DURATION_MAX 3600 // 1h - enum { dest_notification_down = 1, dest_notification_up, @@ -463,9 +457,10 @@ static int dest_inhibit_timeout(void *arg) static int msg_cb_notify_master(struct dpvs_msg *msg) { int err; + struct timeval delay; struct dp_vs_dest *dest; struct dest_notification *notice, *notice_sent; - struct timeval delay; + struct dest_check_configs *configs; struct dpvs_msg *msg_sent; notice = (struct dest_notification *)msg->data; @@ -477,6 +472,7 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) dest = get_dest_from_notification(notice); if (!dest) return EDPVS_NOTEXIST; + configs = &dest->svc->check_conf; if (notice->notification == dest_notification_down) { if (dp_vs_dest_is_inhibited(dest) || rte_atomic16_read(&dest->weight) == 0) { @@ -485,8 +481,8 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) dest->dfc.master.down_notice_recvd++; // start down-wait-timer on the first DOWN notice - if (dest->dfc.master.down_notice_recvd == 1 && DEST_DOWN_NOTICE_DEFAULT > 1) { - delay.tv_sec = DEST_DOWN_WAIT_DURATION - 1; + if (dest->dfc.master.down_notice_recvd == 1 && configs->dest_down_notice_num > 1) { + delay.tv_sec = configs->dest_down_wait - 1; delay.tv_usec = 500000; dpvs_time_rand_delay(&delay, 1000000); err = dpvs_timer_sched(&dest->dfc.master.timer, &delay, dest_down_wait_timeout, (void *)dest, true); @@ -497,7 +493,7 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) } return EDPVS_OK; } - if (dest->dfc.master.down_notice_recvd < DEST_DOWN_NOTICE_DEFAULT) + if (dest->dfc.master.down_notice_recvd < configs->dest_down_notice_num) return EDPVS_OK; // send CLOSE notice to all slaves, remove the dest from service, start rs-inhibit-timer @@ -505,10 +501,10 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) if (unlikely(err != EDPVS_OK)) return err; dp_vs_dest_set_inhibited(dest); - if (dest->dfc.master.inhibit_duration > DEST_INHIBIT_DURATION_MAX) - dest->dfc.master.inhibit_duration = DEST_INHIBIT_DURATION_MAX; - if (dest->dfc.master.inhibit_duration < DEST_INHIBIT_DURATION_MIN) - dest->dfc.master.inhibit_duration = DEST_INHIBIT_DURATION_MIN; + if (dest->dfc.master.inhibit_duration > configs->dest_inhibit_max) + dest->dfc.master.inhibit_duration = configs->dest_inhibit_max; + if (dest->dfc.master.inhibit_duration < configs->dest_inhibit_min) + dest->dfc.master.inhibit_duration = configs->dest_inhibit_min; delay.tv_sec = dest->dfc.master.inhibit_duration - 1; delay.tv_usec = 500000; dpvs_time_rand_delay(&delay, 1000000); @@ -542,8 +538,8 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) rte_atomic16_clear(&dest->weight); } else { // dest_notification_up dest->dfc.master.inhibit_duration >>= 1; - if (dest->dfc.master.inhibit_duration < DEST_INHIBIT_DURATION_MIN) - dest->dfc.master.inhibit_duration = DEST_INHIBIT_DURATION_MIN; + if (dest->dfc.master.inhibit_duration < configs->dest_inhibit_min) + dest->dfc.master.inhibit_duration = configs->dest_inhibit_min; } return EDPVS_OK; } @@ -552,6 +548,7 @@ static int msg_cb_notify_slaves(struct dpvs_msg *msg) { struct dp_vs_dest *dest; struct dest_notification *notice; + struct dest_check_configs *configs; notice = (struct dest_notification *)msg->data; if (unlikely(notice->notification != dest_notification_close && @@ -562,6 +559,7 @@ static int msg_cb_notify_slaves(struct dpvs_msg *msg) dest = get_dest_from_notification(notice); if (!dest) return EDPVS_NOTEXIST; + configs = &dest->svc->check_conf; if (notice->notification == dest_notification_close) { dest->dfc.slave.origin_weight = rte_atomic16_read(&dest->weight); @@ -570,7 +568,7 @@ static int msg_cb_notify_slaves(struct dpvs_msg *msg) } else { // dest_notification_open rte_atomic16_set(&dest->weight, dest->dfc.slave.origin_weight); dp_vs_dest_clear_inhibited(dest); - dest->dfc.slave.warm_up_count = DEST_UP_NOTICE_DEFAULT; + dest->dfc.slave.warm_up_count = configs->dest_up_notice_num; dest->dfc.slave.origin_weight = 0; } return EDPVS_OK; @@ -582,7 +580,7 @@ int dp_vs_dest_detected_alive(struct dp_vs_dest *dest) struct dpvs_msg *msg; struct dest_notification *notice; - if (!(dest->svc->flags & DP_VS_SVC_F_DEST_CHECK)) + if (!dest->svc->check_conf.enabled) return EDPVS_DISABLED; if (likely(dest->dfc.slave.warm_up_count == 0)) @@ -614,7 +612,7 @@ int dp_vs_dest_detected_dead(struct dp_vs_dest *dest) struct dpvs_msg *msg; struct dest_notification *notice; - if (!(dest->svc->flags & DP_VS_SVC_F_DEST_CHECK)) + if (!dest->svc->check_conf.enabled) return EDPVS_DISABLED; if (dp_vs_dest_is_inhibited(dest) || rte_atomic16_read(&dest->weight) == 0) diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index 5a9cb6cf4..f30d59f4f 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -498,6 +498,8 @@ static int dp_vs_service_add(struct dp_vs_service_conf *u, svc->laddr_curr = &svc->laddr_list; INIT_LIST_HEAD(&svc->dests); + svc->check_conf= u->check_conf; + dest_check_configs_sanity(&svc->check_conf); ret = dp_vs_bind_scheduler(svc, sched); if (ret) @@ -554,6 +556,8 @@ static int dp_vs_service_edit(struct dp_vs_service *svc, struct dp_vs_service_co svc->netmask = u->netmask; svc->bps = u->bps; svc->limit_proportion = u->limit_proportion; + svc->check_conf= u->check_conf; + dest_check_configs_sanity(&svc->check_conf); old_sched = svc->scheduler; if (sched != old_sched) { @@ -658,6 +662,7 @@ dp_vs_service_copy(struct dp_vs_service_entry *dst, struct dp_vs_service *src) dst->num_laddrs = src->num_laddrs; dst->cid = rte_lcore_id(); dst->index = g_lcore_id2index[dst->cid]; + dst->check_conf = src->check_conf; err = dp_vs_stats_add(&dst->stats, &src->stats); diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index bb7b4be42..3bd730bec 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -98,6 +98,7 @@ #include #include #include +#include #include #include #include @@ -211,9 +212,6 @@ static const char* optnames[] = { "whtlst-address", }; -static const char* optnames_ext[] = { - "inhibit-on-fail", -}; /* * Table of legal combinations of commands and options. * Key: @@ -334,7 +332,7 @@ enum { TAG_SOCKPAIR, TAG_CPU, TAG_CONN_EXPIRE_QUIESCENT, - TAG_CONN_INHIBIT_ON_FAIL, + TAG_DEST_CHECK, }; /* various parsing helpers & parsing functions */ @@ -360,7 +358,6 @@ static int parse_match_snat(const char *buf, dpvs_service_compat_t*); static void generic_opt_check(int command, unsigned int options); static void set_command(int *cmd, const int newcmd); static void set_option(unsigned int *options, unsigned int option); -static void set_option_ext(unsigned int *options, unsigned int option); static void tryhelp_exit(const char *program, const int exit_status); static void usage_exit(const char *program, const int exit_status); @@ -415,10 +412,46 @@ int main(int argc, char **argv) return result; } +static bool is_dest_check_conf_default(const struct dest_check_configs *conf) +{ + return conf->dest_down_notice_num == DEST_DOWN_NOTICE_DEFAULT && + conf->dest_up_notice_num == DEST_UP_NOTICE_DEFAULT && + conf->dest_down_wait == DEST_DOWN_WAIT_DURATION && + conf->dest_inhibit_min == DEST_INHIBIT_DURATION_MIN && + conf->dest_inhibit_max == DEST_INHIBIT_DURATION_MAX; +} + +static int parse_dest_check(const char *optarg, struct dest_check_configs *conf) +{ + memset(conf, 0, sizeof(*conf)); + if (!strcmp(optarg, "disable")) { + conf->enabled = 0; + } else if (!strcmp(optarg, "default")) { + conf->enabled = 1; + conf->dest_down_notice_num = DEST_DOWN_NOTICE_DEFAULT; + conf->dest_up_notice_num = DEST_UP_NOTICE_DEFAULT; + conf->dest_down_wait = DEST_DOWN_WAIT_DURATION; + conf->dest_inhibit_min = DEST_INHIBIT_DURATION_MIN; + conf->dest_inhibit_max = DEST_INHIBIT_DURATION_MAX; + } else { + if (sscanf(optarg, "%hhu,%hhu,%hhus,%hu-%hus", + &conf->dest_down_notice_num, + &conf->dest_up_notice_num, + &conf->dest_down_wait, + &conf->dest_inhibit_min, + &conf->dest_inhibit_max) != 5) { + return -1; + } + if (!dest_check_configs_sanity(conf)) + return -1; + conf->enabled = 1; + } + return 0; +} static int parse_options(int argc, char **argv, struct ipvs_command_entry *ce, - unsigned int *options, unsigned int *options_ext, unsigned int *format) + unsigned int *options, unsigned int *format) { int c, parse; poptContext context; @@ -511,7 +544,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, { "hash-target", 'Y', POPT_ARG_STRING, &optarg, 'Y', NULL, NULL }, { "cpu", '\0', POPT_ARG_STRING, &optarg, TAG_CPU, NULL, NULL }, { "expire-quiescent", '\0', POPT_ARG_NONE, NULL, TAG_CONN_EXPIRE_QUIESCENT, NULL, NULL }, - { "inhibit-on-fail", '\0', POPT_ARG_STRING, &optarg, TAG_CONN_INHIBIT_ON_FAIL, NULL, NULL }, + { "dest-check", '\0', POPT_ARG_STRING, &optarg, TAG_DEST_CHECK, NULL, NULL}, { NULL, 0, 0, NULL, 0, NULL, NULL } }; @@ -912,15 +945,11 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, ce->dpvs_svc.flags = ce->dpvs_svc.flags | IP_VS_CONN_F_EXPIRE_QUIESCENT; break; } - case TAG_CONN_INHIBIT_ON_FAIL: + case TAG_DEST_CHECK: { - set_option_ext(options_ext, OPT_EXT_INHIBIT_ON_FAIL); - if(!memcmp(optarg , "enable" , strlen("enable"))) { - ce->dpvs_svc.flags = ce->dpvs_svc.flags | IP_VS_SVC_F_DEST_CHECK; - } else if(!memcmp(optarg , "disable" , strlen("disable"))) { - ce->dpvs_svc.flags = ce->dpvs_svc.flags & (~IP_VS_SVC_F_DEST_CHECK); - } else - fail(2 , "inhibit-on-fail switch must be enable or disable\n"); + if (parse_dest_check(optarg, &ce->dpvs_svc.check_conf) != 0) { + fail(2, "invalid dest_check config"); + } break; } default: @@ -986,7 +1015,7 @@ static int restore_table(int argc, char **argv, int reading_stdin) static int process_options(int argc, char **argv, int reading_stdin) { - unsigned int options = OPT_NONE, options_ext = OPT_EXT_NONE; + unsigned int options = OPT_NONE; unsigned int format = FMT_NONE; int result = 0; const struct inet_addr_range zero_range = {}; @@ -1002,7 +1031,7 @@ static int process_options(int argc, char **argv, int reading_stdin) /* Set the default cpu be master */ ce.index = 0; - if (parse_options(argc, argv, &ce, &options, &options_ext, &format)) + if (parse_options(argc, argv, &ce, &options, &format)) return -1; generic_opt_check(ce.cmd, options); @@ -1083,7 +1112,7 @@ static int process_options(int argc, char **argv, int reading_stdin) break; case CMD_EDIT: - result = dpvs_update_service_by_options(&ce.dpvs_svc, options, options_ext); + result = dpvs_update_service_by_options(&ce.dpvs_svc, options); break; case CMD_DEL: @@ -1548,23 +1577,6 @@ set_option(unsigned int *options, unsigned int option) *options |= option; } -static inline const char * -opt2name_ext(int option) -{ - const char **ptr; - for (ptr = optnames_ext; option > 1; option >>= 1, ptr++); - - return *ptr; -} - -static void -set_option_ext(unsigned int *options, unsigned int option) -{ - if (*options & option) - fail(2, "multiple '%s' options specified", opt2name_ext(option)); - *options |= option; -} - static void tryhelp_exit(const char *program, const int exit_status) { fprintf(stderr, "Try `%s -h' or '%s --help' for more information.\n", @@ -1572,7 +1584,6 @@ static void tryhelp_exit(const char *program, const int exit_status) exit(exit_status); } - static void usage_exit(const char *program, const int exit_status) { FILE *stream; @@ -1680,7 +1691,8 @@ static void usage_exit(const char *program, const int exit_status) " --hash-target -Y hashtag choose target for conhash (support sip or qid for quic)\n" " --cpu cpu_index specifi cpu (lcore) index to show, 0 for master worker\n" " --expire-quiescent expire the quiescent connections timely whose realserver went down\n" - " --inhibit-on-fail enable passive health check, inhibit failed realservers scheduling\n", + " --dest-check config passive health check, inhibit failed realservers scheduling,disable|default|DETAIL\n" + " DETAIL:=down_retry,up_confirm,down_wait,inhibit_min-inhibit_max, for example, the default is 1,1,3s,5-3600s\n", DEF_SCHED); exit(exit_status); @@ -2116,8 +2128,17 @@ print_service_entry(dpvs_service_compat_t *se, unsigned int format) printf(" conn_timeout %u", se->conn_timeout); if (se->flags & IP_VS_CONN_F_EXPIRE_QUIESCENT) printf(" expire-quiescent"); - if (se->flags & IP_VS_SVC_F_DEST_CHECK) - printf(" inhibit-on-fail"); + if (se->check_conf.enabled) { + printf(" dest-check"); + if (!is_dest_check_conf_default(&se->check_conf)) { + printf( " %d,%d,%ds,%d-%ds", + se->check_conf.dest_down_notice_num, + se->check_conf.dest_up_notice_num, + se->check_conf.dest_down_wait, + se->check_conf.dest_inhibit_min, + se->check_conf.dest_inhibit_max); + } + } } printf("\n"); diff --git a/tools/keepalived/keepalived/check/libipvs.c b/tools/keepalived/keepalived/check/libipvs.c index 1a35c4d96..9af74def7 100644 --- a/tools/keepalived/keepalived/check/libipvs.c +++ b/tools/keepalived/keepalived/check/libipvs.c @@ -108,7 +108,7 @@ int dpvs_update_service(dpvs_service_compat_t *svc) } -int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int options, unsigned int options_ext) +int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int options) { dpvs_service_compat_t entry; @@ -168,13 +168,7 @@ int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int opti } } - if (options_ext & OPT_EXT_INHIBIT_ON_FAIL) { - if (svc->flags & IP_VS_SVC_F_DEST_CHECK) { - entry.flags |= IP_VS_SVC_F_DEST_CHECK; - } else { - entry.flags &= ~IP_VS_SVC_F_DEST_CHECK; - } - } + entry.check_conf = svc->check_conf; return dpvs_update_service(&entry); } diff --git a/tools/keepalived/keepalived/include/libipvs.h b/tools/keepalived/keepalived/include/libipvs.h index 6b2db0fe4..bc4c90e65 100644 --- a/tools/keepalived/keepalived/include/libipvs.h +++ b/tools/keepalived/keepalived/include/libipvs.h @@ -46,9 +46,6 @@ #define OPT_WHTLST_ADDRESS 0x80000000 #define NUMBER_OF_OPT 33 -#define OPT_EXT_NONE 0x00000000 -#define OPT_EXT_INHIBIT_ON_FAIL 0x00000001 - #define MINIMUM_IPVS_VERSION_MAJOR 1 #define MINIMUM_IPVS_VERSION_MINOR 1 #define MINIMUM_IPVS_VERSION_PATCH 4 @@ -102,8 +99,7 @@ extern int dpvs_add_service(dpvs_service_compat_t *svc); extern int dpvs_update_service(dpvs_service_compat_t *svc); /* update a virtual service based on option */ -extern int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int options, unsigned int options_ext); - +extern int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int options); /* delete a virtual service */ extern int dpvs_del_service(dpvs_service_compat_t *svc); @@ -155,7 +151,6 @@ extern ipvs_timeout_t *dpvs_get_timeout(void); /* get ipvs daemon information */ extern ipvs_daemon_t *dpvs_get_daemon(void); - extern const char *ipvs_strerror(int err); extern int dpvs_send_gratuitous_arp(struct in_addr *in); From d41afd4cb087ed572e54c488a704ee55ed8047b0 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 19 Apr 2023 14:41:35 +0800 Subject: [PATCH 024/105] ipvs: backnd passive health check for bidirectional udp flow udp dest-check works only when the udp is bidirectional, that is, the udp conns that forwarding inbound only or outbound only are always detcted dead. Thus "dest-check" should be never configured for the single directional udp flow. Besides, the a smaller conn timeout may be specified for the bidirectional flow service to detect dest fault quickly. Signed-off-by: ywc689 --- conf/dpvs.bond.conf.sample | 1 + conf/dpvs.conf.items | 1 + conf/dpvs.conf.sample | 1 + conf/dpvs.conf.single-bond.sample | 1 + conf/dpvs.conf.single-nic.sample | 1 + include/ipvs/proto_udp.h | 4 ++- src/ipvs/ip_vs_conn.c | 8 ++++- src/ipvs/ip_vs_proto_udp.c | 49 ++++++++++++++++++++++++++++++- 8 files changed, 63 insertions(+), 3 deletions(-) diff --git a/conf/dpvs.bond.conf.sample b/conf/dpvs.bond.conf.sample index 64d4d73cb..06faf096f 100644 --- a/conf/dpvs.bond.conf.sample +++ b/conf/dpvs.bond.conf.sample @@ -334,6 +334,7 @@ ipvs_defs { uoa_mode opp uoa_max_trail 3 timeout { + oneway 60 normal 300 last 3 } diff --git a/conf/dpvs.conf.items b/conf/dpvs.conf.items index d2a388937..c62f66309 100644 --- a/conf/dpvs.conf.items +++ b/conf/dpvs.conf.items @@ -234,6 +234,7 @@ ipvs_defs { uoa_mode opp uoa_max_trail 3 timeout { <1-31535999> + oneway 300 <300> normal 300 <300> last 3 <3> } diff --git a/conf/dpvs.conf.sample b/conf/dpvs.conf.sample index 4e9beb735..dc05f61b6 100644 --- a/conf/dpvs.conf.sample +++ b/conf/dpvs.conf.sample @@ -298,6 +298,7 @@ ipvs_defs { uoa_mode opp uoa_max_trail 3 timeout { + oneway 60 normal 300 last 3 } diff --git a/conf/dpvs.conf.single-bond.sample b/conf/dpvs.conf.single-bond.sample index f3d44e2d5..f8151245a 100644 --- a/conf/dpvs.conf.single-bond.sample +++ b/conf/dpvs.conf.single-bond.sample @@ -239,6 +239,7 @@ ipvs_defs { uoa_mode opp uoa_max_trail 3 timeout { + oneway 60 normal 300 last 3 } diff --git a/conf/dpvs.conf.single-nic.sample b/conf/dpvs.conf.single-nic.sample index a90dbfc2a..099c23e0e 100644 --- a/conf/dpvs.conf.single-nic.sample +++ b/conf/dpvs.conf.single-nic.sample @@ -213,6 +213,7 @@ ipvs_defs { uoa_mode opp uoa_max_trail 3 timeout { + oneway 60 normal 300 last 3 } diff --git a/include/ipvs/proto_udp.h b/include/ipvs/proto_udp.h index 66881f0ce..3bd98a3af 100644 --- a/include/ipvs/proto_udp.h +++ b/include/ipvs/proto_udp.h @@ -21,7 +21,9 @@ #include enum { - DPVS_UDP_S_NORMAL = 0, + DPVS_UDP_S_NONE = 0, + DPVS_UDP_S_ONEWAY, + DPVS_UDP_S_NORMAL, DPVS_UDP_S_LAST }; diff --git a/src/ipvs/ip_vs_conn.c b/src/ipvs/ip_vs_conn.c index b94cb6855..38e79bcf4 100644 --- a/src/ipvs/ip_vs_conn.c +++ b/src/ipvs/ip_vs_conn.c @@ -517,7 +517,7 @@ void dp_vs_conn_set_timeout(struct dp_vs_conn *conn, struct dp_vs_proto *pp) /* set proper timeout */ if ((conn->proto == IPPROTO_TCP && conn->state == DPVS_TCP_S_ESTABLISHED) - || (conn->proto == IPPROTO_UDP && conn->state == DPVS_UDP_S_NORMAL)) { + || conn->proto == IPPROTO_UDP) { conn_timeout = dp_vs_conn_get_timeout(conn); if (conn_timeout > 0) { @@ -1287,6 +1287,12 @@ static inline char* get_conn_state_name(uint16_t proto, uint16_t state) break; case IPPROTO_UDP: switch (state) { + case DPVS_UDP_S_NONE: + return "UDP_NONE"; + break; + case DPVS_UDP_S_ONEWAY: + return "UDP_ONEWAY"; + break; case DPVS_UDP_S_NORMAL: return "UDP_NORM"; break; diff --git a/src/ipvs/ip_vs_proto_udp.c b/src/ipvs/ip_vs_proto_udp.c index fb8313828..4adecb4bf 100644 --- a/src/ipvs/ip_vs_proto_udp.c +++ b/src/ipvs/ip_vs_proto_udp.c @@ -59,6 +59,8 @@ static int g_uoa_mode = UOA_M_OPP; /* by default */ int g_defence_udp_drop = 0; static int udp_timeouts[DPVS_UDP_S_LAST + 1] = { + [DPVS_UDP_S_NONE] = 2, + [DPVS_UDP_S_ONEWAY] = 300, [DPVS_UDP_S_NORMAL] = 300, [DPVS_UDP_S_LAST] = 2, }; @@ -253,6 +255,14 @@ udp_conn_lookup(struct dp_vs_proto *proto, static int udp_conn_expire(struct dp_vs_proto *proto, struct dp_vs_conn *conn) { + // Note: udp dest-check works only when the udp is bidirectional, that is, + // the udp conns that forwarding inbound only or outbound only are always + // detcted dead. Thus "dest-check" should be never configured for the + // single directional udp flow. Besides, the a smaller conn timeout may be + // specified for the bidirectional flow service to detect dest fault quickly. + if (conn->state == DPVS_UDP_S_ONEWAY) + dp_vs_dest_detected_dead(conn->dest); + if (conn->prot_data) rte_free(conn->prot_data); @@ -269,8 +279,24 @@ static int udp_conn_expire_quiescent(struct dp_vs_conn *conn) static int udp_state_trans(struct dp_vs_proto *proto, struct dp_vs_conn *conn, struct rte_mbuf *mbuf, int dir) { - conn->state = DPVS_UDP_S_NORMAL; + int old_state = conn->state; + + if (conn->dest->fwdmode == DPVS_FWD_MODE_SNAT) { + if (dir == DPVS_CONN_DIR_INBOUND) + conn->state = DPVS_UDP_S_NORMAL; + else if (conn->state == DPVS_UDP_S_NONE) + conn->state = DPVS_UDP_S_ONEWAY; + } else { + if (dir == DPVS_CONN_DIR_OUTBOUND) + conn->state = DPVS_UDP_S_NORMAL; + else if (conn->state == DPVS_UDP_S_NONE) + conn->state = DPVS_UDP_S_ONEWAY; + } dp_vs_conn_set_timeout(conn, proto); + + if (old_state == DPVS_UDP_S_ONEWAY && conn->state == DPVS_UDP_S_NORMAL) + dp_vs_dest_detected_alive(conn->dest); + return EDPVS_OK; } @@ -860,6 +886,25 @@ static void uoa_mode_handler(vector_t tokens) FREE_PTR(str); } +static void timeout_oneway_handler(vector_t tokens) +{ + int timeout; + char *str = set_value(tokens); + + assert(str); + timeout = atoi(str); + if (timeout > IPVS_TIMEOUT_MIN && timeout < IPVS_TIMEOUT_MAX) { + RTE_LOG(INFO, IPVS, "udp_timeout_oneway = %d\n", timeout); + udp_timeouts[DPVS_UDP_S_ONEWAY] = timeout; + } else { + RTE_LOG(INFO, IPVS, "invalid udp_timeout_oneway %s, using default %d\n", + str, 300); + udp_timeouts[DPVS_UDP_S_ONEWAY] = 300; + } + + FREE_PTR(str); +} + static void timeout_normal_handler(vector_t tokens) { int timeout; @@ -908,6 +953,7 @@ void udp_keyword_value_init(void) g_defence_udp_drop = 0; g_uoa_max_trail = UOA_DEF_MAX_TRAIL; + udp_timeouts[DPVS_UDP_S_ONEWAY] = 300; udp_timeouts[DPVS_UDP_S_NORMAL] = 300; udp_timeouts[DPVS_UDP_S_LAST] = 2; } @@ -921,6 +967,7 @@ void install_proto_udp_keywords(void) install_keyword("timeout", NULL, KW_TYPE_NORMAL); install_sublevel(); install_keyword("normal", timeout_normal_handler, KW_TYPE_NORMAL); + install_keyword("oneway", timeout_oneway_handler, KW_TYPE_NORMAL); install_keyword("last", timeout_last_handler, KW_TYPE_NORMAL); install_sublevel_end(); } From 7123111528bae3265c6631ca624989258c634d22 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 19 Apr 2023 16:32:18 +0800 Subject: [PATCH 025/105] ipvsadm: add option --conn-timeout for service config Signed-off-by: ywc689 --- include/ipvs/dest.h | 1 - src/ipvs/ip_vs_conn.c | 4 ++-- src/ipvs/ip_vs_dest.c | 1 - tools/ipvsadm/ipvsadm.c | 13 +++++++++++-- tools/keepalived/keepalived/check/libipvs.c | 1 + 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/include/ipvs/dest.h b/include/ipvs/dest.h index bccb89167..b28e5ed34 100644 --- a/include/ipvs/dest.h +++ b/include/ipvs/dest.h @@ -73,7 +73,6 @@ struct dp_vs_dest { uint32_t vfwmark; /* firewall mark of service */ struct dp_vs_service *svc; /* service it belongs to */ union inet_addr vaddr; /* virtual IP address */ - unsigned conn_timeout; /* conn timeout copied from svc*/ unsigned limit_proportion; /* limit copied from svc*/ union dest_check dfc; /* failure detection and inhibition */ diff --git a/src/ipvs/ip_vs_conn.c b/src/ipvs/ip_vs_conn.c index 38e79bcf4..82a30a06f 100644 --- a/src/ipvs/ip_vs_conn.c +++ b/src/ipvs/ip_vs_conn.c @@ -505,8 +505,8 @@ static void dp_vs_conn_put_nolock(struct dp_vs_conn *conn); unsigned dp_vs_conn_get_timeout(struct dp_vs_conn *conn) { - if (conn && conn->dest) - return conn->dest->conn_timeout; + if (conn && conn->dest && conn->dest->svc) + return conn->dest->svc->conn_timeout; return 0; } diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 3c046e424..8ff051616 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -113,7 +113,6 @@ int dp_vs_dest_new(struct dp_vs_service *svc, dest->proto = svc->proto; dest->vaddr = svc->addr; dest->vport = svc->port; - dest->conn_timeout = svc->conn_timeout; dest->limit_proportion = svc->limit_proportion; dest->vfwmark = svc->fwmark; dest->addr = udest->addr; diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index 3bd730bec..94e7a7b4d 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -333,6 +333,7 @@ enum { TAG_CPU, TAG_CONN_EXPIRE_QUIESCENT, TAG_DEST_CHECK, + TAG_CONN_TIMEOUT, }; /* various parsing helpers & parsing functions */ @@ -455,7 +456,8 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, { int c, parse; poptContext context; - char *optarg=NULL; + char *optarg= NULL; + int intarg = NULL; struct poptOption options_table[] = { { "add-service", 'A', POPT_ARG_NONE, NULL, 'A', NULL, NULL }, { "edit-service", 'E', POPT_ARG_NONE, NULL, 'E', NULL, NULL }, @@ -545,6 +547,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, { "cpu", '\0', POPT_ARG_STRING, &optarg, TAG_CPU, NULL, NULL }, { "expire-quiescent", '\0', POPT_ARG_NONE, NULL, TAG_CONN_EXPIRE_QUIESCENT, NULL, NULL }, { "dest-check", '\0', POPT_ARG_STRING, &optarg, TAG_DEST_CHECK, NULL, NULL}, + { "conn-timeout", '\0', POPT_ARG_INT, &intarg, TAG_CONN_TIMEOUT, NULL, NULL}, { NULL, 0, 0, NULL, 0, NULL, NULL } }; @@ -952,6 +955,11 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, } break; } + case TAG_CONN_TIMEOUT: + { + ce->dpvs_svc.conn_timeout = intarg; + break; + } default: fail(2, "invalid option `%s'", poptBadOption(context, POPT_BADOPTION_NOALIAS)); @@ -1674,6 +1682,7 @@ static void usage_exit(const char *program, const int exit_status) " --syncid sid syncid for connection sync (default=255)\n" " --connection -c output of current IPVS connections\n" " --timeout output of timeout (tcp tcpfin udp)\n" + " --conn-timeout set connection established timeout\n" " --daemon output of daemon information\n" " --stats output of statistics information\n" " --rate output of rate information\n" @@ -2125,7 +2134,7 @@ print_service_entry(dpvs_service_compat_t *se, unsigned int format) if (se->flags & IP_VS_CONN_F_SYNPROXY) printf(" synproxy"); if (se->conn_timeout != 0) - printf(" conn_timeout %u", se->conn_timeout); + printf(" conn-timeout %u", se->conn_timeout); if (se->flags & IP_VS_CONN_F_EXPIRE_QUIESCENT) printf(" expire-quiescent"); if (se->check_conf.enabled) { diff --git a/tools/keepalived/keepalived/check/libipvs.c b/tools/keepalived/keepalived/check/libipvs.c index 9af74def7..16d7ca8d2 100644 --- a/tools/keepalived/keepalived/check/libipvs.c +++ b/tools/keepalived/keepalived/check/libipvs.c @@ -131,6 +131,7 @@ int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int opti entry.flags |= IP_VS_SVC_F_PERSISTENT; entry.timeout = svc->timeout; } + entry.conn_timeout = svc->conn_timeout; if (options & OPT_NETMASK) { entry.netmask = svc->netmask; From 48f6881604b674fe7a057f784006ed12616b47c2 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 19 Apr 2023 20:48:46 +0800 Subject: [PATCH 026/105] ipvsadm: fix ambiguity of command opt'-Y' fix #877 Signed-off-by: ywc689 --- tools/ipvsadm/ipvsadm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index 94e7a7b4d..e36293483 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -330,6 +330,7 @@ enum { TAG_NO_SORT, TAG_PERSISTENCE_ENGINE, TAG_SOCKPAIR, + TAG_HASH_TARGET, TAG_CPU, TAG_CONN_EXPIRE_QUIESCENT, TAG_DEST_CHECK, @@ -543,7 +544,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, { "synproxy", 'j' , POPT_ARG_STRING, &optarg, 'j', NULL, NULL }, { "ifname", 'F', POPT_ARG_STRING, &optarg, 'F', NULL, NULL }, { "match", 'H', POPT_ARG_STRING, &optarg, 'H', NULL, NULL }, - { "hash-target", 'Y', POPT_ARG_STRING, &optarg, 'Y', NULL, NULL }, + { "hash-target", '\0', POPT_ARG_STRING, &optarg, TAG_HASH_TARGET, NULL, NULL }, { "cpu", '\0', POPT_ARG_STRING, &optarg, TAG_CPU, NULL, NULL }, { "expire-quiescent", '\0', POPT_ARG_NONE, NULL, TAG_CONN_EXPIRE_QUIESCENT, NULL, NULL }, { "dest-check", '\0', POPT_ARG_STRING, &optarg, TAG_DEST_CHECK, NULL, NULL}, @@ -915,7 +916,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, break; } - case 'Y': + case TAG_HASH_TARGET: { set_option(options, OPT_HASHTAG); if (strcmp(ce->dpvs_svc.sched_name, "conhash")) @@ -1697,10 +1698,11 @@ static void usage_exit(const char *program, const int exit_status) " --ifname -F nic interface for laddrs\n" " --synproxy -j TCP syn proxy\n" " --match -H MATCH select service by MATCH 'af,proto,srange,drange,iif,oif', af should be defined if no range defined\n" - " --hash-target -Y hashtag choose target for conhash (support sip or qid for quic)\n" + " --hash-target hashtag choose target for conhash (support sip or qid for quic)\n" " --cpu cpu_index specifi cpu (lcore) index to show, 0 for master worker\n" " --expire-quiescent expire the quiescent connections timely whose realserver went down\n" - " --dest-check config passive health check, inhibit failed realservers scheduling,disable|default|DETAIL\n" + " --dest-check check_conf config passive health check, inhibit scheduling to failed backends\n" + " check_conf := disable|default|DETAIL\n" " DETAIL:=down_retry,up_confirm,down_wait,inhibit_min-inhibit_max, for example, the default is 1,1,3s,5-3600s\n", DEF_SCHED); From b9010942b685d8d3a205d978ab3fb2ee8eb5a704 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 20 Apr 2023 20:50:27 +0800 Subject: [PATCH 027/105] doc: add doc for backend passive health check Signed-off-by: ywc689 --- doc/dest-check.md | 204 ++++++++++++++++++ doc/pics/health_check-master-lcore.drawio.png | Bin 0 -> 86157 bytes doc/pics/health_check-slave-lcores.drawio.png | Bin 0 -> 49219 bytes doc/pics/health_check.drawio | 169 +++++++++++++++ 4 files changed, 373 insertions(+) create mode 100644 doc/dest-check.md create mode 100644 doc/pics/health_check-master-lcore.drawio.png create mode 100644 doc/pics/health_check-slave-lcores.drawio.png create mode 100644 doc/pics/health_check.drawio diff --git a/doc/dest-check.md b/doc/dest-check.md new file mode 100644 index 000000000..e637f70dc --- /dev/null +++ b/doc/dest-check.md @@ -0,0 +1,204 @@ +Backends Failure Detection and Inhibition +------ + +# Concepts + +DPVS implements a simple backend failure detection and inhibition mechanism by examining the packet flow it forwards. We call it Passive Health Check because it doesn't send any probe data to the backends. It works for TCP by checking if SYN/ACK packet is replied from the backend, and if not, inhibit scheduling of the backend for a period. The inhibiting period is gained or lost exponentially depending on subsequent checking is failure or success. As for UDP, it works only when the UDP flow is bidirectional, that is, the UDP connections that forwarding inbound or outbound only are always detcted as dead. Thus "dest-check" should be never configured for the UDP services with monodirectional flow. In summury, DPVS Passive Health Check can be used in the following scenarios: + +* TCP FullNat/Nat64/DR/Tunnel/Nat fowarding mode. +* UDP FullNat/Nat64/Nat forwarding mode with bidirectional data flow. + +It's noted that DPVS Passive Health Check has no way to discover the backend failure unless packet drop has already acctually occurred. A smaller session timeout may be preferred for TCP SYN_SENT/SYN_RECV and UDP ONEWAY states to detect backend fault and remove it from available backend list quickly. + +The state transition diagrams below show the interactions of DPVS master and slave lcores for Passive Health Check. + +![master lcore](./pics/health_check-master-lcore.drawio.png) + +![slave lcores](./pics/health_check-slave-lcores.drawio.png) + +Generally speaking, the slave lcores are responsible for failure detection, and the master lcore is responsible for backend inhibition. + +The backends are detected as DOWN in the following cases: +* TCP session state transfers from SYN_RECV to CLOSE +* TCP session state transfers from SYN_SENT to CLOSE +* TCP session expired from SYN_RECV state +* TCP session expired from SYN_SENT state +* TCP synproxy step 3 received RST when awaiting SYN/ACK from backend +* UDP session expired from ONEWAY state + +The backends are detected as UP in the following cases: +* TCP session state tranfers to ESTABLISH +* TCP synproxy step 3 received SYN/ACK from backend +* UDP session state tranfers from ONEWAY to NORMAL + +Backend inhibition is performed by setting the inhibition flag into the backend server and changing its weight to zero so that new sessions would not be scheduled it. + +Four types of lcore msg notice are used: + +* **Down Notice**: unicast msg, from slave to master, notify master a backend DOWN event is detected +* **Up Notice**: unicast msg, from slave to master, notify master a backend UP event is detected +* **Close Notice**: multicast msg, from master to all slaves, inhibit scheduling a failed backend +* **Open Notice**: multicast msg, from master to all slaves, restore scheduling a inhibited backend + +DPVS allows to specify a per-service Passive Health Check configuration, each configuration including the 5 parameters below: + +* **down_retry**: how many DOWNs are detected from a backend before inhibiting scheduling to it, default 1 (no retry). +* **up_confirm**: how many UP notices are sent to master lcore for each inhibited backend and each slave lcore after restoring scheduling, default 1. +* **down_wait**: the `down_retry` duration, in seconds, default 3s, no sense when `down_retry` is 1. +* **inhibit_min**: the minimum inhibition duration, in seconds, default 5s. +* **inhibit_max**: the maximum inhibition duraiton, in seconds, default 3600s. + +DPVS Passive Health Check could be configured with `ipvsadm`, refer to its help message for the usage. + +```sh +ipvsadm -h | grep dest-check -A3 +``` + +# Examples + +Before we begin, serveral configs in /etc/dpvs.conf are changed from defaults. + +* global_defs/log_level debug +* ipvs_defs/tcp/timeout/syn_recv 3 +* ipvs_defs/tcp/timeout/syn_sent 3 + +Firstly, we configure a test service 192.168.88.1:80. + +```sh +dpip vlan add dpdk0.102 link dpdk0 id 102 +dpip addr add 192.168.88.28/24 dev dpdk0.102 +dpip addr add 192.168.88.1/32 dev dpdk0.102 +ipvsadm -A -t 192.168.88.1:80 --dest-check default +ipvsadm -at 192.168.88.1:80 -r 192.168.88.30:80 -b +ipvsadm -at 192.168.88.1:80 -r 192.168.88.68:80 -b +ipvsadm -Pt 192.168.88.1:80 -z 192.168.88.241 -F dpdk0.102 +``` +The test service uses the default dest-check configs, i.e., no down retry, 1 up confirm notice for each slave, and inhibition duration range is 5-3600s. Two backends 192.18.88.30:80 and 192.168.88.68:80 are initially UP. We can check the service configured just now. + +```sh +# ipvsadm -ln +IP Virtual Server version 1.9.3 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.88.1:80 wlc dest-check + -> 192.168.88.30:80 FullNat 1 0 0 + -> 192.168.88.68:80 FullNat 1 0 0 +``` + +Then we run a script to send requests to our test service every 0.5 second, and check the response. It prints a character '.' if succeeds, and a character 'x' if fails for each request. + +```sh +while true +do + curl -g -s -m 1 192.168.88.1:80 -o /dev/null + [ $? -eq 0 ] && printf . || printf x + sleep 0.5 +done +``` +The request should always succeed at the beginning. After a while, we shutdown the server 192.168.88.30:80 and keep watching the output of the script. + +``` +# while true; do curl -g -s -m 1 192.168.88.1:80 -o /dev/null; [ $? -eq 0 ] && printf . || printf x; sleep 0.5; done +............................x.........x...................x.......................................x................. +.............................................................x...................................................... +.....................................................................................................x.............. +.................................................................................................................... +.................................................................................................................... +..................................................................x................................................. +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................x.. +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +..............x..................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +.......................................................... +``` + +As the script output shows, after we shutdown one of the backend servers, the test service uses the failed server far less frequent than it would if health-check is not enabled. Besides, the DPVS logs show that the inhibition duration is gained exponentially when the backend detected to be failed successively. + +``` +# tail -f /var/log/messages| grep SERVICE +Apr 20 18:56:01 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 5s, origin_weight 0] notify slaves DOWN +Apr 20 18:56:06 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 1, inhibit_duration 10s, origin_weight 1] notify slaves UP +Apr 20 18:56:06 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 10s, origin_weight 0] notify slaves DOWN +Apr 20 18:56:16 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 1, inhibit_duration 20s, origin_weight 1] notify slaves UP +Apr 20 18:56:16 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 20s, origin_weight 0] notify slaves DOWN +Apr 20 18:56:36 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 1, inhibit_duration 40s, origin_weight 1] notify slaves UP +Apr 20 18:56:37 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 40s, origin_weight 0] notify slaves DOWN +Apr 20 18:57:17 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 1, inhibit_duration 80s, origin_weight 1] notify slaves UP +Apr 20 18:57:17 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 80s, origin_weight 0] notify slaves DOWN +Apr 20 18:58:36 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 1, inhibit_duration 160s, origin_weight 1] notify slaves UP +Apr 20 18:58:37 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 160s, origin_weight 0] notify slaves DOWN +Apr 20 19:01:16 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 1, inhibit_duration 320s, origin_weight 1] notify slaves UP +Apr 20 19:01:17 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 320s, origin_weight 0] notify slaves DOWN +Apr 20 19:06:37 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 1, inhibit_duration 640s, origin_weight 1] notify slaves UP +Apr 20 19:06:37 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 640s, origin_weight 0] notify slaves DOWN +Apr 20 19:12:40 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 1, inhibit_duration 1280s, origin_weight 1] notify slaves UP +Apr 20 19:12:41 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 1, inhibit_duration 1280s, origin_weight 0] notify slaves DOWN +``` + +Now we change the dest-check configs to be 3 down_retry in 3s down delay, 3 up_confirm notice for each slave, and inhibition duration range is 60-3600s. + +``` +# ipvsadm -dt 192.168.88.1:80 -r 192.168.88.30:80 +# ipvsadm -at 192.168.88.1:80 -r 192.168.88.30:80 -b +# ipvsadm -Et 192.168.88.1:80 --dest-check 3,3,3s,60-3600s +# ipvsadm -ln +IP Virtual Server version 1.9.3 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.88.1:80 wlc dest-check 3,3,3s,60-3600s + -> 192.168.88.30:80 FullNat 1 0 9 + -> 192.168.88.68:80 FullNat 1 0 5 +``` + +Run the above script and we get the outputs below. + +``` +# while true; do curl -g -s -m 1 192.168.88.1:80 -o /dev/null; [ $? -eq 0 ] && printf . || printf x; sleep 0.5; done +..............x.x..x................................................................................................ +.....................xxx............................................................................................ +.................................................................................................................... +.........................x..xx...................................................................................... +.................................................................................................................... +.................................................................................................................... +.................................................................................................................... +....................................xxx............................................................................. +.................................................................................................................... +.................................................................................................................... +................................................... +``` +Corresponding DPVS logs are listed below. + +``` +Apr 20 20:37:16 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 3, inhibit_duration 60s, origin_weight 0] notify slaves DOWN +Apr 20 20:38:16 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 3, inhibit_duration 120s, origin_weight 1] notify slaves UP +Apr 20 20:38:17 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 3, inhibit_duration 120s, origin_weight 0] notify slaves DOWN +Apr 20 20:40:17 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 3, inhibit_duration 240s, origin_weight 1] notify slaves UP +Apr 20 20:40:19 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 3, inhibit_duration 240s, origin_weight 0] notify slaves DOWN +Apr 20 20:44:20 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 0, inhibited yes, down_notice_recvd 3, inhibit_duration 480s, origin_weight 1] notify slaves UP +Apr 20 20:44:21 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 3, inhibit_duration 480s, origin_weight 0] notify slaves DOWN +``` +It shows that at least 3 failure are detected before inhibiting the failed backend, and the inhibition duration starts from 60s. diff --git a/doc/pics/health_check-master-lcore.drawio.png b/doc/pics/health_check-master-lcore.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..b0bcace6385f72b2e13712c8111eccd22d1dc276 GIT binary patch literal 86157 zcmeEv1zc2H_qKt6iU^8I$ABU#-BJQW3rHv^-OT_)r&11`ih_hRA}t_o0*ZjrB`7gS zch`5$Fr!@c)_3oFufG4+dw;|}XZAT~?X{luthM$!_+65dICOyYz^+}p4oOKu6?g60 z%eQOSZW&x`U}PpdyaxET8?GoJvMalRd}P-yms_@Cs3)yH2u;ZvS+Wjl~!S zw>`-YJ;}zVV`aspZ=z#lqhkSQvNW&-hJfQ1Fntq469fJ2bJ$qe*cn+k7};2qS-4NK z3v+;9*w~pk*jTP@pRZ$NV2Pek7UpbXZmx5ZO`Ma71(@oziixE@%mEJkD5ng3VPye^ z*+qb#fCF3{+dn#TaWDWQ!d6!11}X-+GA6)%h;y=YGqH04!>45=m1QrUWD^B`Ha9Ud z0KQ2W=$XO5kBA!Ez$}0faaLAVCSYpRHI;M>b!<#_OaVTVfvt|w_VZj))VU&|XuxX9 zdF_gYmZ_Do`e4APlS1L7|h((#0veG=s`W0rKN!$dd1OWIyN@oGNT>>J!A+o zM?X1w02J6S&Hx9L^mNR>9aS;Ww>92Amxqme`zgS)B@IlBj4@Yc<>K8wVxfaM8T}-1 zV;w;2wm**=+POB{a>Pi}1_lG>+p%;z4`WWUa1=E#2ZfE1BlnrSx(4PVI(lYCsE>)l%waYt@vibaHVl}|#1>RV9`FMCI&fpu)xha63;IO@m>V{*u{FRbG|FT{;On;%EqtnA;2`|_pjp&j-D0001lfO-6$t?V=eF5q;)|C;YK7*0dr zKX4o{m>uKnsDHpX+|~wWX0YQ37wR8yQ2xN;jORp3+>CQcNuMGag91{eWW%Ek+v zjT(W10tfx!_HUrLKmT^gz{Uh{Vg{gR1qZ(dl0RwwaG0G9%AEtB`z}skaL-o9#t7j4 zDDL+C6VW0y03^138p>V&fA|g?19Kf)6Z@UBu(5m(EB?sb81E!(W1|B)e#|^pFcVAL zU!l+2pZT?~po6{yej1n!Z5bFqLmLJ=8sC1O7JPe+@6FDRrm%l$dUhZ-65p1>ACVjC zbRder@SNZN4Ek&oZ~475{}{bt<@pwTzt|$w5@rc{*}rU(Uz?ACqlqnOp&$VTf4&Nu z858J~hfZlJVuyw|c5sQnSOX0}7`WR(<9`;OhfWjxir@dcPz415C`7;* z{|+1h!Ql&#pnk(3$*-Xi3llFF3P(O85<43hHT(u90cU{X#3^f4_bKAPnO0 zKc`h6A&EhU zgZ~r?d^Y3`8Lyil8wt8$o-&_ zO}}tIT-J7AWejzI5soSrg4In{4l5vZ08-JIA&j6PstqOT8@MZTNb|79ZLYl>w9vjs9*sH!m|8|YI1q-O+g<*!z}(6JmV z2U_95m;<;CR(AAq@5DhaZYFMYv2ADG9s`+}9NNEM1Y<)#%#J7?qg&f*vV$sNbP+u8 zM|9Q3K+k@MPJUKMc`E}zSGja7fTXX8r7j%&hPmi}wc>*5=6_FdIWSoVwBoX{ph@1( zskq;!pD;S~A5&aWa~M#XL__&bO$D_4zYJvo7xS;`DzKYjXTpq?6&<+!oVxmLkb%*n zzpSfpa6cJ~os|}_^T5!=#sV|(e}SL>u~d)^QwA$O0FxlL{MgzLY%fRM<#)9I zFQfQ&isJj>-RBq(MD@?G{CV_ijQ=00X8Aia7nrT<7yt(Y0P+=$_-S%; z-|gZ0^;#X!+=#BZf$f5TQeqkgKYQKJXKd4`FG|byW26&)(GB+3o6EMJ(n{w)(ocr2 zu5n|sY-oRsNgV9JIo|I?SeQ@!Cktz+E!w}*$cWkO{iS7e=O%8{QB14qFArcwzcf9{ zLd{rh#AT$puZZZg>&kIll(16Xmi(6nRtp_C=<3ia2_D@!D@a!WZw2hK|6dC$szS^9 zzZOa(Z%8ae*w%P=ohz;M#PZ>I=1 zJ37nu8>;nhIkR6?EbeQLO7^y#EXulEFiBfWLnj-vKh)^Hqf`2ul+~}bMT2j5_=-$? z>&Le5bmv!;XT!8reQqHG+Tl?)iV^mAm;=xETBX@|S(v!l*||74S-DxcS=hMIjPO56 zC4N=$Lp)oIq`uX_V|JtEVp0)bodVv7dFs(!A#uG$6Q#^3GaW(zkIg&t6$y-^#e6Q z|CR#%E_FfY7=G8gVC?L_p1WY$wRQjsX1}i$U@c#C4%18W8|@}Q^T!|C`m^0{`a2ts z|4gGaaI61qn}mK#&HqN6WM$`I`l=wqiw>1`BIS>`+4#F$9P<*#@96VCvtRyyJ=4Fa z75+nN%)yOjfao+98wS^YP9;W{AHJi+|2a^`!2Vx06ZG2z3@l-GM#kU9HPZ#)Q+t2C4?7%$@$v7@hs8BM1<8L3Q|!+Wt5Z1RBx5aT(vq?RgzePmXJ!AKG6f7AL%lv9 z{GWjUsP{MYrl7kQ*ja%;aEng7e>RYBOJUqUje!7O;a42PUw(JPcX0bVIr*Ra?G67b zTC-vrS$9A)>%UlpMQxh=yISheJ21gN#J# z+Jg7U$6Y7=A#Aw8r?GEb-xGG7`V1Yh?zP*;8%`ieHQppTC*yzY73 zbFV@$0ugpS6pAhPa%<(`=9F6-4BjBnEVvX0Z!C)&=CA6jaELE#-<+&ycdnY6)^OmN ze=7=G>uRrTGj4QhfWMYli>X?PnSIqqkH5k{=n^(}pmbIxDi z8g$nlDf?O8Z$HK9cOf+|>s5F3iCegId;BgyLNVXYaqY>dF6vkk$`SnPIaCX9lS#Xy zD+---c76c(_!Dic%9$V-$CT?ZUyMrCYHR)bN&DibTEtc_h6R^OkoVvXCYm$;Di?d& zlPQ2Xl5vqsU(0}3{KFl+U=yxB*E!^fyoWQr%1q@_Mb3QlWseBFGp!w`gqf>iFgJ<5 z<%_#_W6^b;)mnLtENOJJoC8+2$Z4fctM{Jk?5lcBmx)&DV`P?(b$G|C$zbOO`y=Al z^;bG)V9w1kw;`Ot0)RTy^%cFh??ygqmNVmeZ`+JK$?POGBF{GzsU%GWVJ{ocuRC93 zS+USIWHjLXf|l}K`Gf`RtWdiiV&=SIh`^$;eXrASchK2}j~!~T3cJ`jD!2J}GVc-) zToxrmw}-CzlBiX6hnkuzIbJBJ`=#1IwaKwOvCQ*do$}!@FMeec#I+eGe-R;`fC_)TRO_d3^S zYA!rLB4c1oFU}&axCJ##+%Xbb>#P?ivrul>3N+$RS`Tlg(}6j@ua}pI0CD@#JH4rA6&QUr>YHC*^Js=0h{ILa=5rSa8b3BlJ9{VenGTkFG7xPkFr9EdyKVN-lK zRIXO=PJ<}M*djTS%;pZJ#~(aXrWPP#71a}b5Kb>|Jdt}J447T6`iYC#W=s~GaGG0+ zcB}xjQ(f98pi0bC!^L%B;nCJ@Q}Y2qpOuQQ*W>_hi@1>8qoQl1vq|>!imwQc_xW)Y zYAS>hr|PxtqQMQLJmH-j{BT~;fK1$g@x}hdUYDs#g#`D3fVrwkyBsskt=0A@<;UsA zNI8n!i)mUrQm3yQMtv>N$G9xxIpwpjQ*<}DUZua1&uJ+*&z5|OzNv-a&iMzPp)G_- z!rr>Xw+howj^3I*PA4Z#4rxBCA@}I@V^cPq8ezS$n|2TKg4T$TOJAEj1NGb6o|X}T z(d&$UIqqt8wX_BEE2IrwxJVWgx_fS%cXteW;j+zO^Ll^3t9E4wGv zwA$6-^@;-W8*{BHT5e^wCBk}YlU#tk5>YmdvwejI#K&%EF7Q}{zdI#lSAl=kB*x4A z!(J*?Mb*rdES8tA$~*Lor?mr{CelOxD|I+>qePUtwF5bMd+7StzyZ}J#!?KjAdZ~9 z^VMQf6W-wi4^3KL#pn6z_9d}=g@GA;g&9J=McWc6c(K`{p@eTQMgYJg7w-LamoJcs zMx!?r;30?Nb2#_D!YR5v_rc%Beh^GmP=v9pH;I0Sd7vw8BBmRx|a;DIyZNjqKq z_F^Z&Ls7+yII-Vc%!@#hvq%_ssPEgmp9Bw;lo{}T_(oR5*f*5*$gorRPkkdQBtCE` zrcCYjUb$};MhBcx=hACEU-1tB%9_V*&Zlw5uMg6#SQQcQ;ape6P6BVH;QZ6gT^#p2@a54pK0Km;-ASVn}qf6 zHo*BJP!<)?cd5V6?xZ~T{83b1W35N;TwL*}cbY6$!ia+em7A?sXvJ!44ig$7!@Ij%!z>#9~ki;5OKEbwSOFj7qUOts_eEBe04Qk})w zsH$@HgX*g~iXjXQ^rX#ay9`_r(H=o-y-Sr2b1BSj8P=QUZQ3ifrtQqtGjaO>@9{_u zE4MP6I@-Fv8s94$BDV7S)Mvi%q#u++06a%!P&$g156}3;U>3~HjO3v19LnR6Vduv$ z0RU;2D5?{RL!vuaHF`Pc%nOkSPx}uyaE|Leo=lUI3J5st`GG%hm3m)}+k{yFYvl?u zhB=5HqRic6_58d-2G7kY9H|jV&>=tV4>(f(@m{zsP>W_+ZjGCPC6(t-W(!nna#zWo z>4xTR^5L0=e^ST28dw?=- z`x%^&hd>)F=HnU|ptwEmI_*VuPNnJi0bEb(#ZIHB$n2h9SM`;LX6KJ4S%Z= zt9X3GylGuTnWk0_`m}#tc-LXR@mzyfa!}K*ko=a)qjEg=ot_@l%$0k6O-Pq(AV&nB z`3qVY?gDS|MojK)UlwyxHI2+8?OJIiQZc%p0tU$)daQj0mm4Tu#^1RD7GNAV?M)x) z90^FB_`QPYQM}7_VlB+&kzp5@CIHZh7?9TcRKo}qAO?e3&=bDT1qtg z_j@JMcx`I-9X0VJgO$&me_)&KaU{PvByf>bB|Nr}Lv*n4Gs>O~x$qz_iyvvW82J1E z5hDFj(8Bp33xLm^C5&Y(?#VBiEFHUTs+V20xr&q!T2=5{W|^(=8^_8};P99%8NN-L zD0%s4iZ#CXnZYEN6pbvdPCv6x^Z^2hH;=~jodrUz-`ICssCeUYb?Qf?NUE!`xwHU& zADY$v7+a$*+U@S_voHQR;V7VNSx1Qrj^g5-6?lLA$fuL%2u9=zrO7x8mOEFfPx47V z1McA+^8R5r<3<68(MMVKjIwGx+MG=t1O%qmoVzn#LCi->?`p~$so|GLUAho@g!3YV zpFYk}m(bn{*1$6mc#>gesNwx7@rp^iAR67vQ?STA`*@2#i^K29V-N=)*A6W?L*C{b zPrhv$%)A&87hF{wG^0tmY5htrIn`%|av0C6>J*`cpAjdc;$sott8VfX8O9NhNYfwt zn&ng!5%`qaXGC2PuHq=V6rRa#mBmWQMSA1~V|B-=+l8+7YR;?CX4wqkZ=0}iq~ymu zN>cHB-ncsuEcp&0m)f*vaY$qyg2|TS=59WUitDFbm*on2Kp_0 zonE)4_c3z~d^yi43o=nY5xMsU5D{e6mKe!koSor5K(WV`<$6BiI~ZG*O%w&Y)K8+O zyyJ#tvl+AD5=o0nHDMbM!!D^x_9c(xxSvB2js@6`#R_aD5RZhCOmJ7 z`0Y3oU_40d8~3)5$SXq^Q0`h4WHVU-N#y>AVbF_sy|Ayj%6H6R)45 zz&n=!5W8AUG4F}B;N7Sv(Y7S0U4dCzUdHD@*|QHwj?P!MmUKAa8QVtz*M)msXz+l; zGi?%3UiBPEP1!R=hMd4Tmh=SnF z_!&?X2S8Db+7D^(5XEy)6gRaERX|awfTB<-K8u421)qq3{)eIu35WulqYPZH5@Apj zC6{^M?hwT?C<@kuP7P2Lhd@!(XT83$Eee)xQJnt^q96iA@o@qWg(wS3iSC>QMUmNk z%WH=y@KK`hysH6fg*pwO6#yL}H{aHZ8z`-a`4d`^tBbq-NkYifefc>R7x#NxrMdX6 zmH7I4?!KP&c8?8}fu-Ue8<~~$wMUZL}gm3ImT{>q&DBO*TjAC}=FF zL4Y}Je8}27JeKCdYf(@$#Rv%QmVgv#%6+M<9^ji5$iB^qz60+%90!69hFv)A$^}r5 zSz+BPWi(>ky^eY-)H;H=od5|_t8F_KW8P$5I+9wymlBBVfLQlz*!?e;vjMf~W}`%S zEdJ9s+2F-wfGW4ncy5N%dl4 zG&6?@%Q%3s$hfG>G;>zCKOaz+?eq*MO3mg%_0!O5rh0t0La4_^yN5+3z+AbsfY39h z+p;W+c=NF9hrM-1gm@lUQ+$0Zax2u1$PX4povBW>qLfYi^Y;(O`WasqtVU0qc@xyW zK)3K%3>r{iwG^q_cNz@M1;JdCoB*=X!~aS6@EIxwlYrjj3b(nKzH{*)T?3i@dvgF0 zhmwvnsG)S(?};u7p!%lh_|PDDfnl<0zDcG|Vzli!)#mh(LV^mGVg0e7>ylCFQJ>m} zqO>#>SHUzJcQ>rcP26?%K8p5e3!~5!W{bJ8ec~4ek%<9Jrj^StnVH1sL+_an&|IH~ zD&viGnxw@_57J|9p-T*fU&RNrk-f~ zS^!2qZPa_TmYAf7Et zoV;aWL484B3JB~J=N=jfWOf34zP(y(=rW4e>=jPLd1YRDTW!=_#-|Y$HK2HGs03=WuW?wcsRB2o$Wnn6*XX?Pibz^?c5yYRRSkJ%D<= zWN!El%2=CoLR$q+0MNIZS8XibeZX_Z(a9Ah(X-b;^yuR4`Sbk z+xDHJI5V?9U__2@qGddf<*$~_q?Vs}nSoyKH-ILlB8 z;Et#XRS8koy0hb2;D_Fu=e;~$4`xrEC%w6!g}tZtMRC=}1oH6K^kMq*8y3ay+d#ub zCHC_a8=*E(J1CrTAzgyAwh_R>c2_`NCYp26?HoYLKw*G)aV;tM{F(iYP=~WsU^=V- zg%XZNz(Sx96?nwHl?I1shswFwlMjHp$|s-epBf4PeuBIKc(0CKZd+@8u+0yLHxr;n zplb-}X_OG04HJJb1m?aWH#c*(R&xvr)HubO#wQ(X__$1+q4)8H)~At#A&xIC&s6zbG>~(;zY^QG5}S8(Mt*Bv zzWx<`d{6nt1dPflq6JcC-}!Liv3MYt25X;+bD6vv*zUd{9M}(Jz1(E_TtGKo{_zk@l`T98RT?;1 zm|;n^wOmt|CqZrvWpy7*?E{Jj+3Is@y|cF!2Q`<-YTSp;YB3a^@c@WiC;x}thgH); zq#8A}90C`Ba?9#O_H(I?jR386-KVb~i=E4^SnR4?$_P?Y;hqQMV)z@@8lpGVgnL7; zAxXRp*4z)VSHoNf$m*%KW~fe_EJ84mgrxSxz$#04#~v2EW)~HtAQTBT_aB>D8!wQb zgKaIs_SKvy|FEwfh)i=(Waq{336Gf*H%UY&BT&}$0CY+eeV(7K3-QDtN}~;cK3+YN z1TQ8dUd8LSu0VCClHy$g_RZuTfVgSg#M{R}oj6@9A((&fJVHj6($ur{l=8c!qw&ix zklgMA+_w>`%!zsAopJl_e4<+afK#tWwblWagkHUMSx#RPew>`MuQR;OzM8~{Xiu_MkaSEbwJMG1 zs24w#u(A4cAdBY_Id_!Pu{ow!Ir!B!Xz*`?#%E{Ej(BoYaQ?n7G23RDWnEaTria?3 zqn;VrQbnMfH?lCt&0=QI1IVPGwv!~ht78=qxcr{0+q^)oCF7JrMMG<~VK^M;YJgy% zgpR-o}@H@RnQ8ZF^Y3Ce7aT-bB7lIG3+fD+9PvC#T8j4!va&hHXfDJ zpr-lMUefgHKBl6sVA`1M^mw@Gz2@d@RE`qWd~^KfqZ#2@vwSZ)Cv1=cCw{v9E-uef z%AElS&Qb$WF2M@p5=fvQayCbE4!m=E>qXhJ@~M=Xc_E=|LoC@>T2+>s00&Ei^x6jZ zi;qcE8^(U8SVKwr6qlfQkIsv5oHk{9RnmIL*iL_RYIAZ*I{F%4A?$W-19#O*J@!W+ z8zp_z#A!rEt82Vsskc5NZa#VTa{fCoYKakAO%gJ-@3F3#Jul#`$2xZ!e$t-Ix2aHp%O?hms#Wc$c zRfIBUgmt2T@eT@vpYs8hiQ?DV;)Ki1LL1GB&snk^+)C<5q4uMa2lMmq=}--4gv{_& zn`;ygOqsH`_)s6c)`DmOih_Fl0n7YzcN^9HAL2pyDzYs);ABd%iu7mRO}Q38?N7%_ zk+^J(X$dtoU*tTr0;Nl)$L@3j^3W=iL6V1?Hi|vgic=_uQ)4Vm`J-^it)3{pj;;-b z3js{*tU?sx(>xg>{ct`iWggDdF7u;ZcpUgb`HI zIgBd58ux{bhgnE{$yn)KVf~uN)dIy+MQex8jZ-O|m~K4M88#}0TzPR+o_s_h?3(zY ztn3is>rey%-s3X4rCrtwJ&+HH9EaULi3WUnQZgK;rk_ffphKpxH%vfZdJRl^XB6>8 zV)g<+)Uq_`A$-ZXT8sHn$MU@-3(0ne9QIg#J~S1j|mF-Y2m&Dfj85yx3D(0u_z8n z-cv4Avn)voO$InvG6J_8OlC&~wX9E0ZCYkj313_Uq8A9)1;yxV(TJE9QIDew_aC-p zn_ZjiytTOqs%lCbLNPX)d;$y@+(-^So9nLH=oT1C-}*?kc^{fjkatsHTqlKD4{|DO zZTX^JTdg3F2hrw5QR89SS8}L?(31nSRs%uY#|LIW21>(er&RDvwcCAdLWMD(-Gr2E zpeh)@MDT!y!qO3M@#LFf6v>j%^b>@ln#qC+UhsA5eD=wbfzmZ8$#&iS1;m}5x&e%& zoZ^xkO|%=#qoG|PJZv*S5RK#0KDm^w!+IFT(9;jr*ZFPRDkG@ z%Q=)bv!pfXp{$OW4B(1nWTm}Y7xSA@DVkhqTofa05L_GY4{Il&IEn-c9+ymMuVfmg z1qZU+#z_fgO#9&bHof)TC`WF3a|w`;C|0f;xZ|#n7W%>vH;q6rrDz;LJGM+)Ruf3Ea{(&zKOVmAUkXKymxc4IO;r=!aIaH2_Gk~!qXtGu5^OOkvVZ#8|#*UVa|i4+Viel7^?S> zV2|V>&w=M1s}+4~75RM#Wpe$SyH|l~UL}#cS!Q9Q+=&=}?BuZi!C`y4)V{vkv=m_t zTzH)%3q9`~T(sgB3%%KT&V|M5EOrtKLtQt4EReh3{5U|w>I65MdO~qtNED0=gCukv z3EMR6WS6QS5uwe8yr!LyJ+IEOATa4gO5P|C4tXEg@f2V<{dq~}`nEQg>Q-tEyDwfo zT0yw~2!+qh7Rk7_OY9uSr%up&az>sjQsy49SCj@aYt6@^_s?>GIC=$)%=x~*3! zRS=sb@!2ui3M@iT%|aT&p#9c2N<)RJr>B7Y)|jiuokQ}+l9;2a4b79{%BWrij0IY+ zkO<OyJtVz0HYzACRNe3?>Ka%2Q?ij6VJyg=rsG!;?#Z{@04jJk!`IZlWeBSi z*T(C`B{AAkng>cDGA;WU2tNwjCKrZ9+xKPxnWeW@Ynv2T6}X9X@vsgiXKXY~t;^A< za4`qfCU7V$NimY=`%hDQ5FJjbpm|)|&J&X#?6!O5B^W*^fxe`sm>q*gL_ji4*oGL1 z8!X@L@}}USxM$v(CM9lhWPs*;qV8kAO(3pwrlA%a19$fTWVHC)gd6)g#jt3HwyQ>r zt&1&TcilIrg=+T|auL3=zjk*jBVGZXT8T3gDt>B6RwLAKPSKllFn|AkyayS=JYtrR zLk+wH^d_!(_Zgn<8*#vug-TV;#ZE=$EmIr`T$Xe?n7;r9O+F7v0*D0K2h^LU2p(MI^`E-okZ>c&s(KH=UhWT-wox ziB+Cm5BHLE*+*Y8X{cV0Z#mTBu%3{qi|?`Hp-A70h&F<=;Jz+tf!mUYZ|oJ>-}EL? zQ#{${&W+ksTb>O4;9{f0O{bh&ESoN*ywR|JdF&-?E|83w@3Cq>m1f#MTH#e5f*XW8 z2-L!>n+oS}OcZ74X1%AW^$7RPZklG-(EBw$mREIWCRANR$$g1uTkde5>m1~is%I`P zwrk&M@tMlBW-YJ7J2RqzM_1j!LOCm}Hx$;!ywV3eIWral%MnSm>F`d{`zS|f>WO4} zt}XTKt2(eAg5rMK2t)w&;BS%c>u}aK_1wVQpl@`!| z-U!ryTMma!wl%W8+qc*$0pPo2*LIwr+?|Z1J#l$Ep)m?le+&GA7n)DnmUnv!1 z3~sqYK%S7?W}swju@%WeR5s4H77fGV-|7SKr%sbigB!|c>H=j*Dl+0d$(a$=yKk#n zkZ<_GR!lcT_e#vCNSE+L z91Wpcomvo|vPb{X_>LilwvjqcwrZ%u>aj5SiNVg9H;{x>sB(>AW;54=6ki%anse0s?1994 zrYqNnm`~Uwq@L;mGA?QmmeF?vv|+bE9$OnJalrVHt2x9}>%ntrD(Wl`dFkx!O4pV1I8cXoPk6z5k-{KYi;6=5r&6=8Gl%=f1 ze6&y?&MjHuT4(wpnhPJo_9#$zOS}&`B;+C%JU&9Jad|_YPb1_^%;~_@gwVT`9F&B* z3}!DxMX=WtLY$TT!f8Yx?1@*S;o#mopYr9Zu_cXnGzzr(N*-LLVz;}bt-PwkQCo@% zx63S4+qsY8e%w%(*1?+Y5)Gw}z+C9H{ozTDSHm7@bUOJSqoi{FbpPcOTB9{ERkQ+x z$k!72xQ>w1VY7_-K!|C0sGW%xcrq2z-;gm?7;!c&h`(eEiD%jqrRi)U^^vZk{F?0R zyIpZIOeOjmMf5F=*g;ZIac}QOrK=w0g2zM#Jivq)UXf85IQXEhuRvBQ#Wd*Y;?uup<)O z<)giT${9`xZwF^rh;~;8@VimAb`V_J6xgq^mNz~9+9B=six25)E#s0S;fjef+5YQ1 zl`1-OJSS@I1S)g-w2WH!yAI5^zjQclIHR4Z5^dk5cw(SlFxBh&BXL5xu;4YoXEyV` z!mV%zLKv+F6M2V2x+tgKBp6a&(B@&`5eP*9yA!AFwF=S>6Yg!7(N3^j{XihhMnD6> z@s>%hmtuE$b~MhaEIN9q+Q*xaWPi;bRw5HvqA~L9R9qx?;d#=uAW3{huR+PBh}qOh z$w+D2)hBxopED`0h@5!if*^e+;n|y-4pJ#?U}q{=WmQ8zE%|P2pF@l!2g*}{sGt6I zqkl*%Th@rgizWGs_Wqf3D{)`PHxnr3p(y~&P7DKt8X>a`l} zBDe)MLA=46xS=q?k>m){!m|a$A6Q;?oX6a6Xsq7?12onbq+qEK(QfnRn#iI)NedJ!himt=FL1AVUKRHeFEwzog5-{FJ6Y;&us`d+3wBNq zQG8qHnWOd#)j@{LS1wVvPi@e8o zeKEM7DG9l5Ou1<1bX)e#pzy@CpSpG zPpHl3;9KxQ1a-xxpAGLl)&GzygR(4`R-nwp;oxxm7HT-8A_8*|@Um)AUDHyc?LSjLSA18GC}^Bwb~Ui*H8$flgS5P=t0L;O@n z+xx>4)2Vj$@de2Zg|jrPk^b_}6S=Bt#3qRQFRYlwMJqEwp@%fbyV=c?_uXG!9~RP5 ztb+!%e4>$s9x5*e_F_f(8{b$Z4x{6|SZH2Yda97W7V#yv;W_p5E0ZBbD19;7y{i0p?5G~PpY5zv{qDcXv`g369t+)Z5SA8mK8$>B*L;JH9@;dl1{7aq(pWbi^3`I;+2R1p{Bt5r|M|5sc>fQZV22>w{C~keSy9L~o zS(u#RqZ}xfFbDVIgs^02MCn_Px3L7BBANty3pt2L#JE%PA&ScHPM5bH@RMu;G6bqk zZwP3n{NVwQ!KCF`p~JMZ2_6bYCPj!_SI)k;+b$9p{nkHq@$GU8RrS=U*`Rrtp3~Yb2c{eSB{M^*pTdA62mCx~dokXp)b1D|k5QaJTh3Kpz4jm;-DuT4I z^u<@R;xS>z9wIq*(@0GXSKWPO=%k$zho^PlWl>TdigK02qj;9$E7GBq3b&{Q?hz|= zH{Xt=9J(eZ)siR09&lbrU-VFjlVQBuA_Jk$pfByqLfVVjWJL&NsE^3&GWQxnQNj~u zIdf3ynDaDrGK}}TC`XJw2F_U83?fv!-#oGmi=*e1k1RT_Nxe+%eA3@QP~Fdk?LeCo zSf`&C2Ll^-w(Vj9HzyWQ`*;*?dgMrx93ABTr1&ZhXJQv^o!6Pt=T^j5s_jdj%Ge3p zB)=4U5UqS$A;y+Z;gru?d+Vvf=WFS1_IBmhcAIblN$B@IDLi&QPp^&NBpiP)j9u+y z81>v+J>M8h0!vi$_33w#HD8v`g}YcCSA0- zI(Fiw|K>#0&=jPh=}N|vm2BL%WWCeAiYI&m(}P4DDHn5Z9($&P&$HA6uXD_(@{PLAE7sGJ3DdwRg$Vi!=}KLQ{(w(2Tci6&Oo##BTAtQQcds4g|eR;ot!d@J4>hv zMP(w&;GO=)^OH?kh#mEua$Av?Sal`AqOmDghqhN< z^~qvEEF8eSl8ZMyo&dJ&OA}t~FfXY0SCHh=NLKwq0K&A_tZ%OO4s+?aJ zDX2C-APo!to>lj=+ZJ$?CSh?1Ozj-xo;uh6tefHdbAnt6A2;Dq5ogM})5mX*Rwwz7 zOY)KwyZah(jaozepY!p_Db+oxjl6aO8&@>7J=J$$UMOpdWsz7>a*(NPoGq(aze-7D z*T^!ki$n9?zUH2GKWld&`y3gm_yBQ#U2N!WqvUZTEYbMq&)|KnlvlhGA~uhiST;36 zi})KOIPw=1Rm8&m;;3OwO$4NSa1vil-|lq)cF^9E%s9_OhbOMzyVkl$O-uCAHn&6CPoI`OXCG&4*3MNK2(5Q8aHdE<7e*ocGOBYw#?I^rP*kaO68&u@bl zn}R;gmC1U4zoO0T9vM<5EQ4FdK4l-DKE4!ujtyKdap>u zy{o+dccc4Ul*s)@^mMfTAId82*J=<}j`U)@$ro0y9!UP=JN$l%e~d6pJ5*-xP{P|# z))CSQ$Z?Hel}Bunhx3mV3Jlz9x1;60M@4=HB7{7ka1JT~CD~0hA#4s=2u$!x&o0^3 z`Kfi!iH101$)h*~O&!OTX)ZH5i(1P@s$sn*e_rzJ>Ru0qg2eMpg9LIhESX~An!~+T zbe;T{o#U>ZZJ-!N)d@2Lz&ts^V>?LzQ0PVf&`BC++BEe5S<#_-_DJFbfycz=H;aI< z@i=Vu@yalsCjq&(E)7R zt(NMz&_fu$aHZkmZbEx~Kl)jI4NY_$fF zj{Xq45G<3abdE}FtEsN#`9tOC7`GJ9EU!QgWjfw5 zYU*!{A;}<1y0<=F(8xq5F=LY>=8?VWZm<;dO$XP|n_27@RUC*g?h`Kne?o{xK zmt>nz9&`}D^@wZsTzb3h1KT3h9bdIOKxW zKt7~_n7AR#HF?)c%-S0GsRw#u> zGxx2+^A&BX$?bRHrXP`HxBkzt>ztfnsiON$jZ1MhZ zU5szBnnY!@lT(UDSUWkGWztc^$vDM_fcjFxgfqzvMgQa$goxDE$Bo$HAPOA>wRDZ1 zD~(_TX`Ei)+kKmfwYZ)GZe748$U68V(!q!u6#0{C=6PaHNRpm7ix;QjU{n6l{9Ddb zyv)f;PB@$+28jfTVsU3{qz=Jj>EbGqdNmaMFC8BnU3^aHC*n@Lns^CvXMh8K$Nh~` zw!}fm-h-T?h)`!L6NB1)2I9~?d6z_=-w1WqpjFQ`kI<)&pQb!jmiCqepY_IH2J13sWgtPpRUbL`91k% zP5wRp?t^KOC&Yz99-b1bf7V_1R>G86CCIOw3lW5qsiBVIRyic zXQ@188hF_^q4zXbC%L1evF5RuB{8FWS0~2qM$JW#-fpA2mPpVGFDIolBG8OG=vx|H3PeJ=L{lz;=II&Pi2GTZ zba8hbr;c^YWaxefAoB5#KD{?d-M=-#!QpMk>W0Q4?c~Qah6>$!>k%Bu)eCL#Yv~WA zF3(L;yELis$`J^d z?%1jg(@in1R_l1-l~B%|fJD12U!3(G1mM~Z6*9#mwv*3{G}rMu%o`H}SyZWqywrNc zc+a&2#&S9BXQrdAv5tFZ9b-#KcTvMc2|c)K;PREK_wEG6gM z&;Ry7q#ynCy`q;yfx_{#pUR}8$WBBtRn@SFPP#%LIwreT2i>;gEh=m}VRXZpld3Uc zI9o;Ewk0(QXlM0V`IUiKowSBF|>20P|S_IN` zQaG`EY~cJ69$L?3;^K5{iI+SAaD(68PX`+R45oFJz&5XiPFX&Qtl0ixh*W`*W>|EIHLIzTa-NV;QL?SO8xQF`|++f3zh6s12 zst}!6O0yTaBoR>5=e~CA8J!KQWwTbxBJ~M{Zl$`ukZy+!fvI3;$`@EACk;K*mn)1z zc*RO%OX(S`5CQ2Viil}MrBy1lBBJU!!N;+*%`5RjT-2O>yf=Aeu&$k_VrK6lJQv=I zRDvh=#puOKFoqI6-dO6ZI>?hB0@ePAN|jUH0QAkXONAuA!O&iM83?#U^7ER4CoIF$tZ&~$CCW#h$mPQpJfdwKSnf)BK|J84il|_+3Coe>s21r9 z2MoHg-{i8)YE~oT`KxJoSc2O*7h^94JUjXz1l*e9D7T+>dfNY@AJSVQI`8SgRWf3{ zqYC%4C3|vJ-;7%0UFK8@OQAR zpqlnnoKM0HA|RhYBh6+BpQ>j}thQss57(tUcKJvroTANw&^F`g^oNTk2l>;jBdb%9 z)z;ZAL?vsIX0*4pHJ5s;%NY-Nt6OV(FYjUXS=J!itH&xNQ&$J>r0@b2>M3!MEi^nf z?89rXEulU9zO#>=WEhwgG<1zS`n*0ip1uEgxkX8yky0J&32Pzu+y2ws0`^o?`_#qZ z$q!iZS_UMq-c6>FQ?AzaQdE5BUXv6!&T^r<5Ib+V{ehxnn5+~@)l%)J z*Ql$@*YFe%XyWEJrsr1`xMposSMy%be{wVb4zDUygu`>@@f8TqKrdOCPM89gh^?~! zZGw?YwniicR9HhwqpaWURLnyvx&2`z3I}QyrEiiMy-Ds!DT%eNCXq?LNoT84 zzd+*w#cO#N8j18)*pjRjzIJ!cDWqIU_=rYQiGoHjkuXnm3>C1^YT;hgD3PY#;adWQ zeu}LeQ(<8hbgnYvvQm7SRC9l1`hJa^`7`e* zuxjSCr!G6jWA*~LKL)aCuhpBgx01e z{p=aS%oOs20efG~K@?wG>u(mMg*(+vg&uAGh zH$c*14!`In_B`Qht2`PTo_vUNTQv^J5i!x0Q06JmNPdOXP>T5WCBB+i+=~ZMMcYo$ zZ0Lr7hw>lG$_o#{H3rz2T-IWReu0T;Q?j^emkoS_@_70#8gYtNMY zcFCQQ=Q~Gfw!)(z(s-9h^2HHh?P<&MnQ9**Ntd}Bg^lN+!aW`gP{F1c*HE4?d0(ca zcXOwnW!%R^H)z1wOM^3)w6#0^rWqdf0> z+J}{Qq3JA93!4@3nZo}^(|HF{{r>O2WQA~yV~cal?7jEFv2*O1nXT* zvG-nO9y?nKg=FthB)^yU=lA{BA2|29=ks}8kE?kCXDf&y9gUq%4rYvR>wl4JXX7G7 znF<*w zV*{Fpt&d7M$~I^?wtdIvt>WL&j4&D!Z+9Z`b1~Zpx1B1-|G~Lrc(aF13i&C8{KG-C zGsGD`-d1w!UT4@cLbRiw>d;5I08&7pWF~cfrmQY_ zv3pp?dLIlKG{vR!1iw!X-L-erZwlJ)cio+LmxNE%oqgl_QuC`Hl+C5Wp*3)fpOlnPV0QFQCW^=#6D8v2(V z-z-p;19d?*Z;;3f7=8LdmKMCWR~G*3-D#Qa;eAK-==x2eqLn}?2iSe`M;AE}kho2{ z>%vB&?II6A#{Bcj)&9fe%re|3je`Llll!~nK~sLf{0BV{JsSn+u)1~e+pKYddx0LV z#c9sB0LfSGRFC9>rUq=O?PEJp%0UyqE1+1CLD1@IHrH`1RV;p7ihi(9cLjTrS7o1P zg$&SvX#Ah#-RZWEw8`k}P7)=GxPLDN-1yuK!FP}?~G{%hfx+!ltcBqyiFI0#qo{8Q|43}|tC@ZgZQkYh{ z!)@m)ysCl|B<+-4ZQa?Ppu?8xjI;V{$M3uhu&ueI3_t~;E zBVVE4x!VsmCCSmdg-Q_!YC0@rxRCCQS!MwH860aIK@oL!UiahhIUk8D8@%svcCHVe z2JHs@pp=?}B+yUQFKlvpOy&5wH6;kf6b?I9U02;e(MFcg)Vi+R>x($NYxmxNyz_en zMG#$M6uosqe}|d+kZL|G0$r!k84up}sftKbPJeY(!aQ>FzQD`qRIM}mw&c%uTROB~ z|8K++0-WBzg-(n(zyG-ev*uNvqNBYFRwsU-toW0QFhQ&S-SN~g%E<=vqZXq<>GStT z%tQI94>2%OT7-9#%JWy-Q#E6DTvHCL$(`&81V^jXrvY1Tgj#triH8LqK zQmBJ^F1}$QurAN~XQ+|W>H#)p=8=BG;pK&l9tNpFM~Np1uq?FLs=z9k_)QR(zRNiA zpn4zcc^qovku*~e5sBN$yVgRh8ig$p=ysGlgAcIKg>TNJyQLOi@DsgeV>u;!Xp0no z@2YOSErsBFz?t#u&Lp)IRGV_5UvSafDV!nTrJbN(UF67j5j4$$nH(_8xaIMsrbnVxWllzhPBXD|G$syf) zGj!n*-AkB>Lts9hn0US_o3WwoWRVOj1VZ0iPe!(7gP5TGQ&jdK+l}_i;Vc18(Rk$h zN5L{&ox_X<484UUQ%#c0w8s$L#yHdN%S3;W+`Zh07-3onwJr%Mv;G5z!49?2kBpf7 z7?ekn;IrB2AQLj4B6-&kuBxnQm^_C^p)Vp{DiZs5Uf=zK;l1cVoM-IE=XYZJSc__+ zlK;$P&OC`bkN>Q1s6tUnlti)RuO~G?PJ1!s^FxY|HPSR5(g*1)38Z+8_m>bY>IQZZ%NpLEGkwI(;S*j4v-UBadx@__9C8x$`j#N_wfKI4L`fp zcmUsJArFbSA9tZbf;~uz4gJJ7{e89dNG7+MFq-b~@=N_kYh*@ENNLdHltmsU-R`Oh zStMa5Wst@7H~zkZW7Ws%xB{gEKnDe^zqR_}P!U5;cmcDrb5BWF{}bBzG83K~#Gs!* z)f_=8jd36%$yqc_X87{D5y_16lNs8BERcqvn$1;7^}Q#gs$fwL>?~y)0k}-oj3ypt zd;B%S@)Y5-inkpT7|V|H(P{UZMbNm!*9EFRzr`vpzOJXknU}Jn07JCpRbrRKfmC& zVXBs$FI^=%icGA79J54Hh}mL}?RRG(uX*|n8ekPmctM9)}-Y7}GeIw=YQQj_0TrK)fjnAs!v&G9elHG>Iavne=F+ENcTHN1>a? z@!zPFyPt4y@ciQPxD1e3WQ*#X;S2O~qDXqx^RY0B@Tyw}SXGL9_G*@dzJmoXu5z@I z?+4wVgnCt6qopPJ=3sAPf(g#*65nWBu&)}>R9q-mql%I6OC30Y^M<3?tC#FXubd`D zjN`qqMC#TOI1aV`Vg17i-19rqbpC6BY@DspfA_a7g2R(eX) zD!=l-eRL*|ih>)2P%aEqh;}+!Z=(7i(4LUFVX_@q_xD7-AimnTs~OshYsISK?XhyU0)_!3uQcC zJZbr&u4p(Y(!=727M}Xcs}uWU5NkEF$mD}l-8RF0=DFSux|4+0cW?4@M+B;iNI(s9 zk*s8{uES(eF03|O+KF%-3K%CICvs5Mq_C&^Axt3Td-fi~^ocM$(t04^`qb+w@-KXX zUaXRP>IH}o#OdPm@8`PhE3KbzaS~{eyc*rY)tHC(2__qsaY0o;-@k3gT7!M3F!mI= z@UcpVV{~U@=5e*}gkE^<4_lj|bt9udm#V037`dMU)?&8fmkXM+m&z|^nNKgg!8 z9*y~`g1CyPp952P#(=m>(Br>jKJvd~p2Ux4ARezMBZiMEj@P^+qmUIGNQ__j{#C#N z$5~YPYg1SmJ=FUfxPPqcA-5Ze(LhF&t|-Eb2TH7eA~WxDWS?>fzseVt#Yg^27!*^D z8*i~6IT#bb$$vHx+rVc1C-Y|gvU~?oG+<*f!(sk|$^OtAmnD1y2cPpem1s8Gkghp^$Adzam)2=acyg2jl`)!yvXa(D6mh$-zLXPz%2 zXr>P9(`SI+vMMCW8@n$?wM!!I&WJA8)iJj99(3p+V?dR%l$O8~m~dN=D8 z&#FD&F=OJYGsTaiiXbQ3{crF9$*qb9`3xcad=g-Mv=gy^)mUKV{h|a%3ip%t*pD@U zEaYnq{6UZVw`LKy zyXNEd;kC@V?!eKmNA21K*61T2NYg?{B9WgRHuD!y>;b zNhv-vo9`NrwfD2sBEO2Ydqg&LtM4TYrh|airD@-XN##p$>5uSwcpDsro<9Fp%6+ zONcU}nD&#<3g#{-%H!bu)N*-oC1kGaHQcLwM=yaDol(@qb$&qScK}{X>l(mHOh6c_ zh9pt-iyBmYTCSBrX67|qC_*q~)=g#Y#{qUPIblpwstdTxTOuZ(G5&xRS<@YVhO_nT zEG}8hyX7gSauvs-HM>>P+npP0?g~F$mH?xge-1#}kP9s_t|4eIb=>Ev+L8QK+*fei z#sB1u6EFbf@VfQ2l^IOcA?1!*3=;nt-7~JDh(RK$ce+n&%MJ9lZI3@_%BfJL6aUCVo$#V{oiLd(AUX!e zJTk^MoEGVR3YCfAAG)x=_ZS4hkMH+k2gW2Ytav?k{g7*r0}U38&xkTXyO>7UuvfEA zhyi$uFIyX37^B)Jn(p!mR6;ey(O!K>JC^%M)s6xP)K!6;07Zz~cPTphA#blOwI$9! zR6|m2`++`+)lUL@2l};32!eM>m1T>Yvj$PNUq)?5e}+%nQE64Gn(y9YV@mW5h5wjG zHW6Q4>%2r5qB}IGMN7&OiKs=m&DLugTk=_m_bv;S0w#`>f?@4|$hNf;g@5+tU;7`k zwxSS^TtQXH*iemY31L$=nK};Dt@*w5=ldj1>M=$I*9OPd+Q7Npc86}U3!S-$88uM1 zEtQ&jKYOwsF2}8Eh(oE`C5~VSw`Z;2R8;7TOq9ga$yp>vq`zvnXRZGVl(yaMbY}Mtt z7gfNV%~HSxIyOENK%E_DRgUA)$L~M6Y!8K>7B9>-0<~Y&1XP~6VV`uQq=pLh+kJJm z;KYuq?jXRRY&~UN>(s$(@?E2a zhmW4d-KbKJu8_QFjIE7*WF)N*nfMT7>ebac5eSni+o;V8xJ+wap7Hk3p9ju&2AjbQu~Y!PWl;sS*y_3QS1;E(~6Zn4jJ z@)D7d#h-Lt?aLSj)2Of_W-*t@)D-{yI#wy<=&c^iU#Iz%Py%nCES)%VZ8D9*Rwz5~BlO5jm!w^>HSb zP>crFr|AqRdjefs7O-U!f+)#qr7x`-kH}3)P_w?p1$e*TVD5{z9b-v8QHx{v_3)3| zfcVhgwtUWQnQg8~@69s`dGb$0s?z#QeH`n#XY4)q%E|A2pQ*L(?U8=B(JwopB-P+~jtpaMM+z3pTuk1eC?>K1Z@_s> z=xde3=*%Q-0yomXOB4K1tKKBeWG&qE|4b@@^47f|{3&-!Nr_xQj0{(*wmcC9 zN3U{WsPaXIcnOU;!AG==%BLgTsJwvXpyG!i$C2L^=kxiA-_$}yAi79KYB6H>-Nbj_ zXTv1LuT+|X`4p>;zOMZ9*I%Y%L)YLmbLk2F0+w^u{(}TKQBM!X(czNG%n3xi<$*{K zyr9cR7#8Pigxj&jAc<5Omsd)d{qmj~-z;0Qb_M{n1%ZOl%U{Oe7Gy8$( zoiFtg+H^%2eA&-Fe8`pVM11=@{sM{nr6SWi14$&-im9v(Aen-0_uZw=Nk`nJbc7h} zT>`Gl1cFH=ci5X0w)uW%iGSvX{fwSr^VMFG-8WyMgi>kyJi|YKDfQq-9Aa+vEtP`F zfqOEYpURy6_?D^5RCul1)VB~ekUwE;^qo$CY$K2)b)zC@ z+oYb~X{J4Gu=z)PFa(IhhG5yS$nBz+~GNA3s6QD;|TPTT0XM51p|Yiy0{;=k4%}xCV(6wqw@1aV6*?Tec!0$F?SV zj#Vk_>AP|RJHsn}WvXpo*Jq6OVexJ(!uAua`0c^i1<|ZdVv^|RC>?i1uW%e^jDeUK<7xc~Mn8Jd8>JCi@~Kr2HgrdDJ* z5z}Zz0*(4A#6Oi30Hktq+Zy%r9fSpFi^}qJXn!##yZhd6pi9|oGJ9b}v1JLy9|x@* zDYOZ1syT`~_O${OqmJKuj;H>URP%a8Tfs18Xx?ulF{bIGDoyU>?kY}Cy4cvhkOR4Ur+*k zMIiLiZR)czsfbDTLl9eJB~U+fa@?Bn}Koe*rEaoGde9zWf zk^ybhpeAm-L(?X64vhYXN!Rh)4J0&)Yr)I_)~USydWz|az0i%7@Ggy8?wXVrXv%9R zr>$*ZmlFh_S%HTwb**F4FAa)Rve|Od_VFq;7)ysCjL#1k2wo>5b0NpJQOu*7XNPW!>uJ~#-lpOblOVB0k@p{Nii3-CQii{7 z^B-(kJRZ_lhxid4A>reG)B(B^oT!`hOoJWbRqMzh=!D+CO)dI088E0uS zL(?kmJydgF|E@mwx+V<%qiZu$REEJRE`j}dJ!{a!%e;KyZJEFSP-#7Yw-Bvj0k}yNdZ%s;=TPqL2FtrT#n9AwE ztVl=!T$}>y)UEZg`d9HAus5)~C0yUUOI>B-mAuJ`t*fj6r_ZArVN$eXpfzt5*qCiF z`U5z)?D=^>O2EVjcVh(Sj9ve`qflbs{X~(sU(@nP6E=Ob zf)Dy%d%>G+W(*7b`Y+AnwQ8O@$RJz#d&c8`f)#p%xp-xL7+L(nZD(>EYQ&?T;qn6Ch-_`9mEVit1U9YZ!WkqH!jn@vU$#~ z)M}D|lY-$LSp4}i(w{u=JDey=3dDEvT)RJ=AZzZoy?(ZLT80B&NMDA+x43c3i*;$^uI@__~ zlGlE2Oqw?Q(@g34i-}bpokaC#sT*`}R4T2peQ@ln5?)!`ahD^O^mm8TB5|Lw#p!k| z0n74|2)3X#v_Fd&LMi3MJjx^0YXeY|X@IcUaWrAo_{EN>$d1NdzXasu!IbSdNMBqb zu14^8WdTHePA}RE62yw+G% ze7jR8&{7SAc}$4nCR-BMaZg3R@IF0*~+YYOcL5-^~f6I~69;1{=yIv?v^1Rd# z3GQ*!S!Yz9fx*ZdY_~OCZSRFzm=u52V45rVS6N>8(D3^$3M&X=k^Xsw%&ku&I1Yi}Q8M^4cR3Y>^l!>$#34$xBwF0#!lW&J+&bhq%d~J`wk~ z7n+7g(!nLSUD%Sx8fiMAKhXd;6 zuu|>Xmx)2u9K4-s1|#sCa{D#J*0=3&v>B@aDm~#4&RstJweU$2)QoX_ND6kI1%MsI zaze~$u8K{fYQoPb-p4zG?d&6fPJO=DpXPW!yM=aWIn*_Td;l5gClsypg-ncFXt}9R zGFR1)kndyMQnEOv5f}*WJo^3h7?2&)^ihA4BvreoeZx54E&%TAkSy&?I2b7pvCXJSgh?*F7bDYH|eZ4?s)Oyu4kxJj4Qg)5R6ffxmfHxOKWifBJ!knZqk$jzB;nU=S!2=C2 z-Jn;rLcD`;=i}t0B!In4zO_*v(M%;5XMPCb)nxr9DIm6HIy0hd8!pJLK_<9WG3OvR z?&o{Nw5$VHd0~=fRV}M=#W<(u%W`6LbsY0&@^OD=k1+MDb}Vtdrkr^b+Zz$y^qDnIxHkz~^6C+6xumCtyfk?9oTy)nB0^VAk5;(|(pu8;`< z?cgg5j(5m7Ryn|PWbh<;++1j+pw?93pIRprdL<5V>3}tOg%I1P<(4scJ+SzgToB zsjT-ZJ&2=VHSTn1>otpVSkQjaNT~Onb$G39HXnb>jGNOe<{&( zG9zQG>YVF$k-v7)^N-(`{gNh9Ixvt{)G`(mFsQX7qLZxJocwY3VgMSUXze}3Ud$Xx zlsVz5w`j%6X_8YizDo1@URvbkAQR05hX98iWq;Qsjb5>ntZX6{wVCs4rKg7Q?CIKS z_DYTpPz)N~2+f+qKoT_`ybo&Px6T-6!yEleQ#Xc9f{TB;i`vE9q{MC9OqHf2sLO5Z zJ7RMcVV1$OAIMo($(6NXb_r3LuUbWjwn3~OQmYQvD*oGvTB;DP_h%MlD9#lx%N(Q* z@s91KsyI+q)KGar-s4iWa|o3O<=8MpT%*trgrglLOm`qSob0-fiaO&U+v1~*i6PpH zX=@OPzZV<*`MGpr;>=)cNKhSza(=vtsW zMCoLnCk`&vA+c9`hK0xDNbUcp!B-OD)HHJ<_}%)%9$VIW_-wa+TI*-LmHvG8%rz_j zI1@w0rO7(CLsLjzj(bzE>AVblBe*f2@Jwgw+k%1qSLl+v`B?TqH2IN%TbxZSnx(@v zU^_G}K_hrg)L?5mKX)$Ax@*O(iPOX?aZE+SZW3477^Qtsp$V!QU#k~(a?FfJn(|^^ z4e8|*O!f8x-{{nFAT89R&~2Uf;}i>TE<~*3WrR80{3@fNbV!j|1o{agSed9vkjMk* zn|u>*S2!rI`k&nm{SAZ!*&EB5Z`$;N{O-He4;mIlFc*24`!32r-JYCvrQ}fDburlL z@j+0+rUBfv8RYRyUgxRIo1f%dk=lE@-8lcux>cymf$z_YYA^OO+a+0UUkb7t25EnD zjLrO-;!n@FH{|k8I=G|GSv_34bCQeT>#f}%Q6s+ST%>kcElq{DizIswMiE7-T1{~I zlr%gF=_6;{RL$MSkR3-wMvXQdeN|9Pv-@=cp{Uc{s0D2)y>Rdb$Q89EF5+$<_$b|z z_AIAE#~_QZ|X+ztUT1(5dAJkL23V+sM2%$rayD z!ztv%zdvvWp4<|6sVCw(u~ESRtvYC5|5%?n5(#TKQ}Yk^6+S}~5~sqF%oCFiNOF`p zdS=S;OPJ1F)PrDaD1Ka>2kh)pK2oaEF7CS-w*ri^Ez{|i-nmoEp3)sqf%I4~{jV9$ z)gn@@$kGup8Q_~*s@=b|@(A(npIyMT9`a|tfRTLQzW%!8VZNIm*c_-G*y#SIl|F>- z2)`fy9RZW?pJfz+s#JC4NYA0T7IMvNTz zNc5PAc_|RdWK;^ON`knU{L!UOooQUP6i`CBiHU%t)qU03kdwSUdcWVT{F54aZ+|ip zyf$TSMv8KsIGMZ4Z9}zyq+AG4=ZkaxEV`rjAt;7>zV%^E(qg`g6WrHN4%iZ-)`!pP z&Cl24%4#)MK>1CmqJ~EIlc-k>;>5&epKl4MJi@;(x^J$d))zv6`tJJ6YQwaENAsq> zYI(XdseC4fZ3z336M((=|L;xp3d}w-Pz%w)fi%KM9gWhU(j$EyXd7i>czh)0>O1e5 zT(oq*SnB6?7i(y~165Et*r4atF=A(MTFsw;DT(ab4@kXrRAO6N#a&1B5 zE3CEwUgeIAmL-d8$Zjm#BGf3v*kUmaz_v#-%)2h68JO5#0o+zg@tf79uwjFIgtvG7 z7$**xYKs7Yh5L~jyi?eIyU5FjOTg=km>oD;Jd>$b)zS@WpBp$Cis!P@u`N^9EE8sZ z=56w>SiBT`O96Pt9ikl64OEDFA+J~jEfsFDI|5-x@$q*O44;tdyLccLwyAiy zwU9}otB;pn^fD|zW_*s=fLp}3CD+Bow?1i#ZDa0p%kgM3Q&(fCbt!3Sm3O=6#qR1k z|Kw#ToxsEyz)*U^Xg^R~9pr{C1Ug#ZaCV^zNb*T# z7&b^zvy~vj@}Ang&RBM|B_BU1%md(s0MRW$WZbl@|LB|V(z^LbXH$*Za?P0fHSY^O z(Bt(1Wmixdjlx2>~&yg;o&cnl&agh0QR1X-;g*t?eHu zgr~RJ@7ybO=MF@CCzl+2G+=UIpXe3Jla(bndL|H%5W14WEY4VLK&#>Sq%!?{-IY~g z=|s0T-#t07%++01kRw%vR0=&K^U1$rsbehE1Rd>cp6SpXtN8yf zCc98_q?B=9lAPVlC}v5&wN}Xy`;^m3Nh{3KZEi33 zH=9NB5>t^azn2UCZ58krw@7`c;uDtNTAI;9u_=>uMWmRi-x^=)29V6Lcev9(s7Yv- zEmg=qK&`3`ON;aD4NppqihYoiBGEhv(WW_H_cl=w6BD-%KJMoz3_5lgJt(S^hGvL= z{7RjJB9$Q`)+Ho8jMI=Z<&JeDF3f8l$}|6%e>qbkuFm9V_$4O>jS&@h$?&e>i|dFk zlm&BMsU&FaM)z|7&4!KJ+Tuy@ucrauroLfKwV-Lt172~FGh6QOXaFT4of0x*~K4ZSBE0v=t zg}A>uHMMtdDr<5U>kH%PoMsGHdhtE{cgvhhQv+v7?EdblT$P;ED7Cg~q7Hm`WK^XZ zF7S0x?IY=2p$NyZQfb`jIUfbMn4HnnGiKL?#c2{6`p9TZclketxC=SGpEUikz1JBD zB}a`QGZ0(zA27YucsUC{|BDlZ9Jp8xIoYz4r&MwDo1$U9a^hr_>=oDi^aM1hd#iB9 zntvQS>n&?ZJcWdjgp4YAI(Zu`ws%3C4yrIX?vQCk#N}jjcf7K`kXY9(;juqlttYtB zJ(IaC7?~{n71-T(+uVW8Fm_}2LJW8{4A1&j4Mc}O@tstKdR&SPzdBj?0{ghWZ<{*r zb~4&#rl|b<6(?~xK%)2%Dh5{Fa(WgtViDIo)=CDTVN^Gh(f?gu3f7SIp18 z*)yMHrXGWdZ9H+M_uA91CwPFwyp6N*v6YtMSfLgubp@ZT)f0VzGi_Y~?u9vgzidDB z#yEhSR8&OUge+IGLnP;@K@h(Jh*E}?zu7HFG~F*E_$!q82#JDG;*;7$lRm!&ynQRI zeKBxYduhhoRRTBtMkU}fp+s0Y)-B+qr|aFHS6UnNJ!tg(2w2C*4^t?dX5#}w9C~yNEO6!=#(gi>j>%}F<{KF7qE|Ir z;?T0=`ZcXL)a_4^w7z}Xa#7Q#$Xb9G?k`leYflPFX?C|OvEkqY-ujry3g0y=1C~b~ ztZ=XxqcS15_jd?9=U6&cG7C*zZN9l~@?YY{kJ~MeQ8#F281icOHsZis(;!Jya-v+! z?(uc<*(zWV_Vix~y>Mh|WqtMT$<-N)erKPD@%gsNFL#HwOACv+c1_h-M*L-4PU2a@kk4u+>>vyiY$VUzWlgb5?!q3$ygmA z5HsK%(EA6?9|~w}EPn}ZsR4wQMN@lhyTTPAk^-)(7Q7$OeMOC@bJFch{3$}|Orgn) zh1YLYlGQ&9sFL=QfV*gdb7vNxTJeb-a9Rsy!O6Q#4S^oPzr7^g=uBY?t8Tj zY|iT~)o+<+Zk_;+6BVtYi}ropnFV*@Qp_fRS2E}Mz2T>g{79hi`%|4D0HPLSu-^or z(SfL|28@RK6)<%T5VM42gw-b<+%<2Wa-Ol=GV>E+KFX%#S+BE$*wJ3nBAl! z<&|*OH>@w(Of>lF!IOD0DE;}si7C(mE0KuqqnJI4QG4+k)52%-^JN#oK*+*-9A@$ z)3%Nog_{!v0W!}fAhWU%>T1n3H>zx26vY{*d!Ou(jW{{l!DYD-0MKPJhKD(*%Q1fO z*SRawYfxUqOJn(5Nk|-&d|PRE5%iKRn!J$Yhdq6P?JpmhhNYf0TUzj^q7QC;>$FXA z%TU)o$>}8d%gt1L>Pgm{QIEm!{4>xLQV(xguZ8LP&*Td_EP^{S(r*@bmJ<_mmf z$*MVC!u-Z(p}rmdAnV1T%(6akBjK1$h9XXR_l8u1A<^A){JTT3vkQTPo$EYSf%3B2 zLBPrT(Yf|+)`Ml^db3Qb%KwrMh%@9sF#mL(B+Id*jaJHV`n%Ed?_-#QWgb7Bblz9> zUt}x%m-WLy-Fy+0&H|pJf%ODXzg5S5nhRtRx%dzgaS}f3e!x>K75i8ESuSUonkV`@ zi-?e#{tp%*rHw$!*j&cI@8LV-?0%6ENV6_Ho`_ezPSGibJO^1+JZ_PvPbdFbYkKaX zG*JF}atb5?6Py&|UpOlnJ}G4v*Ts@+#9FW!>FFE52LGwe*?W0|db%VX8PcEa@sbiEczV8&w2 z?#zpS@^OeIT+YX%>Wdf&#H16e%SZGXjI*gOzu3|*Rz>wi|Fd;T!>1D*Lx&Pwdlj2>sEm@g>YJ3F1-R5dG8GqB zKT!E`Co2hSX7IXv9EkZFLIg4&t#^SWqZXZ*Rh0N_YRUU zWQ{`1E-sev)YTV$^5$h>{~lhRIP1k3>W4I%1-0w@?>X`ecx`OL{m$B(tY|}hs8)I%v+D~4akSdk>!S!cTNb+!`qaY)}S%YTFyaZ`?a4Uwaw4^ zzP%G)RUBlMQ3~5O*oygk1OYM6kJ8%sI{tT4^uGkvkps2t_z)fQU{wOwLPW^lkTdGR z^SIsL7Ac%J0i*NX|IQE#PZ-9ItZ-GA%oT*8i_=vC_w~bBB$SfUMTTSa?aMV*{-cJE zB^|}3z}~;iQPdTwGq|WU4Q>?`A9#jjXAvcuR;^L>MT_cl_>FoylynUQg>r&DzD+H; zBSL}nj*N@g_rHNNt9>RXFb3^5FDAdOFAK1n&w&lS9xV}f{+vQ9ney&Bo7K8_GH`j0 zL>J_#XX0qI9)upWlhP64Kvl)_qpZc9bZQnOA6=@osgg$^y)X@Xr$Ov8%P6nC+udN- z3er={W&5QHt1FwLycRF~DeG@1S}%0lfF?+O!mYpuchRBb37-xOfpv84Ojz_c#5^Ig zAkVT!)WXcQsQ}{F0y_{rG=BKKs|M3i`zP;Xsz3e19`r7Q9nazae zMn)dY1GsfN{HoAJ7k3Za$R-x0E2lNjGzEO#-a_yr;MVa=AT;?0R2ClZr&BBErwDpD zX%ttm9KePQH&YM#FONrNt9)t^^GQ{|>r}!IU8fEUBedm359c}`&9)2Zqvrw>0p42+5DXOByvvd%crid ztk}jldtQ>`44~6-5~nCoH?8YeR_*baHJJANmME+dvDaMtv>U4{leh;2qwuOuj-Z%8 z#FGzyUCorp8~vl!ux$~UiVcjMGBa@~u~MI@`WkyObEe(+t$x)LBr18TDNtTy5>d#0 zEl#~>6hEUEEWPh_YQ$51milfyJ1;17Ery}_7r;XBoeJcjeLwY$_G$jl+YE@}s+frI zN%q1bRxBbZ|E$7^TIgOhuZ#Q33~>Mmb~V;F_n?SjrPfMO|aKoXR)tb zT?4SfAqOeJ%JR3NL$P()l)Ecy^>fYVnZUORu+YB-W3e>dzxy5Cg0}5t9};Ta;@+w5 z$q6)aCE4#3?9}c7bo&0%GXT--GxSM*!oi6m#G6-4TmX}ip}hua;0NaPtLwOdxkpJo z$1l&FUK(@k{qMtY$Xp|GwyF5o*u)FmORCNc4Bgg5Do%Z6C_vYz@o1Q+N~H$Zz--*J z+n0#Om=_=+f)T?!(1~%2vcEr(@t>zQ)+EUSUrwP71l(02LYek`n%eDGz1-E&i|UUG1l>O_e3tdeXiSy&Qv;!uS9*T619F{@vp`#w?R zv%DM#&wH$MhIyU{yti{Z)a+PYbY+mICy+9f+6MNMhNvHj$nJEXX~h!T;@XLyU(Yfg+K2yr`#I1gAP3XGT{rP-3-X!K8h1s?;_mVO{Ipx*Xm4@pV4mbM=u z!5Ay0K+%ahX%p`6<*nQS7w~UggFy|P1i*ZqULbrmJIRU(U57q2(~O8ei9aQ8csxS+ zsJn9@TC(&ZtcFRU`v1lrH+Zhvac=oXH6d4pm%CW`pRu2+*?%}s=8^n zXYYSop%43(MLP}0@U6ahhtT}l_x4_ixE$~1#94zJ-YmA$yt^7WdGWU$W=_9K#hT>z zNI6$6MN&0II-bQjjur(=6V!xdCef;@siRW29+$XuBScC4kj5w&lO`jj^eR;>8y84_ zHgo(yp`hgED(}qd{Hp89>Z)VqD(g${#ZpN1S%q8Wwd};%xB1W|5<-~YOkTXS46-R$ z)?1V<1E2spc+Pf<$^F8-e8xDRR*%YaH5>@d*O3-ai(pWOny8mA!qxMW;I`|>zejyT ziM8D898-t9%Int_v#U6#f$%H+cmKW{cN=pmYxsll8yPMVNT2D2@q#j)akq(2zT_@P z;|*8>dsT@%MIjdC?BfTrDA$_PC$@=1NI{_P|8|7iiJYRl3I!$$a;-yE3y z3{vv#dBcj1F)EQ5_qW_`;HucBjf?W`nBML;D);VnElA;~VDH-l;ti}Yq*FEf2KfQL zA}kn#Z|3S>YxJW4a& zG=tx?=3Phg_4!vlI&y7we+c3f_^pk`mR|j}Y%)s~oD8kCiA4gz65Z2*fs93-KLAmR zz69sccn@6SO!Z(R>=u}&p=@JWNbUn1`*vljFq9-7veEU^97csIO0V~Q8GndMq@C=( z+JJHMQC0imEL6wuzGY`R`IK6n=vM4T+G!5MM&t86V_%J-rZrvak-?Op)eZi z2jA`GwpPyIqrL}YGtDXWi9BDnp2~f}CVDXPET6BM@Q^s$#n0`BYt+>XPU+nKDD0;Y zMYz7=$5m6NyxTNB$ABm0i?UY%rs`KWt`6@mFObSyEM@(xL2Vf2>z033$=;_F1+A%h zA64~LjW+lW7fy|1hXFj?TxyDIMtfeYirn@zPn|*KdqYkMrMgp%yWRe+N=lziyN#{> z1jhz2y9t9>)=m@nx_+-3h|i`472gCHt+nKnD0=}Z4PAS4qfcQ*Pt-kYKH(eu5kHGi z73CPkTR(>7jQ?m(dtGvy$uuZjH|;C;Wg$^#(@2Ont+GcIC;|Hu!aGE_3V^wyT9nHN z%1kDVg+L$SJYliioks$^!(6?MFyYPy1dV7Twk996R`cI>C|Qho^kuTUX1~h5e^_Q{+%o^&-`y85mie@k zqpFGP>~=Ffaew>iu@Qmpj@^%YK+?0%fnS)tHOuosrhtZ-qsP2_fWP4h$XQ(&aUg@d9l2ZH{vWQY4oqm)XOT!a+(>$EBt+Pxj&fe3jpLzOylftJ<;a>` zu2HK)fQHi*=fR^o5y~&I&IsB^hC+KY8dVt=tjS{Ce)JvKkV^DtbzkkvvZ$kD&`%CQFRURM6Ip$7?O5K|_zYl_)(lCLJLuD_}7vNN+ z_z1JH17*hUGWyNvdpPPEA%vL#$#VOv3U!6D?{jH8A$Tt+>(&;l+V|V$ZZlw03?Dq* zph>JC8*<5L7j>_*50^^Q<{Q$j&aaXk_a(#%rS-}4k9zkYYPADW8;{C zmu4l97{E23_6IqE{OG$gq-*20I{+s5wbwak?$$Vq2$%~0JGu_Bu{{P@E{*BHvwn^} z!x900;_pq)_yc>JVIx3Y9MpAX*#xsefM_|su;%1c*|=06c`EzcKurb%$`Or7?IoWH zIpU$Kvbqke6a9yT2Tg<-n`t+xi$?dy-5oIV7c9vVH{>-(fBOZ(YG<}wXsj6VV3Omp zt1MEZxhag*z@PLk3u(<~jFJ({4n>}=-{yG@FuAV}fSrm^^1z;<>06R5Iol%fr$1Iv z@iik@clo_@Hk0`oUfCXyqUq!YWJ9{uzWAw908C9o+-Pq5@{zU6STD*tO7y@7^`*)R zUC1fZm-{l#Z0gK!AmdtcCq2Z(G~%g+K}G}JbQ=~)n)q=&e8&nujW&iZ!O$%EtjjHb{{jhMs0x# z^&U<+C>N(lVv+(b)uh_EH|5y>_9$MO0gofu6qyIan70;JVghSfvo@#Vc6R%r)GM})tMa#ujJ;D(n{M?DnOxNE@v;hw(%7E6Oc!m>>g?|>Eh>lF76<*>); z@eT)B#2h-+rC=m*KIn`y`rC6C2bujt!=UYQ-iC{LWr@I;fV6x|aCV;>p1q2EJ6X?W z?#hk*F4n#&>9qi%FUH|ySd3Xb_}GIq&zWh&GH8FQl)0tA6>k9+>ePCMG3RgO7Hiz; z4+Tb@Z!qF*@k`O!n}Il2S7VCuH1l^p{RW~?Dz6(y%I<5man}|jvqnvV$J(j@WB2!x z5^L#c=&{zSxm*~K?+j>8BK1O{WWN}28i#;4{K^cld;Vv6Tuerr8v}~?rS1As;I`#g zQBq=HWLlR;&C2I=={#r%`pk}E5_%|A_nBkM`@2O;&6G}bgawcx!TV4_gTMXM{2Eo5 ze+LidN-4GIP#9vL{F|Ub?tIpk_xrmp`{|9OYZe)7PK80e12E0XzGHVxP9AX;0nEm) zyb4bqx2ek4PurvxSxed+KmT|3{4+K){tO#Rhs?vKT)ilMdKz0ihn<~q`H;v2Vo<8; z+PRLeYFTa_eTKW8=HtwDM3vozzRqk1)=pIH&ja7F2%9tNcd_K(lq!9UUTb{q7RqAv z^ju(UqdZAazj(VrsR0OnZ{lk|9d8Obz1k||FH!C3duW7SEPDI%M*c~a5E%_tqLaKL zGsr}OkAuqTxUT4M_F^H7VnY2F#Rl^N2+vjZ?m%i&4A1-Fx+2kJ5R$p4m!WlBo%?kX zOJ+mFJ!ie1!b>eqa+n$r_Ftar?K!e=m#LNnGHN0 zQ%zdW>F@$C0@1n8{_6r#S>+BBxhpwg@%e2XeiMP&aTE2})tI>WGPJ56c*ES-H@uV} z;60_iKTt#(J@xtl%pxky!@n>jg?NkL!6#KBEd2a986o2*0EFK7U+l$qJVIx3(f5ow z^`RT9PqsCJIcCzA-ipbt>~96uI=H*;|E#C5{E(a%jHXnp365X*^_@c=OD;Oi_LLDAhlMfnGx5*!ULl zPy&Or5ht~aTb~Dvp^kI073I zx>(;@i#Au2L0i@zH(jnJk<>{A9KfusfT0yF&1684ph7rLT-z)GN8XQT0LGQXpp_y4 zy*qS&R{0Rft74CP6k&Zp>Fx|TRX^LsX5;OW0EvXpunCe}Lr!ryQn_F9+>eXmUdK%g zyA7V%iTz4B@W-zy*ej!7@O@eysvgOPDM#CNm@BGW7-?&dQgRub4zkcEUFkMUw&8+( z(!bDBO=}@qT3eXT3+?c*bLU+^zwg`*Q{$NU(Y@(hG!hSyj+bl`&bwnn1Jb# zRIB;%AH-g$FP(8UfxXR+|7kswAyNIN19LHdR>{$~p*_4js!+)hbkHk0u`yN@`e$Lq zeIHPeeXgf0xK*HO(BU+I+kQFx`lk^)Sk>KKHVB(MBs+R1le$=-(7)$cq1?unnFGVd z1W{gn<84~hyDkCSU<3BNasU%IO>$r(LATvE8=ffK8B;KaIm-T-8>LFev5PfGiPmC$ zuH<{8#mG2Dk1BX%WMZ8-bULo}IVX;FYYQ6$a54eN=;kows%uift(>s%qnV=HMCW`l z#qC4IN3ji(f4%e`^@t_E8S;@~(RmO&^vl&|t_C^;pht3#C3-ogi7RbFvxVbztkM8v;zZE$)0T=mN!RJe)BV$MP57P zu>InV2yrANY!f&=g9RCp`rYC3cD>EaJ{(R9WU36hMY0%x?p#WeDT4WB+;MF<ylQG;}#I+RcCDAXqlFo0loS6a!vSwI19~C&CxElOr^ep-81PC+L?OOcw zzORAHKz$Rs1LQYV4jGX+R?eu`z7@r#%~#V99+OzX5}nxc()6_K{`0hVD<$9q>P;@- zakDd|vS$PtaUp^wFYKH}T{gx_dE=W|q%ydH(BT6EYn@t=b(!K1@zX3S$KEu=Nbv=> zIzfkY&4Q0Bs1}<_H-;0>&A^m>*}~m^%eS*DwnRZPbH-wg+HdPX>_=c1+vkf~T^1Z$ zgQG*K;oq{|ngv+fG{~COocMw2-oX78V@v!wOt;a!QlG6ql}Q4(tN6BC?nY_%c#xl8 zmr2SEa~G;K#^hH@Y0bVbeT7NaP!Nws^Sv#f2MT&GC4kr3yi~JyXijQHLN5_@t$B#fBeStdnD5`D!bh=J8ufNgOZ*M7m-Be949UlSk)}V| zz%q`pJ4_XRyxae^t;P?RR-jps=8i1TOHi-X4G9hU9#7q9l8_06vx?{Sm`M7J=Gq;r z^)U#Exr;+N|GCX;I-(ruuEf*yL=Z)32E@IxefjugX%oel3jtgC#%v^?)KK|Y7xq1- z`3?H5_-Fb&Cqe58z@2;a#ba)Fjw~KT%;itnXw;c*J&MgQV{--q2#pff7L-L(7jA^& z=0W1Pi7wccqiS0=r$ z$H(-u_=JbG=0nrZ@rZhyXQY85;QLGY(vUPYZAPuMNEU!et6c8@gijSv{6=j3-3t5b z0N#U(?6-!j)30QyYoAGoP(L}oF9dk=JZX`RNA(YGnYdm1bEIexr@i==%}YjeAK0U@ z5rGADnV|S;n!?varK#^BhoEG~R+1CH+lXh9G1AYQg!U&*&p+(cNsM zIIGN=t^fSLD`3HMQPqX;0dN6$vhYIHPe$S?uzudXPq+p0d7oQ$b<$)TPb7Bc7x>GD zXovO#rlHR*siuI6!YzP!zC2)3;2#iQD8TNs;62Ez;r^<>%!x2pmn}MYA4p_%z1?5= z>z2*1e}IDh@W<9*`X50M*s>A3RO*X0N3Go zVu==4BziDANo^!}xO;nQ9oWm3V2N9=-WUJUqpH zHYTn}Y-+e;_G#^0Nxgh>P470)s8uA7=83;%X3?rtoxNT1QjU}4ia`d5w}(jrtIJHY z&rL>xQmnB>(fu0@3Pku78{~#$T3yZ9*L?LsAy0Z(sqFVA(B_Li;-c@9ndvJX+agASeJCOb)+TsEp&dX_rW`NTB>Gj5A8-V}e!Kv3L^5vPt6$|=*rzF9 z(03Emt&`jkr%n?uREVSjzx?*u3D=eN=ds4gLo7Gu;LWS0dkfnRPpn+cT|PGqd?>70 zj4jX8Qo;3(TWBaB>jYZJMRLE@@)p1qh}wsijM*-MK%t%Xqgrs*Dzc`*B|AkRW_X*NgR{o9`(N+hql%&Cf~;&?u__rAZcnZA2)DwW1EryL~n_j3Kks;eOH z<8O~#^XL<(SqUlB4Q&KUU0Q)Uknr78e@>oHZCpqf@AMx73CQTKli<}DYCaeO8v?Ev z&-N{FdY9Nq5`$Dy55X_tJYFQy#87yL?yxyNeYp{^NeyhH&6!)KrV93Z*hHCUa{sPI z3Hud1Ctp##2B$Y&^@L*sFr0&&Hkk`WsB(>;1G>dy#`pJgOq8Y6Hdl!*xCYKJLzg-O zf!=J3v#kM>g1)+hV}wz$_X?Ki2xa+4IMSDS()MWr#_pMUVq;3!ci69|-0*A+e*1Wk ziA&k)CIp&<0QYOC=<5ZgT*k2iC|)e|j_Nwpd!G?m6e4-cmmF{7$G#7JR$t={_kHO8q-FeR>2;J_K zrjZvQUVKHl5m;*|YQf(0vXH911^?IdngPG=07Wsr|=ei?*AnQKkYV5;XiAaW& z`b;p%I@Q@wa$M1}^9I_(F3^r+;f7!DWP?Afg$88c!`#+FuSo*iu4B>`<4o=K_mPpH zyLjisuLATV+sebIGJb|c2umzx1SSW?#1!BAIj+HP;cZ3~Y)KVegdZQ9neSBszm$aF zBeKh-w9;7Gc}&`QWKlFpdUk^vpe4nnI|nZ!T)(*@ErG>ONT7sfD@k_`F#R&xM@2@2 zcZemVm-Usr!EvCUccP%vOCtK_RyiWp-kTBiR+<*$03d5T(HJ1w8CIpE?;R`)75g}{73i()Nqp9AyV@(t8I2@){T#5nyqm5HyIE4&kEv$i0}*?)rrUjgGrQEg^rn%)Y)QV+0!5!c}jEhzv1AA z7%~XWS)}GU#JYN1>`~`#TS@ybGbY==V4x-YyL1xzTu}Lb?J>4v#!P2A*{izkcd&+y!Y+QN$wJVqh0+lOlt`w|kZEwVJO4O2!haJP)&e;~D^QyOr~ z;G}M?P!6IN_>vYz{{6n?%Obm*N8@hajgayx#e zS@Pf;Z|kq3yAi9v1;wNLDDa@V`k>^;qHjLMoY1z9hf*MoxBxrpHd%@RnzBW=B96EP zaeFpHEzN_=L$tFGv@ATjS~LKCL=w2xwK+I995y5G1UcHWP2B||OrQH{2`?v2$J?kz zxTaY;-^n%Y^<8iKg$#I`>m_F}0UX*n2exvl=JM5*KS!>##mK zx<(Jf{IbZhewX*)Gc7k|8I!t83fYZMpjUo%@M5%rOX6$l#E7_Nfc!uib|2QkBuA0} z+bTM4!v@yq$teP%xwwt;=;ceZvtWeW#$|kJLdlhwi;>9&X1+p7IG|6hRyg3och;D# z*4CQ;8UnGsNlT}}i&J}5GXT|weSTg1v-|_74lWmIm9AMIG@&Kt=BtK^vn@`Pwx}$j z?h-7u*B|_lFU`JQT{Cx|`C`=l5pGm#th5e9fCvw|oZ?3Fc2nX{oc!y{=##APUlhF% zC-x8}I}#8Io*Mh4-w(V_zJ&b!Ob6Z|RjSyymX~JpXU<>+>O&DiFis&MzLYm}20^ef z|CYM>-E9UqcQ}}WSQ4Ovk`Xl~)t+x{IsT%SS`I@sW zk2boOhP&y*GV=9Kvs-$(x+kn`gDFiS={%0E^JN3T^$kV+orrMfHzpCsbUQq)432j2uCg0MiQ=dM+R1=1mBfdm2^}r z(U${4oRXx8x50kvmc|}zUQ=sa0j2M7%E zdJQ7D%OcWs0L-mx$6(KfWNMeXmR@@Alzn_NewTs00W3B9!I@_$Z{6tbvdLNJ$NfzO2o7>YS z`Kpp@ubq}`vSHq;H0>Q$R90^E%A6`d293udmR_~gH7vUDi4?D|Vcqdt>Mw)$6!ojl zqF@;w%|GnmY9DHMcZl${b5reveFQcuHDi};qmJIuI=o(O(`^ez-N2K_otOd90$(h6 zb`xu)zC!1y<$U=2#>|~72??-}+I&BM6;PlFNu_+z$T*~3#VaQkh{b!_gM`pbetN(4 z!ytOB7s~DQupUo(vlnqf+FyGW9rfXhUU^h`B+CQkq{@X1*12h#(fCx_%yo~t zrHWuVvMdi!3H?HF+q!LFJ1_u4Pif zd3|4!%QF*`K0c=j)$WIoNQ$w_a&y=>vr5+;T0>S>=r3%W_tS}-gQNa!O}d#5lly$t z&GIj-iO%VvZj($#6-SXx9@#Khi~Y}ry(#adlMgI}emz}UfzbPqo)s2rt5lXlU+S@6 zf?hhGyTE@PCv5gy*$wm45tx6e^~;sN(HBS^;D7Wz5l$Qv={3Uu8{h0Gx)%Mt6Y!xf zUv5PQZ<7`KADIuYvn+hr<_J$TKCA$#& zIW>PFrg>&*@51cRD-1wGu92Of@+8`PXvL{I7y2FHV@4w!J(SYJYUj>IvebwSWbj|~ z+K^;b6WtNhrbGN6F2Gr{T#;CjhVLfC{@_)|Js@a!5b4VDbU&H6b>AhlLkh3;^ChFh z#lk71yN33s*s3Yzl9^2c`v9TWc~A{VC6PCk_uxim;TJ@H(^(p0wfz;$ajcG2*a;oX zk|sK8O&!Zsg2oa+ZCk7*T}2Ezj;%GlM@p%Slqm`utC}-%>xGU)L1D@o%3o4a3wV7w*D>^-9zG(Ix=g?B537C2UiK0=*9VIFY$T|J4#WQa z(TJEZ88Yc9Pq7|z8Ru|X?XsIOuIE{>BCUoiing;U`TS#*F{ryMs36H>Lq^7bF?>Hl z`E_Q{0TVyqb?YiU+(Yx?Dlmm% zGcuXDEC3CVCzA=>qw`vk+Rfbep!n3FqRRVXi)0iRt zBb6PT9~`*MJjetpY4KS-szQC0vr{5^B{9mr(utDB7ThS)Tt?7Sm^-Q2dNDCuuE3B6 zdJQ{M=}r4-y|sFo-%oP(hivuux$QfzG*nU;{UPTAnqC^ITc!#!o&ntEpwZYUN15?r zu*T*`Hp%vokrT%geC)L?cM-@_HF;2%knsfK4J)$B`!1F1NKxsiIpt{8n$&;{1Sp{z zQ@h(3dn)5k8KyF3aInZ%2mBEXV~aF7tk|AJk20kV`TadQF8C2*1|mZRL{eDujPP(O zZbF#}5UyH5OK2m_n|RJ5Y63J{{1ii}xCch|+jvO50JWO@<3~?KzB%kN;FQRF*JV29 zt~{_|p=D6}z4K-dv7EacHeNIx8%e!pk4nCCB_qsuq_|c)%!pHI2ZCmoe?gWy*?tj< zrJaCRHW!-Cs)8MA%Xhk#vss_9M(+B6P$|S?bnD0?xTSj2fpzy#H^G%qcb2EBk`>H0 z>z=^FA47M?&{LRzuC7`8;N-54n^adin{AfLYg>OQF=FHqKxMcz3qAR&J!F_osmw7V z_wS}G5PymwDqB8(Pa2CN)mj^BsT;a!nJ>XfX7kgSk!L-SPE1u`!(T%}pEM2=-<&(` zc_-Mu6-8WQ2mM2SMypc%h-5q}16JP`*-V}CB;}^-EN6)IFdqa4sdU>)fy`+7%0Et6Mc~oG z&V?Y`2kWpbj@=!PE#Z=L4zQT^%nq8O*GGN6;6ES zAE^oqy5V^Cs=({9@8gscWW$5BEaA4RBj7m5`_^jd4zKr+CE32TB=r+wVqShpl4NXt z2!ZZ5re6v2MUJhyCTv!}0z=}=m^WXMoobu@3_|y!!&!AXjE0I7>VY_!_BR5H0NSiC zBqr4ewTLBbcP`;OJvqJdtU=cd()ZrS@D#aRtb~P0@R!|pA~a?2#(b@ZIjr7=^2oIq5FQ z=b-*14)1lI@hMyHJ*sgCm8Lm5$X3w96(TIUnc!-`$gp9ISdiX|e>3xTXLV?Lt2D^= zVPcNBp%Rt5UvC(_sG%@*m=v%gG?ty<{*0_C681{czzvzh3LN{xHG>}Kv^Z?|5;e`N zKJ&mBUmYyj<_I+pkjx1iTsrz1{j{x>YTEB4vh}WZ`hl@qHsk04bc?|bCtEjHwM5mX zlI?HnXXnXxV_VwJ5Ce)ErIY2772%M+HK=zGy0EKje&l7u-leqF2-Q>JyX6nJf`2{a{|6rDDtUpO#A}y5gx@+LIcmNv8t`ZOWTeX0C#V z5Lr>J9Y4473r=TO!30v&BQ9W%zK;h5z@X^Z4LIFD*F}~LZ*5m2&Sb8&VY|1vk%hg+ z>o}3N3>j|^r<}Yn?uBx;GN!z19P{G`{+l@!qJKtcb$QkA946?|_rcFenVVq>o9=(I zfLB8vF+v6xYaFQ=(0Pc1L%~Dns7sdqSWB4JL{m0C>RvKDDdxnN&kX_Df9l;-)9v&z z6H}hs`UD-prcWU}&T`%Tsnf={^4`fFeDFf|iH@8aBP@ky(!_?OYn)DkFq=M-R;bC6 zr?jH?{_jlN4at5p(s|Az2i;!u&&^y9KGfT*y-9l%2W}ij)whUmn4wF@+f`?~iBeb4 zHa5n`!bqZ#dPbqITL31TcQl^meB_pn{t&svQ}Qtlqin3E_eeL@D04gUS^Oq?EQ)uW zQtg`2ciWAb)}ASKghhhQxw1b`q1Dy6*9WF z)lmuMAp7+YID>Z|cHEpJ$>b4mBe;R)+WzUt>Q1jUr>uTT7mIwINK$0={O3^763}0I zKSX&_thi{uD(27RDD|<_6&1#uVL5NKBIKKMXtj~q*f&Z|G1X&@#ZuCh!oh3W; zqxj6SD-VRVBF&PZNq??Pl)8M__`eOFK(9AMK(!0IK~m*?b#Kq;U&ni(`1DpqX67x5 z14AaxxFO$%)G)sUxWN^VVyIG7Jj-*R_^Ar^J<6XZeTR^EttH@;8ONF^3>T)(+?z`+#F$h_FsH&Fh`ulf#mP?mPD*@A0J|N=y#S7Go(`M2qj(1f$?UWv} z)7kWSwQ|b0F^W@kaFTJ`Q8n@?>_1MkwLEbL5P?7^dJsIOI>p{ z&eMptL0d`(QJLMQ@r_VxO0{SwndK6Ox&XpUrLqkXZGyGl2hlOX{*9qCeUFkZkRQ0L zxW=C~BspC0;&S_I8z^EfFzGscvAht;_@b4n((mRA)hC|jVm^fHWnLD-_q}wmjHV>% zXTlxmwl4s+_mkz>n#@Xm#HkuswYt|Y zM0}FGFLU`bihYf>f4YVi5?`Bj!^47PfAa|{n=VagejouSHSKbBx8Fw_oxa8cG`iG< zYwspsvcyoy#gmwATRv&qr^<_GD>IsitZDx>$nq)z z*yB>bI7tynr4Gp8%OV^P# zMeOVbx~0pS0Tlw8S-u&TPq|QX&qH-ue7sDgOR%he#2H^e=MNcX(563W?{Sd~mC~G~ zDj?YEioiN}i1SoRb+jJcupO6G60Ire4T#%j3JHa||kJ#4QaWk&NZR;Q|XGa~zE z@A&z}{L2A>4J`9#T_o~8KI-Cffm4oTt_j!h^~>a%Q+f!z_*wnx@tV|YUZ1TBe> z5a<%ZF2!{uGP(>$`hNC`0^*U7*qep;SB}Pw+hm?$WR7Y50LJ8`u9BXW@(|a&U;OR> zz5&I1>W;He3&u!WA__k+zhS5GB-HtfK|UwSnQYBjI|0;iOxDCn4vuHl>cBJKF+Q{K6-*1t`mOM}wx*aUTK zt+`8588Atv&^hwaLc49VMwqtMH~nkB$JItAzh3|k9i|taqe^EIlV}tDy_|F8Kk6sN z=>io6bljQZ8#us|VI1V{COkDcCYR1bo355=iUWCJJa@5x5~bBp8&Tvi(krRkQ zuZF#}g}EOC!iy@O{A0gu;AS&AmWrc>S*8F;7MjJO&p>mLp_q!)po6dj{JzW8GQ)OtuP_Mqe6-x!93 zpMP>~>1O8KMjKm1=XHF}`N*<5un5Ub`^Cxez{WQgYN&coC$0jf2lGK$Cb9IPrPl1D zdx?xs37OfTC8|YQ2ska1$s`2+m!9HC(<--z{bOCo=8dfw`6{Xnf-4_OPEob~OW#DV zu7m0bI^lXu3N>4wiTr@_W3yojS8ti9fo=tH z*ByZerH#%bDK)RU8PX}%`AnI-ZGx%G1fdBftiGZxH;i*i$*}JxFrNrtrd;#hV?c7* zLcsIieLw>SjzqU;cNN5o-=JB75)ZLCQxMWCJ~6(Qg~|L!xzQ&>x1jdrgoHPEc)Da{ zkPxRdyXT{af;g)0y=#*MxPS1sH6vWreitP+l}02iG{9?BGT@@8T%deMvhBQlof&Im zY6bArud|UClluylka=4L!RK@iP#Tso^S>~%x)i{VWPoZxRGh73l(L5L^pVl~mP0@% zFrZj)%I8g9kt<%HWP9gg;6s2-)KIrVY4Ydeg~@t_N%UEA5-1mxB4}Q}WIsvkkT=!} zg!3d4=@6#l(DU`m9C#Pq7D-o=ACV0Uy-8fW8m4o}%@QEG2D)GD!H2;9Yee!f1x4ze zE~QNVTE(pt%`9_eJ(w2eAPY|`(Qu{+QPL?0Uxzs$86|j@L}9V87)(NPq+rC~ni8t) z)p2|9j}a=7k^MRhGn!cDYnYkuAfY$oUnq{TR$-_}Z90oAA~)*t$?Kuhio$m3%Ah#u zbV*3T9P}>EL4c?Ty6`?Pb^gO|t=ow;118q#tRP~i+)|H;K-2Dl?p37fIoC7y;Lq+5 zK?Z?0oS{3F6FW@BGRhuV}^O>vO!g`xbU+?Xr8{Sp3VTrp8oNNUW`wKIeTHTv$G- zTF`2&hE(Y4$}ZS}N!1Rh#)@q$pR$VsD#@yq&DLqm!&4~|)xu=8US3<5wxh8_w77L$ z$w2|FyVG$B%s)8@{mSkBhChjIwCkh0uO?I`+l*lSdrM16@w< zy6g-7xbQo*kS%3Q#A31YgCCW%#ROCCtJ@z7ElaGupQOtDy(}VbLX!M()Gcx+pCF^- z7a|;Qa6WUFdW(69p*;+}0LW7E*CA;X*FIx~<%q(`&(0M~2IJ$W=bd8SLFTHkAS~hi zLmWfG;S$hzu@fwwm28HwxvM>wRA}9~O0g*kk?3c5=uGs$%n8q|{$oE>1+(h;*tTBr z?|0X5vlnu7;|gyy5Yv2$jCOs!sNIT2P9EMh*0tWHAJEr%>|{JGnMIyO2UOB0GXB-f z7yPfXLCJTq0Nz7?u0P_wczX$%zw2I4%KJQSg zOkPqWdw*H^ouF;8oG@MO>&}-Fl4J@}NJ&}wKJ^qNWEG@Z(7kB&6c0p8lubWG8sn7_ zYU-KL?3JJ>UZ*9B3*kKe%kwGj_RF(NF?R8TG{I#3>|ruYZw0m9qISWZ`-D0&X9f#h z`CwbZvS%ThLT?hD{@G73QcZoBj=OHstRy;IyjSw?DjT>sY22_osQysr+?|NDbazA9 z0147%7)y6VaBg^&F7rNSEw_o}SVAr+NX}^K6CIWor#|khd5Vg5?MsiMjC_xX$5;x9 z!an6p^3>YQWDrHi=3C=rXFIPu6BC!u89p4h?Gr1KVdE@bhWQ=V={tc0q&)~WI~ zRIk0sO^=c9+wmG2f#QZJ0Bh_{rI8ea{9509|B$+#Hw*9xoU z?*$4`k@`6S9P2+@z=YV9D>l&%{M-}i(%72xs99%jP*AC}$E^wVDe^A;c-MLMW?o2ne|AE|#k>ebTf*~U5V_Eq419=( zs5Rj)i|L3~-^hSrPpl?D!LxJ;0jwmPv8e&d_sO-G0p)z9ULJ|sI$vBT*pY|?tph(R zdhmzEono9uNK9>3A^5)6!S=|zO8l9Rpq1f}V zmgN8HJIEuNz*cF-X0fM9sBmezwq)o}XN6J354Cz_7@KU8CGvym9h0XspN(@B`MZ=x zY>vQ>l|$J(RQ0N;Vs79EFt73!+2xBR1YVg_SWfWae~l(H8D~k{T=!doI7m983=3{U zGm$IV@_5pjqIj6E#Kpu?Bz+?3`)MUtZl1oZ#uR7g&nsPe6>Zi1h6o%QUK>5zcB^#h z?i2)a8`yBuqX0x#YovXMoAxdqOan85lxavBkH;0HsFrdSv?6oc(lbylfk$&fR2haE z7rh75IIQsNoIb~kFKdY{85F7QIY0VkTfpLNEB2bQ=Kv1#%3J8z_&53fWu-OpN=B0z z*b#I*)+8Rq$^B8hG=CJQpV_P2?f)&>qV#BTA8PXp@r3 zj>$J_m3fOiKU0F=%rp-?uE;pzW8g+Hlh-5G2Yw$o7DxbyST7@X-ghCDb<50+hvsf> z(%PCU=d~okR*Uv#ct@RY4@ z;)iyx3ZLpOADwWnRz02M&To@wzuH}MUIQ9(vHL_5YDcgHHku?@%l#E<;#$uDfbu{% zrvEKZK~XMuH+hjMGG{75USjbHsqx2_A!k!}tK#$z znbu5YF45A%N+h(V37Ho-YXWRE1?;`-PM)`D@BLQ(BDUaK=l-+*5Q+;d z^lDOUJ4FJ62-tvF?qV~&ymacM9_z76Djq}Ay7Y2a=IH)geaK*1TQOmwUiTX|WVQD1E+kn@Hz3)pBzT z|4$)E=|eV_g5b@glG^6U6uKve%1aSjewm2jX_(Z@4{qNbrLm=Cu*VtxORKOdu9|3X z?w#WO55wIra=M`E3m-2>TnOGbBxLkoYLS))`YJYDVHV(XUA<((WsUCyBtr)1JEr)9 zPI@AQ_>boIDShQnt?FLzn!D^#D7b+B}i|ywgSFHOv*UCfu^BW9PuP9bBeM7qlI5NV@ z#|+qqA?bb0VZjM6?|n-hO;=SZEDy;p3*!dHVTvmWE*IuaQbr6jb-jr8<&KucEq6H= zC0tt4v(ogy4#JXE;leA;T`YGts2mX>Uc_Ff?9sOGfBPr2s=!}aKSc(fsYTeqIHTIS zd4Z7?Ca8JG5;%zL^r&=q@47t#_MqGTmy?kVA1nd^08$)SKuX8=WEN{lXF_CZ2mjjC zY^@i5$^sg~g)cryA|iz1MO#!{@LDMyP+f^2qSy&oHSC}eRjMoU=%Cjc`mamThhuxL zW|XF<$dQE7*%T^TT{u$NgQtAsn!)#n0{i2Vhp0R}Ad$6fMvLqRvcskd?B zH%=aMzQ; z{o2F}*o>JekBm->I^auyeAOKOYSibQFNussyslj6VE&E$i7>X7@4y1HS0VpScKSd# zx{s33=rLW_Nr(~~{BOMS{Rv#De#B`p3gslW66^z3K{(NpnCy+(x&92IdW?;(NW6FM zIvjcb9jb!DPYC8nDkybpCxeLDI7H8pIn@#lozoHcFwuqTWtS41u9AekY@9&ch9a5R zpgf;;lO}f5DqDBT$q7)l0?E^W=I-!-7J~U}P)K{I<uVMl9%3CVN%j&~swMZZ^U}S1Nc(V{fO*43j)_0upr!yEJ_9OwZ|A zYBGw2)PZ;7@a!++9NjoHM>7=b0`^FeRcQC34N$l|vc(4S;2=Yw`f5!jhHx&z;Ti&7p_g0=g3Zf2q9A#(XY5F!=Dx;Jz%}&hnuYCK}AHWYv z-+Xz;Xs+l9eA+eD-A)2D0f;dT*_`K#U&%g;Ps(4`0n#+S=W|hw>Y5-YQz%n4C~*6p zg1!Aoi$VvjXM>V1fvcWZU)!As{Dk2~-T2NON=r4Eg29!6cWTk*)66E%k>`i(bJ+=w zzf5jJqE-H8ZE04h#LO!vl-G(9t|D4gv>;N)uQ4h8Bo*XzTS?P=iBBA=+ioJao=2}^ znZw62D6J0TVUNUb_e^)*o_OY%8=d)c)J8$z7qO&0TS?Dyh-B&IXu0z|rwG z5hzqPPJs15gA0*8w&E#jW>xc6p=_2&m^ATKF2T)4{rSPi-&<)TK{Og>c$^g$>o@OL-8fV%UAXI$@ z>{BP+Ak5ql70W)j{RnWsAu5u}S5pXvVr=5oNQq{JA3I(YNarAKVJa9~!{K{5m^~IL zd_ZrlxJ5!h?*zRYrOP4(4+m<9@D(e#`g%(Y#qplVfYu61{R0E0uBcBGinKt@Vf%Q% z5AHE`b(i}?|GWnIMug|vj!|gIM%|;fv2u_&))22Z+1l6|jqUe7eUeRTZ=DYcy@qDRE}_ zXtjTl=Kxu4-2k<7kQ5UYDo3Qcd%1b>p~NJFLA6vXWq;fLT1t^mXzz%o)0-{Xy$#$4 zjL&{4q9A=>f|JF8*R=O)?{br=M=#k&5rg<)roL&K=`Oj!S%<+}Qr&?i_A*r~*{!ni za`+;%!lodpYf};=GaUQntl(I%0vSF!0mY4i$?NLr(Is_qmM08N?mmYV?#-q>PUtjX zRage9)_*I6ADmwT))aXptv99JyUHr+Gw@7p^9!PV;O!Qr5@y4kgAA4DYl(xa_ZGvwV0 z?;L@mQYCb&VrP*mKoa8Xnn9*;QDT9|QBaKV3!gW&Wz_(A7#Gwp3;G~lr63V*O_^a_(QJDV0v%9=&r89b;<>odn{_> zvty!KPoWnIp6D?oBTRiVd@t@KZ`~*S_yWNCTl~h9sT+(e12)EG+BU9v*I?tl$IleS z$zy0x`)802t66u~%7%k9qxR8!bpPh@AZV=?Fr?(Ovho zNjcT8eVS4~!0r7?C1!7OX?8O*C{*-+UvCg_%6$$ZIsqkg_JH5MWMd zlw^BLe*W$z;kUoXCIJYONeLpBMBC0sSpEAXrhbw+t^H!Jio5w}@lLUAn`*4Yi0o0C zZE>{|=|@BeYm0ZvF`2!05IrKFF{Fwd>Fn!JdH+uSaxt=`VeqJ|L(Hs3Z|f5kVaR5- zLt;rS-M55LWmyu|Xy<%J?;&R(;fK1AKuG+7gw+1do^N76DBu6T0Tk9r zE~~vM2?ohQIg0T+p9~11l|Pv?KQw4}G`x#@{NxOd5fy(0^SCV&3y^_R<2PZ=v)FOj znd8qy6ByP`fgroaGr;WRwREAOu|-3(UC1iobI#-DR^O`7;BlF>mTdArL0@PAge1hyPwXuGk82#kSDZZy2*_Uk7eNLbxrSySpd@7D>f zMQ6gakauev9EDLx_miOV@br4q;G|i&y0Hg{R?%d34Wfqe#KwCk2mv~1cXm^zxiK0R z0kfa6>}8fQL8ur)zGkcPf>B?wth&5lD2$K~s00xp1ceXP@AaB;3x~>P@8KZS$h9>%5fs^PXQ@f}MsuukQFctb6f7sQao(4V{ z`1L~QpM82>ybVUImjAnm`}X@xzBkh#knKIP`}gF}aJEqzk-x;nBH4CW)_&G`Cw+F1tb6WAhddkJ<5Mqj|y|(+9t_2uyAoZ5Viq?*oubl zRA!p}i{;dDj_5?L$>Q(uaY3PyNSM+NXBX0T2Gy#ffo67#^ zW1u=BmA_H;%M$$rxWy5u|9AE!bdq8#X>erWM{T^`M>v=}YL3Rp`Xv$Y2u zH0!I3Uxdeyc}1$;7ldA3u6p7|(+~mYKP+-PrI%u6j$srntCu2~Mq;8YAAJ~I8y|7! zyR-qbW%ZI@;ddWq?HZq)P$b^bCmK`jk-<6^0PD8X6Z@m9YlRLvc)e6Ov3G^1ipnf$ zu4tszN)sr?GO$(~Fn^3lb$R9HU_2F<`GELO0LA8O2sY8;rhL3AwK%=`;O(Ixo4h+E z{Ug*fK&nigHZy#dl~}kF#P3Wve71=7$GDSyzIQ$l7*b!!7nJ_r?_OeYgLVJW+P;KN z6L9#fr#dS)tK39$jo@SP%`Dr*V%ioG36tj5D=jcF?Zy(;AEd`76Vayqe|?>MJk)6yz(>ux6Oza+ zM#)PqFN)8&H3m~!m3?b{WKmIG&9Egaid>f5XIzq2OS!etWLGZ9B>TF&BcfD87nc}I zu{7g;o%cLHm+iAYpVvR*_Ic)a&htFyoaf9r-={7B0&|5sd&V@(xu-?r8@LFPt8?kB zxtU5whReygidkY5j+1PqOYO)lc>^tcx#_+p8qbtIWO+uW9a)Y)okk3S#8j#8BWg=WjK-&2?&E%&1e4Wjqm2~K1mV6f`h z*LsP5XEh55oe;v{&tst5l9Ec=DNri zM*(=m$ysR1DMNlbEJvSit%c9NvNTJo4}#lZ6Ne-}s&W4fc~;>0N`XqVq;6xTKPDcx zQAi6CoK89wuPO97qL(lC&>I9t#Z~>9Nlvzmhoc>}TNnR6@GMadPpe zSDGXiy1I&EuS|P2Jw6~NoKTC76xnyJm-?;s`A^r@NgP@ye}p!LWTHTqUO%? zKVTL8U;qy1`?()X)r#C-so@;|&{zn&D=y>~c1Gk(fYrV|QZMIuW?U!vy8x6}vE zocl~<>O}(NoEsp}z7+_fl_LVk?>9}_QkU)Yb43vEtmJoLa9<)mCfbJVPyU+SV3L{( zbc_5>x8guP^h7_IWcr5|m-of%W{5U}n>`xqT%LXC$$T4abZlvK?0}W*tZMO})c!c! zM#+r97HzA^yN9+IC#?xZM?x)GK2<~MFJ-(tWd2ht$C1|#k`=R~pf2gYzQzJ6o~#sq z?@m!k>D=zN?fU{p{jbcwYcM+j&=@7|-ElWdo8DI97_|$^x0z6QS6L24BGbLG!Lcw+ z$Sv~R$0$kfRjMomb0q@T`1I2I3a@$DZ!KHI!UluF?)Zn^ z__LO+)V|}o5A1as^S8!r4?=hJsQ+^VGp}s-5G&3>Av>nP;+t3%NW-RZ4|awUNQYrMcnbP$}(q7FgR)HS_CgG-$0Qlp$ab zy$$J$(>`$GIH!HpVKr_-JNL<@3`-}FL|R6MHw&$?oYaFgK;y}HO9ZBzn@Eq!dk1;v zfjthK#u_t;6lv-CkF8pj@ienH+b#vjK3vsze*)6?*yHAGZ7{U>?Vjh77{4`~z8OBF z2V{ZG-+T85ig_iAN}o!gU*-}TEDf3lFLu?9&@jvV678{B>T+n|g=eT$*(XZw>GX`^ z96L@s`bpe-*kFTJGIaPHGOF^l_zZL#ll@LtG}`juy&xF*9=ZKq#-JFsd3@+N<7iaf zJ6{3fNeXR)hCb#nBKV8yJ3gu^hC zxOxjRrj;mCFHmg*haqq1YY7)b6u5jsw{Jk#cB$~e;(`p>YM&BF6|%^F2z64n=Z#ky zry3xA`??CDVQkss#iHd&I8P{5#*VNpTZClQp=CNjFhdvYN=Zafgrf3A=CA(|53uBR zhAuU1_0S7UXQ5C+?xQQv84f@pq%OhiRFLC?I&6pu70}nPd46y$wgZIe;n4yVAM;B; z3&w!#q}k=_eeI|#fE&&S@2(yxjT&>Ix6Z)FA!W$c@ttks^8JC(X0X!aJZtkg1b;>i zRn5vp1fx$lo@E{XdFxN0%5kv>;3qRD5t#?!Q_2vFN+B{F$As2^XnDrtV4aFjrs79r zUKBw-yoyC>XE7ck9~j-a-LLrmBj2-7oa2x77qbAUJ62uoEY8ZVHP-~S1mN|ov#}{N zBYZ}n6o5T>q<0{T7mFwHas;zEObC_kl~1%gUVonfMK`4^LRWf zc$R6!*5*HoXvXtYgNj!7d)X;9=i=n4wM7FoM7?p!%3y!J z7?Mz^DcY4dvJ%}br{9;Ci!fR)Qpv&T>qb;GLi@JfkMhIv<9zuKA!sE`3jfz){fLQ* zC=GLRuU0h{Tz&CgAfPQ0@T#|(&flIM!W2~3eJe23+z*5pD`cB5VL_;(}vii5)T z&ho&77qh*)(SZ;4P)ff|@=qP?{=X`>`9 z3Jp<7Q$u`Tr|$dnxw}8#??1nPevgO8yVHBT=5;-<=k>f^ne1@NAeYfDc6N4yXjCHC z&aMyA&dz?GQ$KLW?Ah`S{9~WQrQq!jRC~7B*|{|uNPL6JB2^^D+xf!@zkm6|AaYHT z!5>cahrvWz?bJAhNTwI5lBTNT4d51duF}LQq>A{s-|xU6F!&S*VhRir2|@eAaR|t- z%TzQ5BK-ZnNEWaDt3l*c2xuTMMxl<=n3KTI@JMihLcnb}9{d6iP>A0@Ehxl9a0jQ= zCdS9aix~>gI~fT_Plcnv?LY=KlEw6g5y0<6MM6CIhY~MI(AYj9$n_c(xI>0Qp;JNA zzxw2fq$0iIA5GY15^oU6e$T>cjZm@_ENzlVz(K;3m=ZRQ{Co7Kczu#WqyBrcQ;}2Q zzaJQ^+W6mh93bkh2qpe7JPkpjf#o6-1z3(r1Ab7c5y?r= z1Pd%lYZNBObG1CIj9|c1VxlbqJkk))mPbSr*&18|EP|uZ3G~qsDhphSg%}7i(K5aw zIYw<&(2!6`f}ARsi6Y1-0T~fNBt^i96qZb?k2WVjv=S>MiOfQ12{4h217{GVQ8*2h z5e-w22to!2BA^Ks@)$XXLZ``PW-dpdq4SJTn2;;OiVzkRiy}f01UMrBh2`=nVl9-( zmf%cCw1pUsG^pa@Bynt!MIaMdlcjXJikQH#FlcHPhDE?=Xgn)6MrStB@M4A)OqR#P znv4c*Brq>B3#U=WB`By&Y`k0@EdzJVBHPw8jTjXIWwJyt6PR*1BMOfo@G%;Gq8UvO z*UHF@#6%L!!Xt{zM2j?;OCg3QlW5!s7z2h(W+GKqe0-EzooJD>Xha0nEQKb4t;NF# z0ulpmMk*uG0ts9tWYBn#COuh!iDb*=3Y-kfh7)ikE8l_+Po_wuL@kXHZH1fkqId=} zJd(glAh7g$c_fc(PD})5Pu8i-SccHZXHul1D48sQB@V~vNDM7_L}Ka;(P}CW9)|+6 z#4D1eCL_BsR%_Jrh z7*HK2%EU7!qA0>}2510p62bIx9Gpy*gLaHa285lcATkL?oK?!?BNL2B8U{Sz_ad9dPISMY-aSgz@6cGq@oEoPysAU+V$)E;JgBOVeHBDfFlCTKy zA8t&N2!_H%G2#TSPRXBv2Y?K z8W@Mpfy;1F6f!PSM>Il&EUO4hOQeV&HrhM32`RI5N6IuHeO}6GT>$ zCWaaw4P{vvCLIbEZi2)mOB2cQrX+%aZN{qQB(8}LPvY`8D1epGtO%SaiHi{`*vTlS zF`APo(Olkwyju@IJ|geQ}t(8+>uA^O+;LjdfNiE6DGrzf*f zA|f(DPcsonBJcqcrIAHYjcPmtqG1!oG%P?{JYHgzk&y`rS{(tSj6jKTOl5?OjRmdX znHYHz9UdKT5+mYhWLpbtrW9PI(io!zW{QkXfU~V}d=nJKhM0vEo(?6_M#18!EGSkc z(MLsKC72koTEozR5yiym1XQ_zAPCn)5N)Q##3aN>qRcR%UZo^TIeNYV3yqP-B%`n@ zgbG8@z;Uu9l5NT=SfrJQW-xea+nC_g#Aq&FsSqikI*2BY#()_S5;-=Jp|a`(5F^Qo zCF2z`JS7PsmTm21Rt!l+~} zGs;M3h_za%DuRJPASEU)GDgop6BLP5sW3T76vgFGh!7}ADuBr87!95Pqr{2mOp?t7 z@Ngwk8bgmp#t1nkDkQ?pmyzSJ#yA9$FOL_{nFKl=i$*AU)M!>TIbJBm3d5lYToiDZ z7(B#)7wAC~HuO?TWh8DS7awPmYa@&t2!@gBq#o-7hMGKJK#smHv##N#uL%jZX z9RDkfM;qdzQ7jah4S`By%zP3NArTBwkhEJM;Gs7X@3AVS1d;jH{*WP*g2#8yOcc`{K9i3gz~KroLH2@NqE zwgrxm$7m%n$+kJs%$j5cFH*~wQ`uMwL?x%8%ycRvTq2?HNOUtY(MTkzL>et#8=fH3 z8spe;`UHhSiPQr^p%Ek}LJq2jfkN`EYa{7DnVsR!0{~NI5m;agG=OzCJ`c0r;+g>N+OR>N`mwG(cDOc zjAJ3iL-7$}2#N*TpkuTcJr+X*V?|-XMa>5{5nO{1EvH3MwJZonM~f7giIlixvI<4C z5;ZXjECQj%i6bdu41~gtTMv35LW+XC> z!vqv9jzSVpV0sX5@p!15gV%uE0fUt?z(*!CjR-!|QxdfzDjpGOwAg~Yf`Aoal$=DJ z1dorl$_X)178RYwr;{Nxt3ncGvV_YSG8u`l47ak$WUT_55CK!fM@ThBBiBYP@DYh{ zMgl^`ON>kemV-AXV;Ecv+ngw(U`T333@eetC&Q#7XiPj!AVqczg1w=rZ|j8+yQ z*F_OA1cXs6!jf@31Di`qVk%(@G6Sh2%0bkW81!r*hR#7nsc7NEXgtLnCFYupa5dZ( zn;AHXNx|fS-jt~LWCaus(g{3GoCt}R0`MSX!_6{G5?iW_(D3iq>E$sPGDpN_ z3X@RuB)ljoUXFoBE16~uNg5rFivi#1!?_3>9S|sSXi>OM7ZZcPSWGlB7DRD!qzRsg zH$-b-6t*@lDhifNkz$MxOoD_R9>EjIl_&vHu9xBC;aVCkPJ(4YV2SF;C^!vLiH7Mr?#e95h-Yg>toMAsLTC+uWP1MeCBZ;iMQ%j79}# zpcAc$Bmq0YXwb_IbVH;`V%39W3T2HELwHo77<@vGCMU}hnX>pql^TMR@snUIZ5%@+ zB1ADMLQ5nE3XjI9BnAkYOBPWi7J=AIO+*ry1hH)`C|cUDrDGDwtSE6j9}#0A3S}mN zm~YiW6J=3G2$P8;TD0^eHWFn(VptNUCNc(@Oo^xIn2ZR}dxS1rN>OW&(GYBOG{kHX zQDp{HGzP8;H!32d#jIpWTqKQbg=i9K@sfCifrGJ4Q=m{PsVruK&cHOu=rSu=nTVnp z;c}UTk4ZKg;)IfzM8Fk6`@(pJ0Lq1+B28Mfln#%_5;X>!d4ca$nrI~q!$b*_cqUua zl|*9sNg6sIrQ;KgHZWtWOvV^alG;XGMTzmW1R6gv4$Tlj6C$Hf3@BI?zz|?jW^01L z3d5-wR<+U)EkPvHIHqKhD9JWGh{*yc@UaR^3{{N6T0~kHAz47=WBD>ujE0zmPc&nr zl<{T`9;7@Xr6r2av?l9BXq8fF09HaoiD^nS4<%26io|FI3YmnpVv^w+rZp}qF&crB zD9u>578S|W6S0^$ya*4%ni$L)&lX1~;?ZIYlP}Rybqo^|4PrPRM-r*9Vig#c9<2>0 zN)aY8Qfp#E#o9P_@YdtT3Kr<3d6h5rvjY ztX3i#sgK7962s+kd7MUq)R}SNW)(9zJ_%}IE650x4yza2qKwsyjl)QA$yh#|YA{LS zWLlAxnrw}?@nkEID<}Yf$qX_Wm?kQMo$!AnDd2^_lpHu|)6#B7J3DVX8W9(1nfs=o z|JPynPF;yOdN6m50Q+x!V8ZFSXY%Y*^d;;%x#dCzcrI_{X1jgk#U^^F22gYMy1I zd(>A}dRRl$UVEJ~7XR^Q0ZpHF`{TpUv83}Ui9<(sVQX* zN7TE&JxVxuD&b&xeSz+Zhq`p<`aO>q?QP5@vW`DLw)Kwz6f>Ll9z3VtU0}+e)_I{% zW33eh`Wq9Ck7ZM)alZ?ud^&dEkFUpvHND)dG5L{KcFt;l zcy#xfww%}n)&=hqiKBn-w@%vtchvZuGG zVhCsK=$7`{nnyAB>!0Sum~RWKl2rDuH14x$UlOhop7L zo0Q9g(1w_~)_Bphw~x!rlyM7>ooU~*xBDsBp}XYi!zFIZ1!Q|&`ls?g##v0X)OE^U?;>>qB(?3wn592qG$cvXeb{RVa9}t*#>1p4ZzVDaZ{@#)mJYs14kB&13 zLtl1c^TZ#Z_oYc zP*n`MnO;fMp1JsHwW=n4STCv>YI?&rSGZAz5l1`~jL&>=#{BLHIsM@`W z%ae|spYib)d}h0QW#KT&&TW;A@!$Wn8E$|p^OVc3r6kh4B@^R3>sjc==aqy*g9AqG z^m*hy_iFgn`axUg-X3q4>$cLj?}h=Cs3qb|D)VZN*W-}b=8pzOgrcq>Vz z4DX`Fc^bCr&mM00FJ6rKT*q5j&Nw)?{88QYPA~kW+PWnix7s^P#Lq7c2>!$w?LMtC zomQvoTgic}7;3_0eV=M!CQg&1TxUMP1mH&Ksx?EAI>hJy**JUL&y_nReeYiS-t}%C z#5uO>V)E!7uLD^)#L6+~>Or2E+XX2--_EUH7Lr$zK`*`QyzA`JrCDC%ayJT&N{828 zSyCDoJp`es9e;idV|kW4awq=*YK2!>Z4LJ{?zrF&7tQdC&54Vdty>!06Fj2L>HdWW z`oyQc=paJ+%d{ag12^{XET584`K>!U(CKF1gjrwbKfs3sZCUcVYU_;0yN^FSyu8L= zxu~FXksC}Jd!Z-oah5wybOPp*apv*=*rT^R^VZaTy8;r2x*m(W@?}#dR8#)B9#6bd zL5Gm424fRjXYX?jP4ubye(~9W`g5Igpqu6Hd_PJ~5I=OY+~pB=!;$5Kj|BEFC$g}4 z$5#Gf?HOSK06l`%ZXosd{}T(@Q|&$a<}v6uGylY~xHXH3tbpLG!Sp}ShPZvU13h%| zhP?Ie|HK=6w`)P5owzTxuP*!x`)>Gnb9jUOr}+KZ?`j%o=jQYHJGg&!oW}ro_F_$~ z{tw9ZcGxuDo3r-%&BC;ye|8+WVR3EE4gZ}l{?#wc*3PDKL%d)+1il? zXAfrnYehXl$aul7h5f7FP2)j3%()}H^8VHFDaW{B?5Pu{O!%J_9g5s^HYggAO(OSE)& z_tQ5&Hmgrxe+wXg(Dd3H=AZXs=A9~9HS^KiGw;r+Z%!#QY+LwcQ|NMDIJUBP7VE#` zYyo>!;a1z_dpp)aw$-|88i16MAuG1dn1A}Q`b^dSGaaW{{>srSXPp`Ow^dy8vERAv zMQ35#>emr=qW71__1w+|sPN7cdgri&GLExxy7fr!eci7>zVfN?}bzH``(53f-hxZltzG=-0KBx5@Ipyqv)yoSaetdbmFfZU_cyG_o z$3$h2-n|lgZOOuAH9LCDE4~E&y_dHG9bhiV_p7bnyd;I?Q^N;m*O=rev&K}O*4uOo=xe28bZjKCc?Eg6A*-H3XC+DpEL*C8< zHat8kD|4IvrQG?b`1SHtenCxd=2t7~N;oQC+LogCP3OO8+)>_%OB#N;xERIO}N__xQJ^NqVcu5|T&q;Fn2a_acm zOIGsD?RBMn-7cRvV|;yrJ!Pe_NmiAAZ`Y!L6=r_j#!*M)G)Q4;r}quwFxjdZUowW- zotWW1F`y-S-onq+_rquI-u~+Klky*UB#hHCo?f?+?OZ?P;WtX=MK0%H^vMWg&R;%q zdyiw@qWV2Cb6e-Qr5-Ao7~P5&-g|IZ(&$F<L2Pu*Hye;!%AavaGB7XZOV>i?} zgC6QP$?)yPhWY)EZ7+f5y5@8`lCrVIOJ7Ir3s@@WZNcLBv5u9L)wuk^T^pN9Tg!JW z{0|HwwgUHib}%)^yT4;$ZOsZ}$>q;T&Td(5cKmw56*obk^s=XHSgh~!17|uutgjiN z%4CENnB~8`2oIOu>U=yon&3WjH+ko_zOUEowPV^`|HC%8z5r12E+~&yk-USHK|^sj z@|@SiUhUZ=+p3TZb7f*Le-7ej%%fw{8_SnOG6W%4J^E@FoZPc?b7nEdFO^Ol4Sg z)^h3Ac1vl6<6^>I>4z%%l!D9d$yW;Ixe7|D*`%d~K?RrBE^j%9(m%hpW_>lTy7|+o zPVB2IBmVYmxfcM+{Ym?cyZ+OO?Z<6{%@zzBA}5Uh+lhYh{rw~m0QMWpjVJ#7`gmo2 z$C~!^KX7~daVHQUQ(rfhY38BhZ{#_iC}#Z;A;J);suK^d%=rGQ=n^j-n1J#u@?2N> zyHmhn4qVwUH~#G=zlIwa9=5Q$*1Vj^%054~F&61i*Z$8@9Coa04a%Xm$qtuAbUU2B z*y5pZ{>S&JkDN+s1Y5R&PR^8dKRSJJ=;D$;Mw2&w`^?=$)}Bze#@N!9dsqIm$6!u~ z)pI|LWq%hqgt}$sJ9;bK|JgCgIhKC!z?^BDcK z<(n1Ma_;AsS-F$&VTHS{%p&~HYvA^>`5>=BUN{=%ul)B2hxu=(vf4HiI%Lk>mhu1d zm|7QU9Re=SQ%~j-Sq`qp|2cj8%=}630E$OBhZhFeYagZmBLId8z;2INMI+n4UrC?3 zgUZUbJAV3~&uPF&-lH>!tm%H4`J+7)|J;|Mwao%$bi?b>jE5NkK+W+T04vi z|IZ~2a(KGv$NpJ{J0!2(sH_0MnMc1HNKz^tOYZ%1@90CrZUvoqAnw?#Ip
o{Hs ztPEWK^%}TyvVY#9=sweDMg7k>!Z;2q>hjKEL2$pYit;~?e-9IkwQ0#-+W#!T>XOo5 z#J?(pGJ?yG&5~}4Zy2(uvrpNZBR5aKSU;<}cg}C(w;f@hIXW}H zF2!#sved7BFmOPn_hQI5&`*2lxRmb0Kc26RXxP1NQTxkVo1XP`YH`R-ZE8xp_O++$ z{JZr+<-}gxMsK$3q>K?W1H^9*F`s)|zIrcq#XA)qJoo)ZO3(XMDVD?O@|Ls=JkuvH z#PsG>^lTmJekpH4myIm$KUPccNgKueO^UVQ01xH>3vyiK{~tUU>JwHRU%yY#(P(~Z zJSwX(ja$%}I&xUSH1n4w_RSY$ONU2yj;o*-jcI8GjQ8WXiV@?|?*n1tIVozx)Hw}% z_8w?IZF<`dNRM$`8^_jBYP6rtcPit5`__MKFUo!U$KESrG+%3GY06*py`|i{|K-vP zllJaw3B4J7e!;!Rnolc|TB|=_T3Pes-T8M*N8@Ex$omFBP*3!F*VoywYx_fI*S@Xa zD27>6@_`Fxo0oyhFU$;k=$N5A`>B@E@nXX~6Ih%*K(2VVpnpm>vc7X$^s6Sn=TEGy zUcI<$?+11~DL?c2PSNsNDL+5M-4;&zu|$cp1+2ieHn(Pjl<*^Y((#RdLpku~k{O$@ zNxOQ_etDFj26=4K>wQOadRNoy+p`VF@6StVOqpwaF}$qf^y|}r&3_+q9REwEyFJhb z1M^6yw)tx}F#d)oIbm_eEndWo7h4y7S8UTCzu0fg*FeWRPFu0cJB}H%-70iKYeNYf*ZHV}7n4@r+UGB!K<5C*3JhD*U(z-o< zi%%X79N8lMScUG&^+ej{bZra>K(#TrF<XM07^fuXxrwr1Dzro;`Q)>UQmJ6(W#PtE20K*{{yc#&$OboaKbF`%@jf?I3 zz_gJej<%JNGi>3}%cl#t1N85ex$Zpu+w-;ROXs`BVN%E@hurMwr?eviydZxuN-G&9--b zc0hqlR@dx|8oU7bSx$x!Bu|Z7=XaEzS}c5V>GgDy_p@Ji;=L2tNuR&$BsE}s=kCy- z*Bg!Z=cro?%wO81%5T15A&)9D-5Y^rcMR(L+aq#q>)LiR(0eQAy8mC%b^CRv1wTLE z@7T3jt*=wQIq_J1Kyo#QWm>jBDJ1FTEgjI3%MLCa4Hc))(qH$V)%yGw3*F>xF1l(x=qizIfvF78^JIy2gI)Q9{5@d{b9_zYZ-;eku zTx?hWwG$7)cKq6jUCyiXKh^OfPW2g#x$v{8f9SPOhufQ!6FSSz|E!v0ZZsYMf+HQe z&ujMyz_Zx_w!XImGV(GzQVIQQ^s9LeMETg1Zk-wQnc!QsW$tC=;4$t_bGHLxbIKQW z&#o>6SmbbEk(rc$qQ#)1w*gQOx9!m*Q@0ES$@#J|p^MIr!Rm_x?%rxc?t5`))4rsJ zlR9;0)5VR)b3wL#DHIhpwuGQdk%ZM*O7M8_xd-_7WH+WYgV8l<@D-8%ok zV-Ug?%vmZ-aNoYQ{qWVXNfWkc@d;_S9|GP}Y~zZExi+Nw@fVRw^>mAckylhMAMBN1 zR8+rX7p>{bV@+3p8}r1T09$gRa9v#j!tAqi%A+h0;@lGY`>ytIC>}G%^f11o!abty z&4*2=CS`}NK6t+8Q9)8Qw&R-Ls>l%Wv*6`9VUGDWO|I?c9-E!a|9hp~9nOEN(lq2J z9B4bypuf4r^YGxKa~*d@Z0mTE{CbM{)sE%$2^$`*0AK&1dtS zh;AEU@hdjNWjR0*_~}Ts5#OQyod;8X-kehYskUQVZ?~-Qv1)zxM37-k{+s(%EM1oQ^zRxDGG_>L+>W)eB?41I!T0&pcL@6_gE_3*61G%X%*==9JBLI_In!JEP%S z>$Z1U^@vT=|16m{Ho9%OWDWjX=UGX-Y)8Xf3;^zaQP>0SM&05 zCmtS{(%q0$^G&#Bz|@l$jBg(uuR&%~@c-x+Q zepR&Ud-xYzf3N3&l9VzJ*@EGGfd0PI>W+_%Ev*i1X#t(ip|YFKEgL1UzF7A-W9;j0 ziL~?CxZVfj@}2XxQ=ME&4{496h5$WV1#q?R#o_*e^vrx=mkK}mS}T}R&M-EP<33`s z?kfNF=K%+Yyt9>iKr{^~SEwRDhREcC~wXXwvO zX+uuyo?XF?i=LU6?@|L{6TzX=&@xL%fNC!1j1gG593?QQm$ml3T&V6X%06^J_wT8?wEo)fWKQ z%zQfe(RSdyuZP;a_X|jFSAvigSA36T=aBO4=Ddc<2hX;USB`4-Lkv6Vz8?pfom7SF zs2n-(Q-P+i&$0O(r>_14)@!zv$R>#|9dPmMwFPL=c}`3Mz{n2Z5}&UY7(f}MSx$+} zW`5nc ziYn1^ua~5%Wn1c zc=NlE%kOvJY4=gO_Sa6>nFxr+%on%XB6f0W~6X*Z9t>p*?q? zn*If???5t?lj5Fxaaa>519r8sSMJ+ltQS0aG4M{<@-fY67q-uMU*Z0wIRS(lM)n=x zEH43^kLmoQUTaiFJxH5&5SX%U-pFu9^Wh& z1C%kj5V#b`lb$yGPL}k<#dTxIC2r7pi@xoA_qAmY>CPvRDZJTuVdwynZ@&ozhBXnv zej!Ie3HIdux$~p$WG9Q1j7y(X;OT?5Q6NobCh5Mkzn@fW35;{a*V9_pl3W zLRhP*qv4eL)$JW~_qqCqmApCCx>fypf0;?PMYn8~g}HV5!#RKq&1}p%rKq1{p3_x@ ze)<(F(2lZYmhD#@cO!F}0khQtWqBQ8;~fYz7EftcjRqtsedp2C;%B`!s@R+KwX?bJ z1Vm3Z+m?fNn`iGX!HSpoUMmcCx>sE=ZNo5R;?dfLS9d-?JR^NcW-0JZafgf;h<*7K zB*k+-`KdFSI(vU*F0PcY!hoFBN&gJ5pKrN;1q5JW-izi+J?i z+XS_xNjr|xikB`)sl5_D<8$P=Qh}~=_|NOhrfky9kf_~4uGig#To1V9&+I3?bUahBxK6@~!(F}#k zS`}9-&o`&7_TDq1a?;c}!KJU|kDDJHp4eJ8^nO$J$>y{ey*)pE-uh@bP^H|IMtb9_+tIo0 zsol+?*P)!tFvE#)^WQ+nUW8V$U0 zbA0vgiNw8_r?z4iC8>_+y~55tujM7h@d$T^dZMxW<-RY{wJemI+(xcCZD{$_Ngv8+ zTJHOcy8Etm?CEX|{oyoF91l2{JZU9S=L$2l zL3wFsz5`@z9vs@OoyX2usyXTR5$G|=xU^S0;8&?|&ftCdZZmF`RL>6PyxwJ{-%3ea z?ZZu9?bE)dBBN{CyR*;AvPj2moYC9m`izld9ZS}asDC_a!0NfOD-Ix0+G9#W?!Q_d z(LT{FaM82#Un_$bEG)(=~}F`)D8NIgVuVE5H%Y{SN+v|L%xqHmf*xhwD?BaH!u51G|A$tB0= z8U|DvQ>C%*x=R;k-mhSSGGjM%uqWnFZB<@*_nU`DXG|_cex?^q{?T+S_Oes#?6ACL zPr3Q-mHH(h2iq_b6A+ZqlqaFH2YB|IxG`zP=#VV~6m{Em=ZMLQjggRy)G=Fa%l5&R z>u#d|N0Y6YY9BKGmKTBe3^3FjPsQ=@IuIt`h5%^;|!V%^1@WS9ddZ zX6({lPGL~ChnKM@94)s0ruV?C%5R$UCZW=)7eZh;9QEbxg_gy zenCix@9Da&Zlw=XdViMp@y*UOxCuwjG2|ZHVY4jida!JYt#n}Yi+H~@Nn)dO(@RqS zbWiJ>4M5`41rJRehO&gE0C90)GkmSQ0~95ntoT+v?cJxf2}2LZMt@5#F7O_|uXCHw zYww2Ay7)=X518I`gG<@)mp!^@lAbpBEfI z=M=XN47zQyAJ9HJX8$%oqyL3#lZ*E7uZ}f0=yD#7DnzdQREx_T8dz*`+wox0kGBg? z-xntAe-S?OTU^;4@|c}ZI6LmjCrVek@PaSz>&i~VMEbOA7c!ZJFK>`X}&f3cjlb5QD~ z@u!Hh6y`mF4RrUkHX%$K4B&+otk!U2mAS|`5wL# zlv76*PBXN;I=g$5lI)oN%)crTXpbK!N(Bez>^P87H={PG{l$m%kE#j>ZD842TQ*mt+h8jpybBE7Vb*%u_+>eLo{DbLd*(mNMvR!; zJ?~H~ZbxV6Dz_oNC}tRa#S@$SgbGoe$2n3jk9Rp-g?bz}6VG#To2UTeP8&PjZ%H4| z7cKtc&w$|nz$$ND`U$kRj}tX@b?j+rc4Dl1H;zLPjww9^GMU{6%bY2xv?#&?pZuUb zE4?2Z?y`P*R{?>1cE=7S*6rF1`+d(mwBtXNo`8V*p}#gJkZY?X6$Uu0d;(eJ=-!(< zIPK$Yn-pIJ%NXqoM--yF$6P$}EN9yH7HRF>SBSHK1U$Kz*^=V2_3p7af3GVpz1YFN zp6d_JbI<5^up30WkdQD;yjIWi)HE~*8^BO{Xpr)lRHdRO3lW|qmP!c zvF#;A4O7p&X~`yy3iAo6uyd&ia7WhFbq>6wUHpBsw%x-m-_4KwRp#!n%xO^eBQM{o z*?msXCJbq=IAtpW-Wz+O-aYk}O|@N^X;T@d02SLd8>NHh?E7V9!ku;-lQ-C8kDLp( z11Qsm7ALZ&9jzG3__}cQfCzi2!mn6wKJ3A)6&@Y5sygc4 z)cN3Wo_<4q9rM0VTawR>%%dXRnOcAxp?1Me0=WS$Fpj?a!yQe zpaGf*bg%ZglTLft*hJZz!K2>Ct+`(Q<eKt((g!mmSx~>-{$av zCbCf3zgII=hH9+8={HU(g)dw=%;cgi+OCdCxu*c4N?5a3b=-;Y|@`r8U_< zMnc1PZ@#$1f5Yq}r8OJY`n8K%`fY&iEvMZ$l7DSb5N$rZC>2r{e7?JuA{m?fYR3}o z;do2W`z?O3pGD(-UZW&ud|e%$;Jdpmcun{re_Ofu+#6erqa$`+cO**9^G{mxJ3!oaD>$~R*Z3vyOg=Vgw0vtj?2 zWfyZ1`I)0@#cB1oIX{jdkXzRc++LCycJ!BYapb>A#@-2G{j&@(&+CCtCaik{YJ=}9 z4`+<^g<=NH0d>QrcbFgUMPQm8pL%$|$h!V9Y+8a#Ndvu9#6ErRjrRazaZ@b)jMWPjNc zA$42joAgKHe7Ds-c%YyDY}B>pE|S5S&_C#Hsq<)zcKgfK^zQ+;zl^pWdq9|MATn#x zZx9Ky+krpu6^M{+yo!tivy%p2)EeeC`)9ur)#ZV+!k8fQBgJm({HVeZ z{+?a;0$BOaD+iM5){94s9OQetBE%3f%D(qSa7x?vFK;)ur*Bmhq#z&rJJ_K^;vYD) z-Z^(V|6}!s5W`B^>+y{%U%dpfN#2XgRksdb1i%rq==n>6gx+UP6kCR-`9lo@oD`4Y&aAP#nI+4gEM&wgKe zW-YsaY>tf9@?zBf&T&5?D+Vg0#b+y#Oc(0XXA4F(SDwnQzVYf#(O#2a#beos^UHnk zt2f=BxSrfpH~+}pAbn{UR2S+ScL+w|!*h2LrN$WhoRd91A-3am{e>CS`r1)V&FD)X zQ>nX;`w*6WH3$oD6Zd$W71cInqaKwsEg(-C9pFGTT9)}nW}0@tXYPC9dHjG=B zfchOD=;PkHmApHB$fc}hZ`&^q37vgtV*q-aSR@^`n^31bJ|JU^1>)OSL>W>Bs&=P@ zFZA*eg^OWZs5VLEmHX26x4S!O_d`)infq_}Whbosi9L|I;MMqNuGg+Qnn(Xg z{H$72D|1+$xtJE==es`A?-KcuheBT5z@1NsTz1iCZ``rST-!t^pO9frKHOKr@{8F&p0(}XW|}eo z%cpH8Lv}{XqT9PYnq`jLhDbh_ z^9M#buC6}~*uoDd)DLl?sNX`@nG?1xI5G`j^4U8sHM_v^@CP-x3gXs{7T1YU?x{hx zTG#oIzd^8$zBdKboc*&t(vXFBBMyfKOY~QCQ_p;F-`hC>mjIXe*ze+8Fd< z=dhwH^XAk}p&?0$8&CR(*At&%iR~VJ$WFty<`!3d*xbB{etK$6#O!+|if5Y$h)u1K zu0eeu-CiGuc6jAvVJ`@;UmKtKdb_HaV#hfOcK^p|;qj%m!{@1I@V4R_>Ux01XU&17 zvjmYjGlz_KdFH`tu%${@*CD2ad@f$ciDl&V^SMm*RfjH!NKbRSf(VH(o@uK)&b`IH zELqySlg!BsSe+H_m>IIMX*On*2gKoq)sZx)Xpf6Xx_?CjN$An(oVLpq3yUAa@Pi9tV-|15BjUFUlL*cy)PfL(qap2#Z^>$Fr zS>fm!ct6>z23Ma;L5nYrJdw3nq_rbB^;-iOWK54Z6(3wbWq$?0l$Cd_Z|KR;-fuOFDhizX z`YpkHVZW-m=`Ok`_X(c&a^sHodXf_~WNlngQsPAEFb1#n(zSSOcE(L`mb!IL(Wv31 z?cS$1&R>eaHrzjLXyXRf$8X+(t~^`(fb)Rys6S^)$N+HAx>PylhJA0Zn`fab(Qo6b z3^!>&V6oqo2@|I^!iMbj$%6JeRrV}66x!<1P(I)M6!)TR-LkKmYndmmg-?js`sVIk zEd;JRS~+6Y_~b7G&vwoxce?twED~)i-s7WwbBZ;rKn7jbXJ7#2+U1X%uANpk3@so3 zh(Fw>WD(Yul(y`0IcSrzDz>PW+zC4{KXSAyKGkieGTt?a7}xXlYUp?CaMwwOmeLJj zC2YcyDR94AL`C4-$`#lu)4TGnWN4cA;Y%sx?#T)#-y|6P*^=$K7l8)&>f?QAAMZV3 zSI6-B_~KsDBd_-yOVl|SI%%cNg#Oz$jGY*hL4S#CS$oX;KE|K+o1PNGJYs$NW?%H^fOD0Z zi^Y9d`BU6N`$;Zc#m(@^#ch4BsP4bM;#9(zDx6KSHrh%YU8ii4b<#2CklebH-qb>u zlZOXarY^6Zu8@P=D%j9|SbSySa;L#wtisWV+WL%FkRgMf!rP>4vYoM0CJ_*o+*>zF ztGpw;I9Hqkf^}prZHA<7&8xK@Bb%niyG>euG0I8OhdkYbLvgy4cFMo5)-R0Z-sOFN z#po&NcER{shqms!f@cJmKHGwb$Wf#TGjfM0XbZj;h}PgJLsQA+(V$xSv&1S4PidPo zTy=`;kl|c=Hz0fqALt5kYgv;TZ{cr#oONOQQu&~^3&l5vmXezwhmKtxJO3;7BRIPB z`fj!Q?0a%(*yUK}$@eQSk6-#K#kkVVDH2Ooe^vTvPpC9M~c}N{`$dV++^EY~QW%HVp zszA&*Zm;V=r~Yr$6L*ncap&U=xkEnpuS5F;e$|${g`#9b3o!durO%Q^b?*ho2FWhb-CrjcGdtRypF*faaS&E0*KzkJtNOfLACrCxe4#Oi>gK z>(|E>)39yemCpH1n^^P-HJ=WxK7rL!&7#%IpANfYE<_DXUI&k@I~@}xn>z*Q78d<~ zU_Np0-A%21rKK^=AN|Tx-(A0V;`*>QzS!#qW0Rp@g~QP~@M)+!E5~O&_YjSTU6z-V z;$1z~p(+N}-z4%!P1y}iUUbc8`PY$X>${b)zIm=J)SWr+o|OMwbni&S;&4wdL`7fU zv}&&r7&+tH?57XvJ9u8NC;^Ta9o{nl@Hb`*`8){yZM zGIGGTN6dj&Kio=GeLOnec;mUjPYSU+bSWhuF{teSQ1#YvQ9fbYHy|ysgmi;f1x?9@a zU?#=9S*T5}{J9!>k?H(u__e&L1OMoLL3s9y1PDB^*}a#Ixt39tiy>#k}&cv(0ks( zNQRYIAIDt_7q(+EOvbhvo=D>aKeXEd8DAD}n9 zqU3(1$TlFl)i?Ut{cfQ5!02xn-E%7s;uM=m9{uLZ!z@|x+aMJ9q0s@ZTqq_(n6kaV z_%az>ws=NT6SXMhsZJty`yaw@CWQ}|9Y0aSRHO-nB&x{iddzaSaoN6>muP>>?7g8+ z@R$;6`k(a`VPXGUjaXm#o3YHe5GQ1zB4X|{%icFJFjVRQ9h};fQW@K#<`7mBqg|qC zYo^yKgB;WPSJLL+k!W*f!ItS*s^lVq))-GXXPqO|&dhB`#)F~)k7Okp8p{`*m=_!x zsAWEHH_Ktg4b2jx#6d;$SQH%H0~GSMRvwO{q_55e7<0`aJAjGmV(>=3ckqys~;$2=jEV` zP|u}>LuThrzl(sj@txf)P__48ev6K#vt!NvK^7cD6i~u@t?2nkJ9+b#Pl%U=VX&0X zMn>z|SJ+x$4VGMdiegB%{GXIiCF|IKl&JzjunVf@zyK`NGJ#fG1;<@K+~!a3P%yE2 zacQBrJN6PsX)f?9h;zx0WM8sfYh@K1o@hnSJaAB5!wJCm7(0sG5^ufV%p5o) zDS<*+s*xMY$BgD3aS%({;r}jW>3x$v1V(rQ+!AJ7NfM{gL8}lS`j0v19A1rERD6V zE}^f8|5aBYpWkDmfKeKe7c0Z_+=`{rPF?rqTBUdnu)R)JRS~=vvO?Y@R4wDB-$GPE zWxUx)K-g;M`Nub!RbGNfeBy`C78ADQ0-xb2o`dxx9&*;qy%_~s&tI}jPKxTNZLj(Z z&9(HMEkNo}b>+i1wUdre1wpv}z%cpD%X$MEcq|2Jrn*h+@d{-9c#;Bf1 z$}=@i@}}`KwarqiK-}|0*&!ho@o*YSpOu56rP#M!n^GBE zY>tOgDop&t>gDiIY_lK@7rZ4|sUSSN{r-9{pc99HLY241lTRa@LgB7MV8?Taj0V397`*j1S)9p}L7%MS3x0V-})MG5)U?z~AqlU=b>F zmRHJH$&6ye^4+5#gpJ{uzMqxLYkO+(lx#NL$}1z%)my6rwKzCA;U?oTq_0|!R7fI6UCTyY}2Lk)O&=HWU0kNa}UGg6-a*e3TG zQA1G{h#Zx+H@jWLJ|+*?jF2Ocyx><6a(D|GMgJf(e^4i zkO-ESRUht3XDJ|T#ihR0EJ(Z?>e-#A2wzLzV>bR7`&1W&KM^Uf8HmfXQ~VNsHDo=0 zsN{+`N^`&QT?xUs#iVZG0HPeQzp+=!Fhv^EjV5`}?e_N5Z2eHpS#WB4SqN;CK`EC< z%ipw;jZg4eLNUWJxBpd{l;&X0lo!HP!B)A+sv?A*^Uj7S!?rjESqQyS8Chy8--G1& z-`9<{rNThmJs$H}dIDEuaNGWKs-f#>h64Q&lgy8iI(e+)8gavPM?Ajmg@3zsJ;Yl4 zV>#4pR}iJPXBP@(bz%OaN#jwUvr^&`PKr@&PlgVeq%W1{;{Tm!y!h3vxuN?3p~)s& zMs9diB={TCxWW5*x+v{ms|CIT`kAk`;v7X;h#IESb8^cOC#9GbNJ@jsI{V_MOwtfK zWXT6lX#qy$(j}oI_2sVt0lpMr=JtYq_}V@8XM2zUr4Fqdpgn}JZ+3%fv=-Tco6}?7@ zMkf;P;I6$y-`gywOrb2?%O?Nj)@~_KsKLp23P<8K?~@P}dCyxMQH}e--eE*Ncu(yi zA}~o1-MF1wuji`B@gwMi2Vx**QA4*n&ns+UZiQnKSvJ9+IHLWY$2k&wB1Jev8lY?X zMJhH-#{4T%>i}PTFnl~ZTZ=oaxUu_z>*Z&?7L}$<<{*l_*Q1YY`583fk9b8{8NJ)C zl6@}`CY8r@3~KtWVTSx^;jAWG@A1@tB@jFb<9iZ2a-{$1sYc4uk59m4)f!LYnNfPa zKj8{B6g}gpx{UND(#UJ}IoteajGbr2IbijxwNVMlV!qwO_7$yTg12<_dF=S@mM>_I zh4>k8U!cv~qHZ$1Po-ad7l3FweR5-fd29BaG- zHpV+CvR@NTokmBs5o6ED>a^3DuRlLSnAyV2cCln?-H4!^(VuyYm`lS;|GEQ_A??3N ziJR2f7(~5V=t*2NSKJ_7Hb)UBsCdJwM%U)xj{$zS*=o5QKXvsT!UJPVL zPiPJ-j6NuH-PRM&o2Hk#JF!~_2RU1YxTK6~58IWM(@YS2*Y}E5Px7LXj*x0POOodu zTvOeLof!1QGAJ-1b*lxM-;`Pee$%}s*6P9i@!q$38k46UG2TbnFLE?G6J+R7$#9!y zb8>!0_!wr>oi+|}ohhVwUa~dT{-okpgGXkUm_>#LU6KpW^IKw@*o`8e5I7-P$U(~V z^~0YhP>HtsZ+XiL)boVu%u!_0W1?~AdmD4`arGx-oBw<$ZG}HaJ->CVsHyYdj6xc7 z0PY1brP6I+Tn-SeaUdsPRSCAk?T*C36^zN%J4Eh;r}Ye)vO_6gAq}_Ir4-Yq9tlO_ zk$M~smTplN z?~9MdxL`IUw(3$Nkg|;W@vWUiWt3Mwy;oNDrz-VFJ|7TO+BDVQ0n6ol{EQK? z&3L&=;AqZLr{9eppM#B4Ao*nk9m6ZikSciN^KHl3X0Uu^30XLQBgf>yd<_cAbpnx1 z>nWVADi25q2P9cL*ds8JP%JC{dLqWgGa}#cUZaqM*2bl(XTiLOm~c8J1i z`Q33>XbRR7=TatS6^G@ooew;WJVFWZm$x8naQwETob2SUzUwfuOeZEuKRns|WqjRf ze+pxOPAn1w7hPNdji|<7S zH|JqUL|P3A?U!*ombLzM!gLpf-;FB$E*!fwB5BbxatVqT8ikL7NgqyETAYVpcDZmK z%`6qo+Dj}KlY9=M3ERMf^M}Q-Jh=eh5;jX&W(beq3GMR&z0fXN;Jr>7Twzyap$+LN zw*_2~%%r8{&n=+pzQRQRz=H`Xm6(jBfIeyg8H-FM5kGEoOBb z{;-qvpEs~HL8oHQ3gGb!h|adaqi{rs-}c_1spZqOj4k#J;RhU;MVnZ)i9`x}SzdLr zApE9>%F1Dux%l4t?MF@B%A(&P<%!6C^METL&VYo8&CDgoLq`RgroAkW(+ubXS&`P| zs|rCc#YYM9LT#?!lml+f^V^aws&0SD<+l=v2Co&HPJf%|PXGFSU)b_yR>M(s)2eH9 zurbA7Y`MsOoVAd1J_eQyAqKS>4lA?z!_RwM&0?7oPzS@vbkQ$IZNdaDZ6%BDL!9>% zjIl*Q_db6CT*!BR)U4C@$*v>2Bo{C-*n^IvO4^6kMQqe}%Rte61Oulyq#9!@ESU7H z;r-;k`Shwe#a(hP zC+Ho7ZPkvz9s?SroYm7hdl`{OK{67pA8uU7P&c=4R3+J=bbK+gO>8&vQczo8L^q~A&&ym z>&6w?izf%a4`V-!ysjNTXppdvD*tLBJ_5r#w1Wml!y+he6tfYyr=`pj5TLpob>2*E z0vP}U4@_evR0>6)gIa92tTQvqWCG_5&o8hlv~<+uk{L`^Ro<7M8Oe@}7Y(allT$C} z@Y`PF+e-oeZsEs@6?t}}8sY9~wcY-xMCl#Pa-EZb>wf9d^mNW}cA+2o&>%or^0PuJ zC2fIPw+Sn6G`7Fa){Tr-Av{BO+iy$f{f5U7u_x0Ud5+wxDq<|JPUB9zak2il2e11CVD6p}xt#NGgsj}j`OX2`qX`5QUm*GirnJ3_&!MKx94ivq z9f&;nc=PIf5SlT6L>oazq3uln&PzJPzfM6ZkClWWL=0Ew#Lc#cOQeQ?YM3$_zGC(k zgln$%)WaiDd_Rb9X{j@+C%~{QXRsg27+5Er^1OI*zq{x5$5o`!7em+(5Fue-Ora0B z47lF>I(y2xWmiSY>A9GHQh`>XYUPAy=)vW|FwSA&AP#<(sa zilGv1OyVrQXx|+{61kAnzj9S$JN?;-lVbJ3rYpe1KmXYp6^5iBK|ep3j}osWsr}5b zAT9Kg33FOR!k*jkIYO-iGt-G(g zG)+!3G0GFp+TWJfV!A_ac!yW&LGomAsF7v=inmQ4491b1wNZOXdcMex7Bf7u@v-) z8v<;v<5N@q;*6zfO3ls-4AoWM|82Q6lm<@!3#&TG7#UGiH)zXTUdxp6(6=lenEh1c zy|vH>Cz9(lToq|Qa8_I>S4rzgMnp{Af5(je;7nW6KGvc$j{Lr}{OubE^2qp#*H{ce z)uM;#A~``ZYetxmn}ZB*lSyb^*bH@Q#9Y_oMt2lDjk1 zAiC=|%O4PLIuy%7<#(0`jUP|^XqmTI=9yvNR~M~YgtLzXRCR;+{0tgX?glO*vBB0RumJ3Gf<*aiBFTJ8BNPlAT)xoqn7MNIOitTx zAYs<(9bHpNKwqX%_i8}&MdQ(!)Xi|7ME#hrnm?&`A^_DHZXf>yMYrI@bHiTFXWB$c z%FA&w>sZGc;9ZQ*f{17<3MEL7pC-!O4V;Pyx>qZnv+OZAC=XdQo8RC5lR`-@uW(`H zHsn9@Lu6G6AUgHYVgi<2bPGpLrNbriQP=%ADV+io7P__NBfxCX_opbFFULD_Kq_XO zXO%^0cq*k#SKT_2xUKfnb5yVvv_jPli3tV&NSVIQctOGC#N^O;KQw(3BV&T{Y00;S zw%!Ud2CC}8cglG!*J<`d8i6+#`(hgk60nk|37uO$^P;aRCs0q&`0cMMK;M1o@-R2rWMdfg8Rq@TXtG8t2SUpT&9;#ycLV2Jx?DL;g zRp!8W;%Spr=>m@4A7*|B8CQYzmdqKrZ$fovfiY%Fm!8zbiB}l7TbJn-|7dB-v*eA^ zCfc^;XrF5;(NON!ik}-rW&QKn{%%r5rTZuxO?$%JH^XaORQR4I5gsny=dZ~k!ul?> z+PQ0k9A2;C^G@1y#e6q|nuREfL9I5;jAL>zJQFKp<+`K1=QmDfl}7AdfA|M~*DWdu zq20lF{4p-G^S5dng<)95meZxF9vqopF}}Dgetz} zzbne8uOL+CBkn$rH>|AC?8vE|c4ehPNgNVMwDLFMyX>~%0d56~k=?GQ%_=*S2hPQ| zCNr1AJLI%4DpjGsEm}6|f=#H2GzmXcGG;)n^vF_VSq2?mx4DknO_5iWxibD6o(_{m z3QdR+j1kZhmS-)5;c1s4G8{>ETLY(J9AYa*YIbCfaXi0H0>C!^SWpnN7 z-gq2DPtaD6pgyJJNb92w*)ZN#AjFzdhS+Rb&bJ&LEPeVm&-+H>mPGXHaRXGrE3}rl zT4mk7!Z}vP3bW(5`*DP^&iH!*k@8~U_tny~tfxDN!U^|GO8M`u$@@$?>{RCMnWGXs zxm^QWM;|4j_$oHk2qH2gz~@RU8@`qBpK#d>v&knw+S~sSH@y<`nBgZ% zu`r_;Kajdwc|>cE_^i%H#)ZauKSgKAxAHk&aJ)0i6e1xO1P}?X@~{YU2z?0;_d*Ol z7b&q|7jf$fUnaZP&B3P|X$*Db(7mX?v==XVf17VP-oz4Wwcfeyn(<6>9a619)zgEk zYXoI6t(l@uu`Q9n@hYhQ@{4yzx_M=X^C>brKn5XDJ`7A4z>}O zo8fDsL{wLz80}*NSqz`fiHc05wv0??qFE{L;dLeC;#F(S`J|r+!-|Vq5k*IXlvbwO z#ZV65$K~qaIjMMFg>AX4jX0QvZs{b#R*e*&Wg3%iFc{RD^}Sa}7S(pd$USJ~)3Q{;p#c)3dYS=5$!&rx^`0`h(ia z@siRC4vj=xM@Eh5^Sc4|t_`OahnuuM4Srs2dDa+Fak4klw^X8EYTk=1e7ievm6{s| z_{{uEiU43DBY>O(5f?LryoG?yC29*GUx+hTFEpmY_<^8DXU|fZYNud><<{=U~ znbxovO7wfMeu3a|OkwABTFlz;?GN@H%^wA73_G^0y9k)Y7p0BrLpr>~uiWavi4b9k z&!^RBTxwSExF#Prd;!iNTNJjw-*7T>B$?~^i|JQKjDi>L-ZdEEZoGcHWx?ik%Jog^ z2YPOWxo!>b4Exjh2)`q9IuS!W`5(uk&Y`Gd{036s_EcQH7!tuUfSpIr%Viy);)Hi6_Z% zXbfi7vhAq0EG)SeR{7Djf3r<7>d|;6#fe3=DdTQw?T9K?Xhn#3I(^EnXnONFZo)mO zMeo{ThLw(Ej-BB9TUYaS>gER_WTP7K!Z(<4x0YU3Z>3jOehSw64Fx`ad&FSHw)m4Hr7I+cW85MQA;KR3alroP{Y7je13?L9_nW<@!; zU197sVm#%E zShP!jgkx_hck0#mwO^rqOgaoAV2wh06p>jdWcQ1X+YOfYG%PBF0Uc(@>`uytae7hro|@dg&ZSW6_;khZ!jhGA94p@~0`Twv3X5-`P+M9cBNL~ef=c2w{! z9yzeGPkOr_9kbHvv^Krc9yK8xRvLMrpfEVhRGJQ>r~Y7gV45FS1XbU=jZBl$MU9W4 z)M4L&rJ6x|BonUZ>ihMB_;zZNmk+dy9)MrG9R#aO*3w{etic0hY=`8az1k-}i9Mo% zByOh0knQvW5R-}pG1GIan6vQ=67Rgzcc3#PTv*yfYSQAMud@)tQn(F4>Vqcau+y2U z4I8pE%0+o`z8=*fJ)?7Yo)gjhW3i@5Ef2|t6CT6MLX|M^CB}`gp#hvH<_zeA=0CPd z8)d*`z4*!LxkCkPvc_lwsd-VeFS77Z%3_}@4IfEr4>AaUvwd;hA6DR6+vziaJ`s>A zaa2rcn(twndZX@WvZ40Xz8kd?KKsOqlEne$tio_N>|n`3&2f9gsvEH)Y1tx>*@|v5 zuP@S4H>IqeyJK6Ck2&%ARrBH$y&GIxson8I`;V$ZG|CAko(hymfnCkk(L1ey9R2yC zTK2p6EU9Wmqi0ATQL{7EqmZ}*H+|?8D^mXF?P|3XC zYcQz7{r(YcJUkqiYVb{B9G_9J>aSu3r(BDL(qVpBMnk%o>T2U01&F7T2zJ<}@nNrY zIQ>GwP>x55ZNG|`2-|(bZBIKQA8hQ1I)dO^y;S6VOqUjRgRRSk-b)Jverf6a>$DM% z#WaaDu=4;rK94s2lt0w|zaZ#u3Pr1FLn~b5LHZE$@=B^2Bk{gA?YD}5vhnRcc3!fp zE$9z!3Sqyj$D^A`v7Xf#eU+~ZU?No1Ivy3J(en!>!-`pnA0`cFs00yF?y{y>LGFSD zK=~O)paLEjU{tq>m|KjPIN_zQoHW(B{psFJus}_-YV=?tb{%!^+mEq;6zcJ98)i*) zaA>FGuC%PQbx*fvre*WWw?96Nuo(V;1q!s3p_^PA* za+j!+lG*Soe&*`Y_-7^eD>69!v@+5&TgCZmEGy$ESS`&3i(~i#N{zupQLQq3!L0}P zp82)Dksv`dL$EU=Nfjt&ijX#vWenlzjk$m^Z5jo4@(`YPYEu5PB%-&f!X5Sy2&%%) z$7Lgogsr_B`L)TEA%ryl@Dv?N^Q*`>KdpK0^{<8ZEq7C!G|k{@hTCr$u-|d`=dU)y zRz#H!So{w{tBqGJ&qbCt0$*ud8@12>M-r}+2dB5G_NmE2`-;1P*zvLKu}*(!H)v;1(VOT`7K zCZW;+&+@&S@~x^9-&9j1yF=Ay`q()1VtH|@c+j$*UA{b)SYu9)Clc(UNIqWR(!Sx& zuq0t|5D_NQvXGKhwMNGaB`R+;JNDc3hbhswLDhj-){BNgOB%&zUz5%d4GV-x5&%uNNRj#u3tQ71Wr1%sMsJ^OTIY z5ya6x5lAxY@hn=J=aWos;r#!!6W+Q=EG`H6p1bpoSc-KWm!L)l?XxK9+b$)J;Aw1t zII0XYFhW)VhzkUzmHEnQ^(0IQ zxmYo|m42w(;ZQm+#1Ll^3TiKB7}I>WC?R+%u`OK)QqzHi69~hJErwC~(`?@Gf#*E2 z#KfxFH_z`-SlYs#U#C5(D7w3z{&pE^Q{XkFa_rXhrMg@J*FlU*Z1`|?`mHr0g0ikC zaXDkVjQ9vlKl|hf|*_?l$5KZ6Nc;- zj)(Uqntc3cXxKW`@38Z)SrJ+@$a1~Ymbb@bGif&8ffh0ff+sj6giR*t+bj<9c!2lA znRP>}C(4qX4#S#WPH#Hu;64Lz96wSv(^BvZi;cCd2#}kiTQr*0pW7)S>zluNufZH^ z*!Go)jJG6=)|U9YP*~r+Y)A%FUAEJaBIH~mF8BFO z+Uqz9F+*YC$56elx*;&R>O&?np|o&;$&J%Bb#vM)&QLK?&J}^ z#LD6*L=Y2eSDaP9eA04f_~-j&{T++%ZU`%2H6UOH_NfQY_ny zL`{5sVd8yF3T$Bd$VBNGiVjE=^}SA}Jvt zjnnD}k`IYs#yQKg=hFPH4;;62yKitNqjOpRHi;O-`{t`MUUsoICNK$DKFry+Vx~J{ zC)brt{q6U&z~Q-pkpu=jb3IRTc`W4U14b@2|3nJ7IygIhPKH^@)1^>{+)xZ{y@2bDBNpI4 zycms{Mb6d!{cfxupX}K@Z>SRhf7vVdI+HC1Q)W!&m6KkQ(XYuy1)y}AOv@`VqWJvp zfGHX&KaErU$G(vr=~j{%Nz!cFx(|ZIpNSou4J$$5Zt@&)OGAc%S6G;1j_ZQ7D0q!JGXSTY~;)ArhA?6Rn=Djw%nQnnBlT z4_g3qHm`;z_w5|ObWWC?L2wt1G1&5_O-d1{Drdb87eup4E64AxXBCls&YyhTz;G4D zn#VL*&+$kd5ogq%$n<>rb*;s;jHB)b1lz8(c>Cs_eQ2}H#8dytfKm;flnQR05C@97 zDqYguKr_p7bDZ;?%Dr>M{hQ?sF(Fm?p&D3qv$RnwY+xOyUPXccbD8&XTMLX5pl>+?(eo4PU(iPSFfZqgYp^aXWo&pTX7>L(9 z*XYb>?)2#OW(a(}4|I|tCocF@Z68*duHm=CFoA zq6!f;P85p)=`7{Dfw>f+3ljDNO??gr1Uk|ifXaQBo&IO{2f8%P_LQMjg3v3XRdbpm zfa;q0@)ok%Z*sFG{jjrF6L?-m+YVS^TT%=?K8R~d4i7#pU#2Ax_Vp4Kk}uj1AI<}g zj?iz)@hP`+^UW0n5+f#8GS3bME%1BG@?=q=bcx>)2*D=u!;UkJC?Wv3IoLq7b1qoc zzqefd?YmCvtJg~pw4v;x^aGqsj^RIxYr|gG$S6==1T5_nh^u_r`}l1MYz4N7Ddgce z7QO$$e~gJGCXBdT55UfPei{2;j{sCQcdLj5kJQt&C8SZ#0A;Oa z#0S9V*FGR5&e)J7zoj`uNHI}l4bywzX;vF(XH3)Hzk0Yf_#5}?wmX5G{|9G7FQM5C z6-a)g)$}1iAwfY?Mz%f;-k?Dz#z9%#V+5E$XOS{LpP@K|B-(Z)K$Y;IShLYtUm=po zX!JeBuk>_-bpC1(hnNSs1MpD|rcPgJWF6?{ECy~)0M%Q+nV)l^1C=a67KWfH-ZRC> z(K&s+Jym^hjon5doL+^cPG2Sk-S)%@DdxSMvA`(ujpScKP(B@*Et%^i2B# zhUO($K^CJ47(2cX=(00L+z*|(Q2Mb`P1zx`M zv!!$Icc&A~sSU1G$Jf#*P!sfyxK5kYa{TJGcAfUd)-(-fvChiAxxe!B3!wl0IM7@c zCP!xAS^tsX0Vq^l=)7>F)ZF-Y^m4!JOoWB4`ytYFZ^0qt3y9TriASFfbeq4b z@Zy^!d=b=W>^{<9)_ymjV{4*&o#UK+p7)>rCcf%YF-3t&roD#F;M)4?Ti{d8+vmL|fHBE}#D6%-XNH6UVE zV>Jqrci2L-7Yg7I)qtDJ3-0zO2ByD{Nc_Ci9xLmzDj~J}cv;<4D-3$IzC_dajf%nP z>xh%`LECy_L^aO4C2qs|?@F(?Yl{M}cLI@;Ye`V?k2(-y*ckf*0P9`La_v8mpYMSi znu5Nb-CLP`S8O)kvwkmWbHP&cH0$W%KZVi$g(C85!f9FgRB+0c#Ao9^+3~;5SmuOp z0AlqY1v&QSkUf-h3Ls8^(;8&yL3bSh_zor}-p$xnoS?`zCkqAtk{MoiAen|e6}vs| z=@dmeo9dlhPJaL0R0L@B`J}SCRT^IJ?yLm9Qway%uG0oEv1ad*c;kQzi&6o*H%&m> zncEfB>7Gx`;@v9((Jj%D{xkckg3Ud)oS!&*4{m-Sci)-ETpFD&K=H^5>Rx~U@vrr$ z%G7|KAN6EWZKkQzbWNqS(XJX1f#5z;#K?Y8Jap(cTamDVsFJhxlTEXjxL@f_ot8t# za`khR_sgZi@Ku4vRdAtFIP9^<(LP`YMQp27uOser^0$t}QXY{hHoU{V5b8iuQLXQA zfR2JaeR0af^+1VK4nqU@9#Lnlzm`}uW?u&m=YjifJp!wu$4|1|#A)*%K$t;*S=H+jRQ zAN0r;bqJ6gzeG4m5-5@azBqjg@)x^s5^X9Sczy1sLd?~(jr<dcL3FL7e_#Z zL^-?euhPkAY0c;Zuu65@ate0;!R@Gzfiuz@LBYCJe$^n0X4dOebd>W-Ngeh5Q;_B7 z6s^k=M!_W4Ng|(FpH;m9EXE^79-Kdx(`o@YY&_AF=u6SRw3K3!S94UUt$~nq`&Xg~ zQ5C^?!}qMSsfZ>DI|P8o$h~4MiT~i;WG&B0B14$KU2+j^W`nm zrxhH62>bmExib@f$8W*sMx9ljrW>GsXG==U93(}i8btJtqp*+;GloAZQV3|1qE8Ix zOpFiLy9%w7p=Y>##G$}ErebkUfLl?vu(qee^7QWooA)0xn5y~ z!V-fa+PzjBhIh&>sPjw(*(xYAH1Zu?Xb+PmakS2iG`Lsnp|r*ZkEK;o!EF9gt4Z)U`a^Uye*7}6VH44i?Aqq7TY9em~!!Wr^pFfI9co@Zn+)tR*kuWO8CgYOQU+MA!x} zMjzfMn%!|LIUW#X@p5F4|DzSK(|S3Al*+8`8A>2nDgpxI6Ao`28LvakKd;3;>wwXr zg=}Lox=$fc!&$P&$L>rQ!33h?5D24MztJAfZ}=>oem&09K{+v0ZXFynH^ZKgWIKYb z!3JJUJj)?;qUag7{c>VsY=z{2V~I3Kn93^yXYT*+05wSj_=v=X=dVg<%I{O%ZFasw zCEmSlR6CwkamEP^m1PLWKcZZ!aC(&W3;eh}>(rH!duu}CiA6=m>$K{sA_aOzl<(X8 zJ9f7#X)sykzvBWAQ$E=f$deWv333}9I!wEaz4O1>e~q+9tmN&p3leP}JR zh`Ko7b`NUfpZ*^N`pU|Yjvr_PuS&*BG`b0rG4Z_k%lWiwBE#^w4XJjv%^94?2ztLG z(JSDN0wbv&L>H4g9`zkT6nXeqlc|*P2QOe}YCddn{lU*Nl68;uNLFZzCdd!e*&RNQ zwJCHOV@6jbVxHC+-74V{R`jtRdGV>d(GKEcOC4~o0`3`jJj&X!+jtwT1h{x6P=Gu{ zzDl$1D=JxpT>r1%Pt{|)Pi#nXqH$C;88IkAdV5GWJ~<`bqufpb8pSQ=!?6Lo4>o~4^``Z>W~~` zOE;#WX6*Dm_Mdh1XMU|oaHqnnntnJs)P06z836+JVo_Ooh2T?sY;npI%V9c{y`&q9 zqNJs0St&64uDHT7-Obr(1*x$Y*jGLp<7B<-)R00}3DbqKMvG6%g%8kP@_hz{X=b?E zBh_c{0j56SG$~isZ!O@sV4+M6B#DUAqu88T3G*Xzh||o)j~nDNxzA#5iI#Jhl87ho z+DfZ@q)G!@HMZHYk4AQI-R}JhK;w3KEsfwA0lul2YNk z4(2d62?V908heuqNAY9s#4aU?#bg|AG`QzvpmuyQ9&*A&_Vk8car~!w7qpUvKFnbGd9^bmT*$JSRb$G zKgpIPE(}o6N zJxO|KHU)|zBqoLFs^f6wqee^k$~K)MQal}@cG*C}jfCwBrZS_i!B|y@P*tolZbh8TjF4w^6nt8nezc#)a-; zhtqbvP&%4yONO=~@eLNz?8)b#=k^l^Uy4BRCt7M3wNXlFe21^e(ZHH}Mw%0wD-f zxB!}2tPSqVJ!oTFs&!%qSS5UxTNnfiIllLA1=1&l?d53^5BeV`3<}gbm6eW^?gqwh&lZZD+O%Z^KM7IG zAQ%?!M2eX}@MqAOWs{Q4QRPoHbaSjd-_E_T`Ml)@dD6){Ejf8U&YwU@*i=%@z>uX!c)2_svq^g=4 zpaH*g|7Ds44Z&}sLJzeoH38B0y!9%v92Z>CWTn#`f8Q0Ja&$k5_fkoDO~bA8i^pk| zhFZ$MEy(6XjqzGtFISeluu7sP_JE%)6FkjW>&AKQpz(H_UCm7$c(|)Q7v_$X|Mtq6 z8`DPYD1F(2KkL${^|ylA4;zm}n9LtKigAeG+l2+kc$?J9karCz^V(&K{{|#L ziMTuQ3o;S!sgrE~a~RbN>Wq#w=lBX!>A*~=bc8$kVwl>7kr1n&~+37jzyVcyb)e6Vo zlu$2IM*M}-Z*2N~kT6jX2vSD}x&0qB4aRX^;N6oxq5LZ&nTN$bE(+lgP&MeGp=gkg z3b`Ssx5|X;N6C9)34bbPlaow(b@LoSiT~`M=d~A&9gg*gSs?Zwd2o3q8mV4Q3~x&4 zwkRUh-4tnyLqyBpA4X?cYzywJxc@isjX=^V%4Zt9nl!F$-TqG5_`FGE1bG6KKgZhb zrE&z=rfuiJQ7_6P)o-9yTPBrdfR#6q*ge8xnWnU$f}2}dL8XC$<>;3 zFG+V?6jzysf2~y>6Tb5^9~7twhh##c6iQV7!E*}BkZ24`DrETsvcFiF!*CVta$4Ke z5XcXZDck!1qPTXC=WCyKt_971IWtrlJoQ_7N`Q)Lq%eYs!+_1oE^i8%MJKkv#3U2o z;-H9*jd=(Tl@sWSMkTdm$c16DmLW3~(-mXNqoThi)q)C1PeBsl*<2Qz~#92>l_lNnJVg?Z* z4@O%c{x7&>8&$cujrsX0(Un(v?^pgyYwYY3dxajcUbZT%o%JD!uvdIXPAEY>#*=kdV5Tzr3KVgg~Drh3F*j5(n#!; z(QRDlcaB`lC@n*a4a@22lvU|@Hb`=@PX`H&!O8k zT25?V`+cKLr-qWm5%1vE0=TZNa|p^~e7fR zeFed+Ca1k@`q#fe^V+K4N!4S;U5d$`kDX6=*Gk#!wRZ2nP^ zvcM&u!_<0h5gf;I4I9J$(WN^ZNzo-oVU`WsvPeCOfXeNEu&wlUb#xStmNVLe`wZGdXf7{zrc-*=;)x>*CRg}x|13h0?9MY79OSe&T8a( zSz}cDfTsG3A<6i0s6nMRFV}dYTMR67KR&=Po=%b?Y%te&0Y;sRsQs5SjMlUWLMir`qXU`_&4jKeg2MKa>qj ziU#gK;2i<~Kp-^_8xt%hYBNWnQrsyY%r>X+rU$xT(kS$TcUIYwYCI^VG$e4-Hu2#79+MKGyj~g&C&21#HvW z-}FgJ%kA%r77`lJ!%zs5%&Z+sYx>LDQ|D4l=05I^fIf_2O5QCXF@4x@i=6%d_K(j? zQ8l^4sfwN?;=9hnN*4A1k|P+@fHBO!JpgXM)j9_mtOq1tisAd)B#L0sE_Q zqDV10wJziet?WDuS0y`c)g`}i($X`j7MlFCD@7|b6lDg_NZT8+5?>c8Npk+L7XUSc zj>iWR8Ytv5&BRYZhobPK-tKql9Qn_0cWn-ZJ3s9gdKg}{hDW&53tL;%$)B|Wl6u7) zP($|uAM-s^Pm4Vblq5^89Dh)h#AEoGkT9&OU%6Are7$qGA*eqY*g-%<&d8UP`n2I! zvU7>aG(01HILLtcMyA}_9zwt;$R|QzB_D5;s@xuH%b|X%)~OdqX>g&JSY4HSPtcwv-sAJ* z50iSP1!O{sXui;y>hV!b#$(g{mVJ*QN<9NEXx^Ki#9WE;tNB#z9(<8fSq5*X`E#m_ z(C5J_u%9l6Z9mIv;NrL-j8Uk}2w;Q%*&?S(6y}U|*aeR&=GQjdg?WGP&f1K}Li-Lb z>#NFCN-;T+j5HFo|F&B%D2*tOYyx~sbHG&c`cbm%2rCn$kUA(4=h(Jk;6D61wL2mB zx{@r_(^p)Mdm)Z`Zr}K5tAVc1bi-}v1>P~e<6uY2%Q1V4+4heU7Vt765wVz)WLJ}! zvYxTfN%wi?u_reSPEJ^-Jw|G0gE^0D|Lvq`N4BExsh`)$v? zq}GP{MT>R5U>06mcPOWUumqpOr|joxb{R}Bp)`E~7%YEcO|>vk+@Xn zYn|zm=AlSMLqN7;ZEMF8Qqp4hl&QiKxl%RkV5q;K9lt8c9oe;|C)Ub(vPZcJkLrfD z_1)=H0LdA*!#X3eIpH~vp-1`#+0%V2d)aWoIKm!^GxonTY$}h4@iJvjI{!Y9Hq9B% za)&jd_$`jUApAh1dobbRY_iQ!fV1Xl*lh5t#B12J;-^1Q`5sX!P5HD`nO_il@?F$*B|(~u6|rqa$5N~ zxp`(GV`b--#FWuOdv1-ku`}qizTy)SSKiBW z&Qj_~J%#N=$ry!_oZb9yAC$Ht!UWWA>&ZdXmc&%boecR3`-otX+D@8t#H;B6Jmjtd zw{XVGj_8Zf`0Gna;r)xtksR^G9Qi$QRAhjP2}Oh2_5$_KRdC7;n?&UT zC6QX=5Mqxf&turoaW97tAN=6UH(KFPG+*K22zz<@tR~SYf+LuBze}{luvCwpe7L!R zTUDHKrTuS=g8INucF~NDX2-|vASFHdm4S4#LOX_(DhNWq$5|SzwgeZ=uf*(TA_9}LlEyj!G3JjK zu&9a!ES%CusNn^>trGJ0(4&AlBdV8_&6*w;JG|!`?nJC^v!)4Ckesu_PD}%TeIKub z5Hr!~soeCJ7rTK_^}0d(pjhSRRNos=I(5rgQ@wJnX7X9FIs5va`0RyYTbGmwS#(OY zOx#f$e!L|mM2Ix^@9myrizsC)I}JXQwkb}bq3bq!cpE_l?Z<$5VVbluFFE>bK<@Xu zye2kwj(AVt;wKrUk8OOdzvXg4h3X_8vZ^!DnAC3!O`mHGjn%6v{@!|Vzk0dXVgDRq z@Ur5mKxq!*W^Ku%eO6^7Qd$VJ#HXwI5dqtn=Z%4oJ1Y|&x)qr_vj8i%v5IqcMh)|H zzYmJNwC-rHij9K8@U<XH{O8zwZ5L-rHwgIBP(llQ@b|rZ_q*H_gmjA-B02`zq-miHEfxr&;9FMA|;d5aU+!w zN_WBP^u|>hgW>7C;T7K*3taoiz#J^a1@AyTYcwNPa%BR1H9a`xs;+yc2rO5sW5poERVhPs9M@nAJ_I+4jf zOS1^yI<3)zc2KuI6Qg^w^vv$>`Egav!F^|`Hy2C2FQ=TMzG|R2pDY9*e`bM#31onBUoo>v_m7am}siL7Lxb;G;(=6S4=RO1#xcaZbk^TM=1LwY<7XQlyi65~Y|L z#Oc-D*TnKCWQaMzQ~bC0VTZx0^o6hiubDTuJNo@3N~1FSPfZley}Mk~DXOz?D>Gb2 zTv67vTZ| z`M0!4sT4Nl{)gltd7!89gDa2aYvQhv22)hs+mrStke151AzrsL<*PDc@$2ZvrdY=I z+d)w%<)t9}2w52VNZ0|EUeX)7nb+i+l4nZc%)}<|QXzURjL}49+*`bk6fg@bx$+Oa ze>rHI*yTg#!+gvFA;+$HMIxg6W7@=Os2@K{`IHj;JgM(V_J%9|HeTo9PZh7p_a?9g zbKRJG8`nAa8%oJ=^gHfp7Zo)5ndh2u?8fuP(T@jC#;Z8&!c~|^Iw^^@YoXpQ+KetrM37eOCX0~39A{IbGW|I^NAvR$7T)s9bwI(Q4~>*J{qy0zl;9be+P z#7^}h^~HpBD*UfrdS&2eV3DjWk#uo3L!Z`QMbD)n!)rJ*RNaJb;HcKb=~+9=h$pp= zn7|6jAT^)9`Xd0B_+)nH{e~x<-l|(=NO}0$ZOO!zTj{0?tyM1L)t%3-oAJ%TB)bi` z-g(mAOAp;N5TAZZGavKIIa5Q*$mtt|6QBG1!(nkPQ5t*7&3%6sLnZv<$v(K(wg8Pf zR&nI|hy;oUl}yu=6y|uovbzglkA8GCDYRk~t2K%mpI}9#*ZT5}Uc4&u(-1>%|?9NF=rg#pCt(DJxEM|RH z(uyDJZEhb8;zRIg=P|jxuuZ%r;7_mcHxtCqnA|%=CenHm(K8RlhW&`t^u6Cbi-@Z) zOk|v9d~7EtxZV5ANk=)tl|E+~g?=ukU+Z{%*@;l<(Viq>_R`t@A#Vfgc>I{=s#UhF z-R{;o{c;C)Z8?%Um@1ng@^5Kvu`p{HX8OzOrDfNUZEoT5UD;>q7IqlBVn(=kKwl$V zLX(I9ihqwE>d^#aX3WMwx!zRy$1!lnwQL8KNqG} zkVtk))Vzu$?g~I#J6$j-EgjMQH5jEqbvc5oR+zMnp1sxuJn3&-!p4o5wh3}FhQ^q` zX?h=>!Lolbxs32=IIP&Din$&2xXd>~|h}Zr@gDy&N zf~{c=Lob<)FD^GK(+CPn;c*b45%I>5KWVbXM#JHvXwDTUl%oAd&NTO$#H4SIH_E!& zzCPg04y#rxlp#q5Y2p*Q*~x~`qmBER zvA&cZ^<|i(6sDBA`!$EF!;x+HykC`m+kMNvx1sk^7A{9I@%oHhnw_`LqRfP76G&8W zA|9v#C<)5?fN+8F9rWnFshCTb^3fJ!aMk~9Py2N>W>?dTdx*<+ryXqoq*=w#h=>fZ z=HFA(aIwe+Nswn@GFn5b>=Nf98ZUcLnwbs;;l^&{4PwgI!D?;CIjjV7M4%ixp! zDf3LQvE3wL-)ovpUs`}_S6GABU@snLb2GOLBYG$RNHe%6`s`Q zE(yz{SvFz{b5o6DjGvj2=(2tFGm6;B+~O1_Fu)(CNf9Y4d71mTkh`2dScQ;5$^2j- zIZP9~2J(W{#~MfU5V9a(m2llbx!}%Qu<93wO2uhG+1JAH*(6UXR&7qA+A;zD$dl_m zTtx{n(Q2|L9?>IF#H~`EZx)&~%PubVq$IgL>D$^f6Ke@Iii^q8@gApt@aPg#C)e<3 zNU7r~099BXw+V5J3R5z*JZ^Pb9iG~09z5`w#$LOIP{N6q{tzE;D?IW1syB;-s1-g1 zMB&-?5@b)dmr60~Pxn-`3mu<~6VnjyyQExAy=YI#p~SxiFaGGdP%wV7?2m#&4-yoX z9SG?)NKibi+8yz1*9xtiikeakDv6)4z};Drp7WA=#KcDJUt6#;nw#9=2Sfx)MBWty zUbj1s+f;w7v&0s@un80tS-*{LYYj8#?J7JO-e8MvO$_5|#=hkUsW4^zZE#N@LkYPe zYmqrPqCh!Rk+pBQe)1mSGqXZD{Gn}vmmp%PJKNU}v`_j;<94J5uz3HJgujnDbnLvjYwFMp|(RL2a? zNbva|>Lvx{_oWf1%LfKjjV^m|D0V*6P>l-{ifGddC{leIeL-5&IV;vC&@?_En>b7R z@;Z#iW=#+G{dC)-^>?p$hfw|iD;A4W{Y`xaV|kEYnR>hDPnKm^n*dak9^^hTp0dac z;0e^>%He%geBI6NCvPH`unyU#(=j4yeTyd5zfq}MHSR{sZr|n|&#CsT4S9Y@vXg!+d4yX z6gu+fPqm21RNU`;%>c^6b}C1zBPjuD>_L$fQBkO=!`A}-CEKE?QngamTX{PW{V-kc ztZzgv3(DLh^__1ik~W{Y4UKfslF@78uae+|q^aSD6L+IIHAJkc3LIH6y4>USz7Br3 z@hBwE-TRxl86#Z>oVcl0(N)+!*YLIwMrXm}? z_Wfp2rampRK65xko$?uXjK5bOfXzMIsw`xPj^rxQ>N|UiOwgWRG6`FV%%k@)t2#G+ zIM0t9nncuzY`%OY^bFFYo1kolAfd>x8%UkJtSMI}_JIWYxNRYr!iii;Zyt5{0k&&L zdRGd%6Wbg_^q!z}Hfh@R;Mg6@*&TkLdr6wgSlf1MV-DSqt|aw=c$>Z5&wj*N%2}+b z6iaia%P{V^;+rfuVgVLqjc^~EcONJU?(BpuoZUG66h%S59@f*^^W^bn64kFYHF-0K z=jaI7x@${$bfq>@L~yij|}r@t8@M67sY>D}z0Uxcaj!mnjV-%dK`wEzYdB*J2J zW;eO$W;cV@?Xb7EX(TUwUMNeS$)hvcv=E)aRI2_Wdr%TKXT9 zaCNaK#<^t8LX4WxE-Us$$Z01?f%>SdH2XY2*8#!@qFb`I&qw5rn@1+yB7$kNeU^j1 zVY}yyA3z9j-y89Yu8PyIr7RftlEPI?i1*z4YBg#XM zHV6GlReEOIes_eBnAlc6Gg7GI82K70!2F_F?f6mbmvQ)$tFK< zHcVT3(zhIpejGIRQfvIsurI4}hx~>l>s2F3Z5Wh9m;SI~)C>)u0i2)|fC*~Fm|@@0jJi0B)P|PVM9MYuKK9kvJtU-kmgb^Dt1KjlN(2-g%km`?Wnpm~ z?=kz8Ubr=z@v*9K+ID<`_m?HOV{E)%wsbAOD#4))z*-ZdHEV|!`_11tI-kFPZ^1te z7mf)@KWW-P51#jN=alQbJ05&!Rz*<^m#i&_WItA+5}rH}r6R^Lu1R zYb-|#(&`VvG3O#8vC4z8M!LeW%}I4nsOPW9}o3zCjeKgEI&gw3wi>>B;RkpQKfy)_-0=jBdoso%HEwdp zP8O9HR7gjttW?ZB3a%L1^GEpdiOJEPffb&kNy9A8@`C{;ZobT+!7zSTcJZ!{lbFR4 zy^S}I*CclPYa&8ksGQ3lf38z3l#I=ft<$zI+}Eor)E*JelYGuFEBd>2j#1l=gc|)s z%#^9;4-<%XAwdCPoyxBt?9IXjKfriY4zy!Zgbj$0!hc;`Xnb;F!y-C*5PtiCv3Uwu9j1?GfKOT1u8dANf&JDLmXX zim%!wb}?WNIm^;@jInV2NJ%dxI}KtvNKl_5T$T7=GzS-a4CUFdGmV|VYx6{Q05&bB z*42-n-4?m-8%`P;-*0%&jC&PCN;lmY5U!f#6d9gEy5ZnIVRK_|!lFKn@8=1!M>Elqq6rP9C+q{?Wu6yiN@wh?d^KOyzU2b|gMUZPPJ22s zM(U9E9Vq=tGg^e7dS&1D7$uX|u}W<+tk21S)%=i1?~&!K{_!fabGaVFnJ{NkoL(x%&T6m!byIVhqo&(&O@=|mk`{y?#7b~mY zt-B-(-)+yd`sXQ@5#Uv!uU!ml3VNudn45SF{n|w7&22?_jUqZCBB~h;Wz@Zl2m(*R zk3rQcS&>uOI8+kzzJdje4Vz+bg{Z37l!&B=nMdL{dk~hP9f<`iaw37QH)O&>>pAXQ z@|v=FGRA=DU5LAC-9OJtA9GJ~9$X9uk{YQX>}$%xe83=&%Rx8(8?N=*gj?v273lR$`8Ug&lr>W z>%hroswfy}F=YZGMiIF(}cR+4Ruwv?kw&u|DrG)$1k z#0qPw;G>h|!wwHqZ~94jVXnP!`1Kc=q( zU=*B0vL^O5x->4^KXyiUFJBZ$TybW@GCkGmSSH zIkw3u4J~C2G%fZ+36wBllI5~2icgxWlCjfw3kyZCd>=;Ns?v`ZraFVV|H{Wh|Aq|- zdPkV@{~34$HRCfaEq2O3pKcF)Y{}h8o1j}%v_ER7^4~Jmc6=Sb(slihyQ@y@&&PVs zX-PNVD7VT7ifxB43)#nHL13cU`GL*lhsz<)F57@PHH2Fkw)bA#7j-BSq7}Rj}E&(M%Q4xQb(&O zeU*@@A#8?gBtnG*Gjd~+N(c?jLNh(5OeYB{)Z#jWP?9Z}NiABV=ldqOA6!)U&xizV2+10o zPLC!qefHcW8wwqV6^|yhfeq%el5l!n2i)gn{EagRBGP{o+!;v?>iL8gBrU)M*D(;c zTLYT&0jHuYFI+o!67~vd5I}ntwgBAdEwP#Z+OeP+=+!m;c}X+E@34R}FYjEp%QwyI zK-uB&UR~b-c^J_Ja#QA&i$LgLHrFfT9Q2;Bm=Pd+%2mqUYy9^KwQ#mSQni%=VBrfd zXdq4yAP}4B1lSnLE=w%DfYT5r07_!308EQAcQp}=Z!iD?fXoGE!7J=Ip)XJZ>(AA7 zg8q{D7lq|baE}8&t_P3uE>oSMj+1`0l zfUCCjS=$n8-;CBOe_|csn0!wtgQ%uRUMDP+AFK%=mr7sXO*2ws^Fbe;t;z=;Y03z1 zQ3SpHd%knEq$^%}+l1eusk+Mld)I$W@&9)YFFAe!5KTb~VEZq-@_gZfXN`C7XVn)P z-2lFA+5YFSs%rkI@y*Z{W@z@`GTL7RcAS2L;np}M=u0hiV$GP=9{|z|6n!+`)|c&K zKP^l$kS0*ov7fbb4{+3*BSmEM)35y7V`K^72CyJB#74LW>q7!SRA2;{2fPlmkK2mo z+*-E^>B5@*=72tqd4u=v;zs+9|D(fj@wNxs*$;>L{#iH$HHg*eE$cNU!N)$81%N%Q z7?xOybpq#L5|`Gt-G;9{XE;EI8+gt5^+7@nEQ574 zZ1n!0*01MouhT7rdjWTfcl2<8Th<1+wdy-I_Cpr^cl@jx2!>WcJ2(p_8wOc{fux?t zn$5~R&|EqTq_SnBbc0;}7pehN`)%+)@)=mxoMXE$JTxHiwha_Jx0V884FP*1TJJdIYr@v(><8A=*ZwcIXJjWq5~W%CI`XU8 zQe=i_aXg+#|tPSM;w#(@>fHLE*`fz(4!Ge%l^7=3}Iv2vi-F$0=9p)fNcc5uSiU ze&Q4OfgC5G*Higs(#V`Y@xRWBMFFgmq&twd18onoLIQq&`f7AH?REuFkL=w5N0@7S z`-Wi^PMTX{QJ5eoUJ7WI8s-7%LxdB6ftOpJ^c%-})BkgJpasfnAnikW?c1h2!Hh>Q zkN{2)d1Ev^8-R&Afo)ROM}?j9$llLnJCb0%egYsG<^%nSSORi(&ZTb12;Bkp$f_1O zRC3_ove6;HSi=}(i&(%KZYnMi7>_*%_}|bSZ+lpvaiRE$2v>`aP=Qmqsu&%%&LH`ay!CQjtyHwzXLHoTSFDT>rLS4E6X4bS% z)1~=)YQwu1t{5#brjc${?+N+yb)6KOz)!%&3>+#O0nvz5%#Dnc*g>d(>gB8dEE7(! zOcVo$!9_yzPeWdi{vpIqzIB~{0ol0T-Ac>Tk7-6A?^gB(Ad{;z?rTr@T?YU~r<1+! zheseOXjI@0REdqWmK*1s%6v1(5aN0aH!%NN)8ql$kkW5-;8t3j}t3>qk(tA%gF-B;i2jsd!;Eh5Le+k;ST{vxMKsM zJZyh;q{{MVFvC-dyM&09uvI-+K=sDTFVf-lf73#^!EXS158HNGfczJIpuocBvz+7v zconLqtOCzlj?kb~s^SeeIg7SG1?$dCS$GWL&Z^VxC0%X9KG!SR-*vT3bFqCDTP|~c zFfLkByFReLjL|U)1h%!IRWVAC!Z`=!)Rkf&BFDL~TMGD&#gwMCE#Ek7JeqS}1$dBu z1BRtj6OxEfz4?EBExi>AX9CnS-deX4DY0y!U0;*f2?hP|TTtjnef3yhdQaJ~Ww=Zv z4M`}JT{$v}%2W}DHcR9|JB3h*75^pF77|8_%DoOzbUH-|?aF_wCqf~X+k=3RVM@vZjKO(P)+v# z+b>AaA5d1JKq#8~-&X!(@UcumxC!;ynOH)Saz6G + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From acc908257d3f6913a6441be228601d8e7131bbe3 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Sat, 6 May 2023 17:36:15 +0800 Subject: [PATCH 028/105] ipvsadm: update scheduler help text Signed-off-by: ywc689 --- tools/ipvsadm/SCHEDULERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ipvsadm/SCHEDULERS b/tools/ipvsadm/SCHEDULERS index 84ba2997a..69298e800 100644 --- a/tools/ipvsadm/SCHEDULERS +++ b/tools/ipvsadm/SCHEDULERS @@ -1 +1 @@ -rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq +rr|wrr|wlc|conhash|mh|fo From 232bbc3ef46dcb0ba1b551d33cc1728385d46f43 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 8 May 2023 18:18:49 +0800 Subject: [PATCH 029/105] ipvs: passive health check down only When up_confirm, inhibit_min, and inhibit_max are set to zero in configs, the dest-check inhibits the backend on failure until it's removed or changed externally. In the case, addtional checker is needed to restore the backend when it's available again. Signed-off-by: ywc689 --- include/conf/service.h | 16 ++++++++--- src/ipvs/ip_vs_dest.c | 28 +++++++++++------- tools/ipvsadm/ipvsadm.c | 32 ++++++++++++++------- tools/keepalived/keepalived/check/libipvs.c | 3 +- 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/include/conf/service.h b/include/conf/service.h index db77d4bf7..c6fbce16e 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -106,6 +106,12 @@ struct dp_vs_getinfo { unsigned int num_lcores; }; +static inline bool +dest_check_down_only(const struct dest_check_configs *conf) { + return !(conf->dest_inhibit_min + | conf->dest_inhibit_max | conf->dest_up_notice_num); +} + static inline bool dest_check_configs_sanity(struct dest_check_configs *conf) { bool res = true; @@ -113,14 +119,16 @@ dest_check_configs_sanity(struct dest_check_configs *conf) { conf->dest_down_notice_num = DEST_DOWN_NOTICE_DEFAULT; res = false; } - if (conf->dest_up_notice_num < 1) { - conf->dest_up_notice_num = DEST_UP_NOTICE_DEFAULT; - res = false; - } if (conf->dest_down_wait < 1) { conf->dest_down_wait = DEST_DOWN_WAIT_DURATION; res = false; } + if (dest_check_down_only(conf)) + return res; + if (conf->dest_up_notice_num < 1) { + conf->dest_up_notice_num = DEST_UP_NOTICE_DEFAULT; + res = false; + } if (conf->dest_inhibit_min < 1) { conf->dest_inhibit_min = DEST_INHIBIT_DURATION_MIN; res = false; diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 8ff051616..86b8e3ecb 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -461,6 +461,7 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) struct dest_notification *notice, *notice_sent; struct dest_check_configs *configs; struct dpvs_msg *msg_sent; + bool has_up_notice; notice = (struct dest_notification *)msg->data; if (unlikely(notice->notification != dest_notification_down && @@ -472,6 +473,7 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) if (!dest) return EDPVS_NOTEXIST; configs = &dest->svc->check_conf; + has_up_notice = !dest_check_down_only(configs); if (notice->notification == dest_notification_down) { if (dp_vs_dest_is_inhibited(dest) || rte_atomic16_read(&dest->weight) == 0) { @@ -504,26 +506,30 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) dest->dfc.master.inhibit_duration = configs->dest_inhibit_max; if (dest->dfc.master.inhibit_duration < configs->dest_inhibit_min) dest->dfc.master.inhibit_duration = configs->dest_inhibit_min; - delay.tv_sec = dest->dfc.master.inhibit_duration - 1; - delay.tv_usec = 500000; - dpvs_time_rand_delay(&delay, 1000000); - err = dpvs_timer_sched(&dest->dfc.master.timer, &delay, dest_inhibit_timeout, (void *)dest, true); - if (err != EDPVS_OK) { - dp_vs_dest_clear_inhibited(dest); - return err; + if (has_up_notice) { + delay.tv_sec = dest->dfc.master.inhibit_duration - 1; + delay.tv_usec = 500000; + dpvs_time_rand_delay(&delay, 1000000); + err = dpvs_timer_sched(&dest->dfc.master.timer, &delay, dest_inhibit_timeout, (void *)dest, true); + if (err != EDPVS_OK) { + dp_vs_dest_clear_inhibited(dest); + return err; + } } msg_sent = msg_make(MSG_TYPE_DEST_CHECK_NOTIFY_SLAVES, dest_msg_seq(), DPVS_MSG_MULTICAST, rte_lcore_id(), sizeof(*notice), notice); if (unlikely(msg_sent == NULL)) { - dpvs_timer_cancel(&dest->dfc.master.timer, true); + if (has_up_notice) + dpvs_timer_cancel(&dest->dfc.master.timer, true); dp_vs_dest_clear_inhibited(dest); return EDPVS_NOMEM; } notice_sent = (struct dest_notification *)msg_sent->data; notice_sent->notification = dest_notification_close; err = multicast_msg_send(msg_sent, DPVS_MSG_F_ASYNC, NULL); - if (err != EDPVS_OK) { - dpvs_timer_cancel(&dest->dfc.master.timer, true); + if (unlikely(err != EDPVS_OK)) { + if (has_up_notice) + dpvs_timer_cancel(&dest->dfc.master.timer, true); dp_vs_dest_clear_inhibited(dest); msg_destroy(&msg_sent); return err; @@ -536,6 +542,7 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) dest->dfc.master.origin_weight = rte_atomic16_read(&dest->weight); rte_atomic16_clear(&dest->weight); } else { // dest_notification_up + assert(!dest_check_down_only(configs)); dest->dfc.master.inhibit_duration >>= 1; if (dest->dfc.master.inhibit_duration < configs->dest_inhibit_min) dest->dfc.master.inhibit_duration = configs->dest_inhibit_min; @@ -565,6 +572,7 @@ static int msg_cb_notify_slaves(struct dpvs_msg *msg) rte_atomic16_clear(&dest->weight); dp_vs_dest_set_inhibited(dest); } else { // dest_notification_open + assert(!dest_check_down_only(configs)); rte_atomic16_set(&dest->weight, dest->dfc.slave.origin_weight); dp_vs_dest_clear_inhibited(dest); dest->dfc.slave.warm_up_count = configs->dest_up_notice_num; diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index e36293483..f08a90c2b 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -442,7 +442,12 @@ static int parse_dest_check(const char *optarg, struct dest_check_configs *conf) &conf->dest_down_wait, &conf->dest_inhibit_min, &conf->dest_inhibit_max) != 5) { - return -1; + memset(conf, 0, sizeof(*conf)); + if (sscanf(optarg, "%hhu,%hhus", + &conf->dest_down_notice_num, + &conf->dest_down_wait) != 2) { + return -1; + } } if (!dest_check_configs_sanity(conf)) return -1; @@ -1701,9 +1706,10 @@ static void usage_exit(const char *program, const int exit_status) " --hash-target hashtag choose target for conhash (support sip or qid for quic)\n" " --cpu cpu_index specifi cpu (lcore) index to show, 0 for master worker\n" " --expire-quiescent expire the quiescent connections timely whose realserver went down\n" - " --dest-check check_conf config passive health check, inhibit scheduling to failed backends\n" - " check_conf := disable|default|DETAIL\n" - " DETAIL:=down_retry,up_confirm,down_wait,inhibit_min-inhibit_max, for example, the default is 1,1,3s,5-3600s\n", + " --dest-check CHECK_CONF config passive health check, inhibit scheduling to failed backends\n" + " CHECK_CONF:=disable|default|DETAIL, DETAIL:=UPDOWN|DOWNONLY\n" + " UPDOWN:=down_retry,up_confirm,down_wait,inhibit_min-inhibit_max, for example, the default is 1,1,3s,5-3600s\n" + " DOWNONLY:=down_retry,down_wait, for example, --dest-check=1,3s\n", DEF_SCHED); exit(exit_status); @@ -2142,12 +2148,18 @@ print_service_entry(dpvs_service_compat_t *se, unsigned int format) if (se->check_conf.enabled) { printf(" dest-check"); if (!is_dest_check_conf_default(&se->check_conf)) { - printf( " %d,%d,%ds,%d-%ds", - se->check_conf.dest_down_notice_num, - se->check_conf.dest_up_notice_num, - se->check_conf.dest_down_wait, - se->check_conf.dest_inhibit_min, - se->check_conf.dest_inhibit_max); + if (dest_check_down_only(&se->check_conf)) { + printf(" %d,%ds", + se->check_conf.dest_down_notice_num, + se->check_conf.dest_down_wait); + } else { + printf( " %d,%d,%ds,%d-%ds", + se->check_conf.dest_down_notice_num, + se->check_conf.dest_up_notice_num, + se->check_conf.dest_down_wait, + se->check_conf.dest_inhibit_min, + se->check_conf.dest_inhibit_max); + } } } } diff --git a/tools/keepalived/keepalived/check/libipvs.c b/tools/keepalived/keepalived/check/libipvs.c index 16d7ca8d2..700400c29 100644 --- a/tools/keepalived/keepalived/check/libipvs.c +++ b/tools/keepalived/keepalived/check/libipvs.c @@ -169,7 +169,8 @@ int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int opti } } - entry.check_conf = svc->check_conf; + if (dest_check_configs_sanity(&svc->check_conf)) + entry.check_conf = svc->check_conf; return dpvs_update_service(&entry); } From 9cefc1bcf69653654218d37a2ebb786074358331 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 15 May 2023 14:45:49 +0800 Subject: [PATCH 030/105] fix use of uninitialize variable problem when dpvs-agent enabled Signed-off-by: ywc689 --- src/ipvs/ip_vs_laddr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ipvs/ip_vs_laddr.c b/src/ipvs/ip_vs_laddr.c index 080c9e260..b6fca2810 100644 --- a/src/ipvs/ip_vs_laddr.c +++ b/src/ipvs/ip_vs_laddr.c @@ -501,6 +501,7 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) struct dp_vs_laddr_detail *details, *detail; #endif + err = EDPVS_OK; lcoreid_t cid = rte_lcore_id(); // send to slave core From ae1820c376452722258808ea016c970e4640b84f Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 19 May 2023 16:40:36 +0800 Subject: [PATCH 031/105] ipvs: fix service flag conflicts for synproxy and expire-quiescent Signed-off-by: ywc689 --- include/conf/service.h | 8 +++++--- include/ipvs/service.h | 1 + src/ipvs/ip_vs_core.c | 6 ++++-- tools/ipvsadm/ipvsadm.c | 10 +++++----- tools/keepalived/keepalived/check/ipvswrapper.c | 4 ++-- tools/keepalived/keepalived/check/libipvs.c | 12 ++++++------ 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/include/conf/service.h b/include/conf/service.h index c6fbce16e..e55868c14 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -34,9 +34,11 @@ #define IP_VS_SVC_F_PERSISTENT 0x0001 /* persistent port */ #define IP_VS_SVC_F_HASHED 0x0002 /* hashed entry */ #define IP_VS_SVC_F_ONEPACKET 0x0004 /* one-packet scheduling */ -#define IP_VS_SVC_F_SCHED1 0x0008 /* scheduler flag 1 */ -#define IP_VS_SVC_F_SCHED2 0x0010 /* scheduler flag 2 */ -#define IP_VS_SVC_F_SCHED3 0x0020 /* scheduler flag 3 */ +#define IP_VS_SVC_F_SYNPROXY 0x0008 /* tcp syn-proxy */ +#define IP_VS_SVC_F_EXPIRE_QUIESCENT 0x0010 /* expire quiescent sessions quickly */ +#define IP_VS_SVC_F_SCHED1 0x0020 /* scheduler flag 1 */ +#define IP_VS_SVC_F_SCHED2 0x0040 /* scheduler flag 2 */ +#define IP_VS_SVC_F_SCHED3 0x0080 /* scheduler flag 3 */ #define IP_VS_SVC_F_SIP_HASH 0x0100 /* sip hash target */ #define IP_VS_SVC_F_QID_HASH 0x0200 /* quic cid hash target */ #define IP_VS_SVC_F_MATCH 0x0400 /* snat match */ diff --git a/include/ipvs/service.h b/include/ipvs/service.h index a643bb45c..f3c6e3c45 100644 --- a/include/ipvs/service.h +++ b/include/ipvs/service.h @@ -37,6 +37,7 @@ #define DP_VS_SVC_F_PERSISTENT IP_VS_SVC_F_PERSISTENT #define DP_VS_SVC_F_HASHED IP_VS_SVC_F_HASHED #define DP_VS_SVC_F_ONEPACKET IP_VS_SVC_F_ONEPACKET +#define DP_VS_SVC_F_EXPIRE_QUIESCENT IP_VS_SVC_F_EXPIRE_QUIESCENT #define DP_VS_SVC_F_SCHED1 IP_VS_SVC_F_SCHED1 #define DP_VS_SVC_F_SCHED2 IP_VS_SVC_F_SCHED2 #define DP_VS_SVC_F_SCHED3 IP_VS_SVC_F_SCHED3 diff --git a/src/ipvs/ip_vs_core.c b/src/ipvs/ip_vs_core.c index fbc53efa8..2e7851c40 100644 --- a/src/ipvs/ip_vs_core.c +++ b/src/ipvs/ip_vs_core.c @@ -86,7 +86,8 @@ static struct dp_vs_conn *dp_vs_sched_persist(struct dp_vs_service *svc, assert(svc && iph && mbuf); conn_flags = (is_synproxy_on ? DPVS_CONN_F_SYNPROXY : 0); - conn_flags |= (svc->flags & DPVS_CONN_F_EXPIRE_QUIESCENT); + if (svc->flags | DP_VS_SVC_F_EXPIRE_QUIESCENT) + conn_flags |= DPVS_CONN_F_EXPIRE_QUIESCENT; if (svc->af == AF_INET6) { /* FIXME: Is OK to use svc->netmask as IPv6 prefix length ? */ @@ -345,7 +346,8 @@ struct dp_vs_conn *dp_vs_schedule(struct dp_vs_service *svc, flags |= DPVS_CONN_F_SYNPROXY; if (svc->flags & DP_VS_SVC_F_ONEPACKET && iph->proto == IPPROTO_UDP) flags |= DPVS_CONN_F_ONE_PACKET; - flags |= (svc->flags & DPVS_CONN_F_EXPIRE_QUIESCENT); + if (svc->flags & DP_VS_SVC_F_EXPIRE_QUIESCENT) + flags |= DPVS_CONN_F_EXPIRE_QUIESCENT; conn = dp_vs_conn_new(mbuf, iph, ¶m, dest, flags); if (!conn) diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index f08a90c2b..3d4e5be67 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -913,9 +913,9 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, set_option(options, OPT_SYNPROXY); if(!memcmp(optarg , "enable" , strlen("enable"))) { - ce->dpvs_svc.flags = ce->dpvs_svc.flags | IP_VS_CONN_F_SYNPROXY; + ce->dpvs_svc.flags = ce->dpvs_svc.flags | IP_VS_SVC_F_SYNPROXY; } else if(!memcmp(optarg , "disable" , strlen("disable"))) { - ce->dpvs_svc.flags = ce->dpvs_svc.flags & (~IP_VS_CONN_F_SYNPROXY); + ce->dpvs_svc.flags = ce->dpvs_svc.flags & (~IP_VS_SVC_F_SYNPROXY); } else fail(2 , "synproxy switch must be enable or disable\n"); @@ -951,7 +951,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, case TAG_CONN_EXPIRE_QUIESCENT: { set_option(options, OPT_EXPIRE_QUIESCENT_CONN); - ce->dpvs_svc.flags = ce->dpvs_svc.flags | IP_VS_CONN_F_EXPIRE_QUIESCENT; + ce->dpvs_svc.flags = ce->dpvs_svc.flags | IP_VS_SVC_F_EXPIRE_QUIESCENT; break; } case TAG_DEST_CHECK: @@ -2139,11 +2139,11 @@ print_service_entry(dpvs_service_compat_t *se, unsigned int format) } if (se->flags & IP_VS_SVC_F_ONEPACKET) printf(" ops"); - if (se->flags & IP_VS_CONN_F_SYNPROXY) + if (se->flags & IP_VS_SVC_F_SYNPROXY) printf(" synproxy"); if (se->conn_timeout != 0) printf(" conn-timeout %u", se->conn_timeout); - if (se->flags & IP_VS_CONN_F_EXPIRE_QUIESCENT) + if (se->flags & IP_VS_SVC_F_EXPIRE_QUIESCENT) printf(" expire-quiescent"); if (se->check_conf.enabled) { printf(" dest-check"); diff --git a/tools/keepalived/keepalived/check/ipvswrapper.c b/tools/keepalived/keepalived/check/ipvswrapper.c index ce9b5f97b..284e01a21 100755 --- a/tools/keepalived/keepalived/check/ipvswrapper.c +++ b/tools/keepalived/keepalived/check/ipvswrapper.c @@ -787,11 +787,11 @@ static void ipvs_set_srule(int cmd, dpvs_service_compat_t *srule, virtual_server } if (vs->syn_proxy) { - srule->flags |= IP_VS_CONN_F_SYNPROXY; + srule->flags |= IP_VS_SVC_F_SYNPROXY; } if (vs->expire_quiescent_conn) { - srule->flags |= IP_VS_CONN_F_EXPIRE_QUIESCENT; + srule->flags |= IP_VS_SVC_F_EXPIRE_QUIESCENT; } if (!strcmp(vs->sched, "conhash")) { diff --git a/tools/keepalived/keepalived/check/libipvs.c b/tools/keepalived/keepalived/check/libipvs.c index 700400c29..4067a4d98 100644 --- a/tools/keepalived/keepalived/check/libipvs.c +++ b/tools/keepalived/keepalived/check/libipvs.c @@ -138,18 +138,18 @@ int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int opti } if (options & OPT_SYNPROXY) { - if(svc->flags & IP_VS_CONN_F_SYNPROXY) { - entry.flags |= IP_VS_CONN_F_SYNPROXY; + if(svc->flags & IP_VS_SVC_F_SYNPROXY) { + entry.flags |= IP_VS_SVC_F_SYNPROXY; } else { - entry.flags &= ~IP_VS_CONN_F_SYNPROXY; + entry.flags &= ~IP_VS_SVC_F_SYNPROXY; } } if (options & OPT_EXPIRE_QUIESCENT_CONN) { - if (svc->flags & IP_VS_CONN_F_EXPIRE_QUIESCENT) { - entry.flags |= IP_VS_CONN_F_EXPIRE_QUIESCENT; + if (svc->flags & IP_VS_SVC_F_EXPIRE_QUIESCENT) { + entry.flags |= IP_VS_SVC_F_EXPIRE_QUIESCENT; } else { - entry.flags &= ~IP_VS_CONN_F_EXPIRE_QUIESCENT; + entry.flags &= ~IP_VS_SVC_F_EXPIRE_QUIESCENT; } } From e2429166667c7dfb49b3397aa5dcfbc7b30a91fb Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 19 May 2023 18:13:38 +0800 Subject: [PATCH 032/105] ipvs: fix the chaos of dest flag, flags and fwdmode Signed-off-by: ywc689 --- include/conf/dest.h | 11 ++++++----- include/ipvs/dest.h | 2 +- include/ipvs/service.h | 1 + src/ipvs/ip_vs_dest.c | 13 ++++++++++--- src/ipvs/ip_vs_service.c | 3 ++- src/ipvs/ip_vs_synproxy.c | 2 +- tools/ipvsadm/ipvsadm.c | 14 ++++++++++++-- tools/keepalived/keepalived/check/ipvswrapper.c | 1 + 8 files changed, 34 insertions(+), 13 deletions(-) diff --git a/include/conf/dest.h b/include/conf/dest.h index 29a678c5a..ba0cf56a1 100644 --- a/include/conf/dest.h +++ b/include/conf/dest.h @@ -46,19 +46,20 @@ typedef struct dp_vs_dest_compat { int af; uint16_t port; uint16_t proto; - uint32_t weight; /* destination weight */ + uint32_t weight; /* destination weight */ union inet_addr addr; - unsigned conn_flags; /* connection flags */ + uint16_t conn_flags; /* flags passed on to connections */ + uint16_t flags; /* dest flags */ enum dpvs_fwd_mode fwdmode; /* real server options */ /* thresholds for active connections */ - uint32_t max_conn; /* upper threshold */ - uint32_t min_conn; /* lower threshold */ + uint32_t max_conn; /* upper threshold */ + uint32_t min_conn; /* lower threshold */ - uint32_t actconns; /* active connections */ + uint32_t actconns; /* active connections */ uint32_t inactconns; /* inactive connections */ uint32_t persistconns; /* persistent connections */ diff --git a/include/ipvs/dest.h b/include/ipvs/dest.h index b28e5ed34..9d77a1168 100644 --- a/include/ipvs/dest.h +++ b/include/ipvs/dest.h @@ -51,7 +51,7 @@ struct dp_vs_dest { union inet_addr addr; /* IP address of the server */ uint16_t port; /* port number of the server */ - volatile unsigned flags; /* dest status flags */ + volatile uint16_t flags; /* dest status flags */ rte_atomic16_t conn_flags; /* flags to copy to conn */ rte_atomic16_t weight; /* server weight */ diff --git a/include/ipvs/service.h b/include/ipvs/service.h index f3c6e3c45..8ef66b902 100644 --- a/include/ipvs/service.h +++ b/include/ipvs/service.h @@ -37,6 +37,7 @@ #define DP_VS_SVC_F_PERSISTENT IP_VS_SVC_F_PERSISTENT #define DP_VS_SVC_F_HASHED IP_VS_SVC_F_HASHED #define DP_VS_SVC_F_ONEPACKET IP_VS_SVC_F_ONEPACKET +#define DP_VS_SVC_F_SYNPROXY IP_VS_SVC_F_SYNPROXY #define DP_VS_SVC_F_EXPIRE_QUIESCENT IP_VS_SVC_F_EXPIRE_QUIESCENT #define DP_VS_SVC_F_SCHED1 IP_VS_SVC_F_SCHED1 #define DP_VS_SVC_F_SCHED2 IP_VS_SVC_F_SCHED2 diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 86b8e3ecb..166f33dbb 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -75,6 +75,7 @@ static void __dp_vs_dest_update(struct dp_vs_service *svc, rte_atomic16_set(&dest->weight, udest->weight); conn_flags = udest->conn_flags | DPVS_CONN_F_INACTIVE; + dest->fwdmode = udest->fwdmode; rte_atomic16_set(&dest->conn_flags, conn_flags); dp_vs_dest_set_avail(dest); @@ -322,7 +323,9 @@ int dp_vs_dest_get_entries(const struct dp_vs_service *svc, entry.af = dest->af; entry.addr = dest->addr; entry.port = dest->port; - entry.conn_flags = dest->fwdmode; + entry.fwdmode = dest->fwdmode; + entry.flags = dest->flags; + entry.conn_flags = rte_atomic16_read(&dest->conn_flags); entry.weight = rte_atomic16_read(&dest->weight); entry.max_conn = dest->max_conn; entry.min_conn = dest->min_conn; @@ -664,7 +667,9 @@ static int dp_vs_dest_get_details(const struct dp_vs_service *svc, detail->af = dest->af; detail->addr = dest->addr; detail->port = dest->port; - detail->conn_flags = dest->fwdmode; + detail->fwdmode = dest->fwdmode; + detail->flags = dest->flags; + detail->conn_flags = rte_atomic16_read(&dest->conn_flags); detail->weight = rte_atomic16_read(&dest->weight); detail->max_conn = dest->max_conn; detail->min_conn = dest->min_conn; @@ -821,7 +826,9 @@ static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void ** outdest->af = dest->af; outdest->addr = dest->addr; outdest->port = dest->port; - outdest->conn_flags = dest->fwdmode; + outdest->fwdmode = dest->fwdmode; + outdest->flags = dest->flags; + outdest->conn_flags = rte_atomic16_read(&dest->conn_flags); outdest->max_conn = dest->max_conn; outdest->min_conn = dest->min_conn; outdest->weight = rte_atomic16_read(&dest->weight); diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index f30d59f4f..a98656e76 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -806,8 +806,9 @@ void dp_vs_copy_udest_compat(struct dp_vs_dest_conf *udest, udest->af = udest_compat->af; udest->addr = udest_compat->addr; udest->port = udest_compat->port; - udest->fwdmode = udest_compat->conn_flags;//make sure fwdmode and conn_flags are the same + udest->fwdmode = udest_compat->fwdmode; udest->conn_flags = udest_compat->conn_flags; + udest->flags = udest_compat->flags; udest->weight = udest_compat->weight; udest->max_conn = udest_compat->max_conn; udest->min_conn = udest_compat->min_conn; diff --git a/src/ipvs/ip_vs_synproxy.c b/src/ipvs/ip_vs_synproxy.c index 339aaca2d..fefb2d41a 100644 --- a/src/ipvs/ip_vs_synproxy.c +++ b/src/ipvs/ip_vs_synproxy.c @@ -695,7 +695,7 @@ int dp_vs_synproxy_syn_rcv(int af, struct rte_mbuf *mbuf, if (th->syn && !th->ack && !th->rst && !th->fin && (svc = dp_vs_service_lookup(af, iph->proto, &iph->daddr, th->dest, 0, NULL, NULL, NULL, rte_lcore_id())) && - (svc->flags & DPVS_CONN_F_SYNPROXY)) { + (svc->flags & DP_VS_SVC_F_SYNPROXY)) { /* if service's weight is zero (non-active realserver), * do noting and drop the packet */ if (svc->weight == 0) { diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index 3d4e5be67..9ffd3f3e6 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -744,26 +744,31 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, case 'i': set_option(options, OPT_FORWARD); ce->dpvs_dest.conn_flags = IP_VS_CONN_F_TUNNEL; + ce->dpvs_dest.fwdmode = IP_VS_CONN_F_TUNNEL; ce->dpvs_svc.flags = IP_VS_CONN_F_TUNNEL; break; case 'g': set_option(options, OPT_FORWARD); ce->dpvs_dest.conn_flags = IP_VS_CONN_F_DROUTE; + ce->dpvs_dest.fwdmode = IP_VS_CONN_F_DROUTE; ce->dpvs_svc.flags = IP_VS_CONN_F_DROUTE; break; case 'b': set_option(options, OPT_FORWARD); ce->dpvs_dest.conn_flags = IP_VS_CONN_F_FULLNAT; + ce->dpvs_dest.fwdmode = IP_VS_CONN_F_FULLNAT; ce->dpvs_svc.flags = IP_VS_CONN_F_FULLNAT; break; case 'J': set_option(options, OPT_FORWARD); ce->dpvs_dest.conn_flags = IP_VS_CONN_F_SNAT; + ce->dpvs_dest.fwdmode = IP_VS_CONN_F_SNAT; ce->dpvs_svc.flags = IP_VS_CONN_F_SNAT; break; case 'm': set_option(options, OPT_FORWARD); ce->dpvs_dest.conn_flags = IP_VS_CONN_F_MASQ; + ce->dpvs_dest.fwdmode = IP_VS_CONN_F_MASQ; ce->dpvs_svc.flags = IP_VS_CONN_F_MASQ; break; case 'w': @@ -1040,6 +1045,7 @@ static int process_options(int argc, char **argv, int reading_stdin) ce.dpvs_dest.weight = 1; /* Set direct routing as default forwarding method */ ce.dpvs_dest.conn_flags = IP_VS_CONN_F_DROUTE; + ce.dpvs_dest.fwdmode = IP_VS_CONN_F_DROUTE; /* Set the default persistent granularity to /32 mask */ ce.dpvs_svc.netmask = ((u_int32_t) 0xffffffff); /* Set the default cpu be master */ @@ -1080,8 +1086,8 @@ static int process_options(int argc, char **argv, int reading_stdin) * Don't worry about this if fwmark is used. */ if (!ce.dpvs_svc.fwmark && - (ce.dpvs_dest.conn_flags == IP_VS_CONN_F_TUNNEL - || ce.dpvs_dest.conn_flags == IP_VS_CONN_F_DROUTE)) + (ce.dpvs_dest.fwdmode == IP_VS_CONN_F_TUNNEL + || ce.dpvs_dest.fwdmode == IP_VS_CONN_F_DROUTE)) ce.dpvs_dest.port = ce.dpvs_svc.port; } @@ -1885,6 +1891,10 @@ static inline char *fwd_switch(unsigned flags) case IP_VS_CONN_F_LOCALNODE: case IP_VS_CONN_F_DROUTE: swt = "-g"; break; + case IP_VS_CONN_F_FULLNAT: + swt = "-b"; break; + case IP_VS_CONN_F_SNAT: + swt = "-J"; break; } return swt; } diff --git a/tools/keepalived/keepalived/check/ipvswrapper.c b/tools/keepalived/keepalived/check/ipvswrapper.c index 284e01a21..a41df0103 100755 --- a/tools/keepalived/keepalived/check/ipvswrapper.c +++ b/tools/keepalived/keepalived/check/ipvswrapper.c @@ -832,6 +832,7 @@ ipvs_set_drule(int cmd, dpvs_dest_compat_t *drule, real_server_t * rs) drule->port = inet_sockaddrport(&rs->addr); drule->conn_flags = rs->forwarding_method; + drule->fwdmode = rs->forwarding_method; drule->weight = rs->weight; drule->max_conn = rs->u_threshold; drule->min_conn = rs->l_threshold; From 3a3a1202591af4455fbe0a10c0ef743f2a208b2f Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 23 May 2023 15:04:42 +0800 Subject: [PATCH 033/105] ipvs: support external dest-check configs Signed-off-by: ywc689 --- doc/dest-check.md | 53 +++++++++++++++++++++++++++++++++-- include/conf/service.h | 25 ++++++++++++++++- src/ipvs/ip_vs_dest.c | 8 +++--- tools/ipvsadm/ipvsadm.c | 61 ++++++++++++++++++++++++++++------------- 4 files changed, 121 insertions(+), 26 deletions(-) diff --git a/doc/dest-check.md b/doc/dest-check.md index e637f70dc..966b1a4f1 100644 --- a/doc/dest-check.md +++ b/doc/dest-check.md @@ -80,7 +80,7 @@ The test service uses the default dest-check configs, i.e., no down retry, 1 up IP Virtual Server version 1.9.3 (size=0) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn -TCP 192.168.88.1:80 wlc dest-check +TCP 192.168.88.1:80 wlc dest-check internal:default -> 192.168.88.30:80 FullNat 1 0 0 -> 192.168.88.68:80 FullNat 1 0 0 ``` @@ -169,7 +169,7 @@ Now we change the dest-check configs to be 3 down_retry in 3s down delay, 3 up_c IP Virtual Server version 1.9.3 (size=0) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn -TCP 192.168.88.1:80 wlc dest-check 3,3,3s,60-3600s +TCP 192.168.88.1:80 wlc dest-check internal:3,3,3s,60-3600s -> 192.168.88.30:80 FullNat 1 0 9 -> 192.168.88.68:80 FullNat 1 0 5 ``` @@ -202,3 +202,52 @@ Apr 20 20:44:20 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88 Apr 20 20:44:21 dpvs-devel-28 dpvs[54778]: SERVICE: [cid 00, tcp, svc 192.168.88.1:80, rs 192.168.88.30:80, weight 1, inhibited yes, down_notice_recvd 3, inhibit_duration 480s, origin_weight 0] notify slaves DOWN ``` It shows that at least 3 failure are detected before inhibiting the failed backend, and the inhibition duration starts from 60s. + +# External Backend Health Check + +DPVS supports external backend health check with an auxiliary program called `healthcheck`. Three checker methods are available up to now. + +* TCP Checker +* UDP Checker +* Ping Checker + +They shall work independently or together with Passive Health Check. Notes that external checkers rely on dpvs-agent to interact with DPVS. + +* Enable external TCP Checker. + +``` +# ipvsadm -Et 192.168.88.1:80 --dest-check tcp +# ipvsadm -ln +IP Virtual Server version 1.9.4 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.88.1:80 wlc dest-check external:tcp + -> 192.168.88.30:80 FullNat 1 0 8 + -> 192.168.88.68:80 FullNat 1 0 7 +``` + +* Enable external UDP Checker and Ping Checker. + +``` +# ipvsadm -Et 192.168.88.1:80 --dest-check udp --dest-check ping +# ipvsadm -ln +IP Virtual Server version 1.9.4 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.88.1:80 wlc dest-check external:udp,ping + -> 192.168.88.30:80 FullNat 1 0 9 + -> 192.168.88.68:80 FullNat 1 0 7 +``` + +* Enable Passive Checker and TCP Checker. + +``` +# ipvsadm -Et 192.168.88.1:80 --dest-check 3,5s --dest-check tcp +# ipvsadm -ln +IP Virtual Server version 1.9.4 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.88.1:80 wlc dest-check internal:3,5s external:tcp + -> 192.168.88.30:80 FullNat 1 0 8 + -> 192.168.88.68:80 FullNat 1 0 8 +``` diff --git a/include/conf/service.h b/include/conf/service.h index e55868c14..d408b9d50 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -47,6 +47,14 @@ #define MAX_ARG_LEN (sizeof(dpvs_service_compat_t) + sizeof(dpvs_dest_compat_t)) +/* dest health check types */ +#define DEST_HC_NONE 0x00 +#define DEST_HC_PASSIVE 0x01 +#define DEST_HC_TCP 0x02 +#define DEST_HC_UDP 0x04 +#define DEST_HC_PING 0x08 +#define DEST_HC_MASK_EXTERNAL 0x0e + /* defaults for dest passive health check */ #define DEST_DOWN_NOTICE_DEFAULT 1 #define DEST_UP_NOTICE_DEFAULT 1 @@ -55,7 +63,9 @@ #define DEST_INHIBIT_DURATION_MAX 3600 // 1h struct dest_check_configs { - uint8_t enabled; + uint8_t types; // DEST_HC_* + + /* params for passive dest check */ uint8_t dest_down_notice_num; // how many DOWNs detected in `dest_down_wait` before inhibiting the dest uint8_t dest_up_notice_num; // how many notifications sent when UPs detected after inhibitation uint8_t dest_down_wait; @@ -108,6 +118,16 @@ struct dp_vs_getinfo { unsigned int num_lcores; }; +static inline bool +dest_check_passive(const struct dest_check_configs *conf) { + return conf->types & DEST_HC_PASSIVE; +} + +static inline bool +dest_check_external(const struct dest_check_configs *conf) { + return conf->types & DEST_HC_MASK_EXTERNAL; +} + static inline bool dest_check_down_only(const struct dest_check_configs *conf) { return !(conf->dest_inhibit_min @@ -117,6 +137,9 @@ dest_check_down_only(const struct dest_check_configs *conf) { static inline bool dest_check_configs_sanity(struct dest_check_configs *conf) { bool res = true; + if (!(dest_check_passive(conf))) { + return true; + } if (conf->dest_down_notice_num < 1) { conf->dest_down_notice_num = DEST_DOWN_NOTICE_DEFAULT; res = false; diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 166f33dbb..5d0722106 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -545,7 +545,7 @@ static int msg_cb_notify_master(struct dpvs_msg *msg) dest->dfc.master.origin_weight = rte_atomic16_read(&dest->weight); rte_atomic16_clear(&dest->weight); } else { // dest_notification_up - assert(!dest_check_down_only(configs)); + //assert(!dest_check_down_only(configs)); dest->dfc.master.inhibit_duration >>= 1; if (dest->dfc.master.inhibit_duration < configs->dest_inhibit_min) dest->dfc.master.inhibit_duration = configs->dest_inhibit_min; @@ -575,7 +575,7 @@ static int msg_cb_notify_slaves(struct dpvs_msg *msg) rte_atomic16_clear(&dest->weight); dp_vs_dest_set_inhibited(dest); } else { // dest_notification_open - assert(!dest_check_down_only(configs)); + //assert(!dest_check_down_only(configs)); rte_atomic16_set(&dest->weight, dest->dfc.slave.origin_weight); dp_vs_dest_clear_inhibited(dest); dest->dfc.slave.warm_up_count = configs->dest_up_notice_num; @@ -590,7 +590,7 @@ int dp_vs_dest_detected_alive(struct dp_vs_dest *dest) struct dpvs_msg *msg; struct dest_notification *notice; - if (!dest->svc->check_conf.enabled) + if (!dest_check_passive(&dest->svc->check_conf)) return EDPVS_DISABLED; if (likely(dest->dfc.slave.warm_up_count == 0)) @@ -622,7 +622,7 @@ int dp_vs_dest_detected_dead(struct dp_vs_dest *dest) struct dpvs_msg *msg; struct dest_notification *notice; - if (!dest->svc->check_conf.enabled) + if (!dest_check_passive(&dest->svc->check_conf)) return EDPVS_DISABLED; if (dp_vs_dest_is_inhibited(dest) || rte_atomic16_read(&dest->weight) == 0) diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index 9ffd3f3e6..ebf967e91 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -425,11 +425,16 @@ static bool is_dest_check_conf_default(const struct dest_check_configs *conf) static int parse_dest_check(const char *optarg, struct dest_check_configs *conf) { - memset(conf, 0, sizeof(*conf)); if (!strcmp(optarg, "disable")) { - conf->enabled = 0; + conf->types = DEST_HC_NONE; + } else if (!strcmp(optarg, "tcp")) { + conf->types |= DEST_HC_TCP; + } else if (!strcmp(optarg, "udp")) { + conf->types |= DEST_HC_UDP; + } else if (!strcmp(optarg, "ping")) { + conf->types |= DEST_HC_PING; } else if (!strcmp(optarg, "default")) { - conf->enabled = 1; + conf->types |= DEST_HC_PASSIVE; conf->dest_down_notice_num = DEST_DOWN_NOTICE_DEFAULT; conf->dest_up_notice_num = DEST_UP_NOTICE_DEFAULT; conf->dest_down_wait = DEST_DOWN_WAIT_DURATION; @@ -442,7 +447,8 @@ static int parse_dest_check(const char *optarg, struct dest_check_configs *conf) &conf->dest_down_wait, &conf->dest_inhibit_min, &conf->dest_inhibit_max) != 5) { - memset(conf, 0, sizeof(*conf)); + conf->dest_up_notice_num = 0; + conf->dest_inhibit_min = conf->dest_inhibit_max = 0; if (sscanf(optarg, "%hhu,%hhus", &conf->dest_down_notice_num, &conf->dest_down_wait) != 2) { @@ -451,7 +457,7 @@ static int parse_dest_check(const char *optarg, struct dest_check_configs *conf) } if (!dest_check_configs_sanity(conf)) return -1; - conf->enabled = 1; + conf->types |= DEST_HC_PASSIVE; } return 0; } @@ -1712,8 +1718,8 @@ static void usage_exit(const char *program, const int exit_status) " --hash-target hashtag choose target for conhash (support sip or qid for quic)\n" " --cpu cpu_index specifi cpu (lcore) index to show, 0 for master worker\n" " --expire-quiescent expire the quiescent connections timely whose realserver went down\n" - " --dest-check CHECK_CONF config passive health check, inhibit scheduling to failed backends\n" - " CHECK_CONF:=disable|default|DETAIL, DETAIL:=UPDOWN|DOWNONLY\n" + " --dest-check CHECK_CONF config health check, inhibit scheduling to failed backends\n" + " CHECK_CONF:=disable|default(passive)|DETAIL(passive)|tcp|udp|ping, DETAIL:=UPDOWN|DOWNONLY\n" " UPDOWN:=down_retry,up_confirm,down_wait,inhibit_min-inhibit_max, for example, the default is 1,1,3s,5-3600s\n" " DOWNONLY:=down_retry,down_wait, for example, --dest-check=1,3s\n", DEF_SCHED); @@ -2155,22 +2161,39 @@ print_service_entry(dpvs_service_compat_t *se, unsigned int format) printf(" conn-timeout %u", se->conn_timeout); if (se->flags & IP_VS_SVC_F_EXPIRE_QUIESCENT) printf(" expire-quiescent"); - if (se->check_conf.enabled) { + if (se->check_conf.types) { printf(" dest-check"); - if (!is_dest_check_conf_default(&se->check_conf)) { - if (dest_check_down_only(&se->check_conf)) { - printf(" %d,%ds", - se->check_conf.dest_down_notice_num, - se->check_conf.dest_down_wait); + if (dest_check_passive(&se->check_conf)) { + printf(" internal:"); + if (!is_dest_check_conf_default(&se->check_conf)) { + if (dest_check_down_only(&se->check_conf)) { + printf("%d,%ds", + se->check_conf.dest_down_notice_num, + se->check_conf.dest_down_wait); + } else { + printf( "%d,%d,%ds,%d-%ds", + se->check_conf.dest_down_notice_num, + se->check_conf.dest_up_notice_num, + se->check_conf.dest_down_wait, + se->check_conf.dest_inhibit_min, + se->check_conf.dest_inhibit_max); + } } else { - printf( " %d,%d,%ds,%d-%ds", - se->check_conf.dest_down_notice_num, - se->check_conf.dest_up_notice_num, - se->check_conf.dest_down_wait, - se->check_conf.dest_inhibit_min, - se->check_conf.dest_inhibit_max); + printf("default"); } } + if (dest_check_external(&se->check_conf)){ + char buf[16] = {0}; + printf(" external:"); + if (se->check_conf.types & DEST_HC_TCP) + strcat(buf, "tcp,"); + if (se->check_conf.types & DEST_HC_UDP) + strcat(buf, "udp,"); + if (se->check_conf.types & DEST_HC_PING) + strcat(buf, "ping,"); + *strrchr(buf, ',') = '\0'; + printf(buf); + } } } printf("\n"); From 851d71c8e070ec9ae7b5c1323ec3f880e2180caf Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 24 May 2023 17:58:01 +0800 Subject: [PATCH 034/105] ipvs: allow dpvs-agent to edit dest's weight and inhibited flag only Signed-off-by: ywc689 --- include/ipvs/dest.h | 2 ++ src/ipvs/ip_vs_dest.c | 47 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/include/ipvs/dest.h b/include/ipvs/dest.h index 9d77a1168..1e1c70c5b 100644 --- a/include/ipvs/dest.h +++ b/include/ipvs/dest.h @@ -146,6 +146,8 @@ int dp_vs_dest_add(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest); int dp_vs_dest_edit(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest); +int dp_vs_dest_edit_health(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest); + void dp_vs_dest_unlink(struct dp_vs_service *svc, struct dp_vs_dest *dest, int svcupd); diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 5d0722106..9d0c93198 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -186,14 +186,9 @@ dp_vs_dest_edit(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest) { struct dp_vs_dest *dest; union inet_addr daddr; - uint16_t dport = udest->port; + uint16_t dport; uint32_t old_weight; - if (udest->weight < 0) { - RTE_LOG(DEBUG, SERVICE, "%s(): server weight less than zero\n", __func__); - return EDPVS_INVAL; - } - if (udest->min_conn > udest->max_conn) { RTE_LOG(DEBUG, SERVICE, "%s(): lower threshold is higher than upper threshold\n", __func__); @@ -201,6 +196,7 @@ dp_vs_dest_edit(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest) } daddr = udest->addr; + dport = udest->port; /* * Lookup the destination list @@ -235,6 +231,43 @@ dp_vs_dest_edit(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest) return EDPVS_OK; } +/* dp_vs_dest_edit_health only changes dest's weight and DPVS_DEST_F_INHIBITED flag */ +int dp_vs_dest_edit_health(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest) +{ + struct dp_vs_dest *dest; + union inet_addr daddr; + uint16_t dport; + uint32_t old_weight; + + daddr = udest->addr; + dport = udest->port; + + dest = dp_vs_dest_lookup(udest->af, svc, &daddr, dport); + if (dest == NULL) + return EDPVS_NOTEXIST; + old_weight = rte_atomic16_read(&dest->weight); + + rte_atomic16_set(&dest->weight, udest->weight); + if (udest->flags & DPVS_DEST_F_INHIBITED) + dp_vs_dest_set_inhibited(dest); + else + dp_vs_dest_clear_inhibited(dest); + + svc->weight = svc->weight - old_weight + udest->weight; + if (svc->weight < 0) { + struct dp_vs_dest *tdest; + svc->weight = 0; + list_for_each_entry(tdest, &svc->dests, n_list) + svc->weight += rte_atomic16_read(&tdest->weight); + RTE_LOG(ERR, SERVICE, "%s(): vs weight < 0\n", __func__); + } + + if (svc->scheduler->update_service) + svc->scheduler->update_service(svc, dest, DPVS_SO_SET_EDITDEST); + + return EDPVS_OK; +} + void dp_vs_dest_put(struct dp_vs_dest *dest) { if (!dest) @@ -748,7 +781,7 @@ static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len) ret = dp_vs_dest_edit(getsvc, &udest); break; case DPVSAGENT_VS_EDIT_DESTS: - ret = dp_vs_dest_edit(getsvc, &udest); + ret = dp_vs_dest_edit_health(getsvc, &udest); break; case DPVSAGENT_VS_DEL_DESTS: ret = dp_vs_dest_del(getsvc, &udest); From b7477b73ce29afe538b4a032468fe8f6b5caccc9 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 25 May 2023 17:55:24 +0800 Subject: [PATCH 035/105] ip_vs_wlc: fix scheduling to inhibited dest problem Signed-off-by: ywc689 --- src/ipvs/ip_vs_wlc.c | 2 +- tools/ipvsadm/ipvsadm.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ipvs/ip_vs_wlc.c b/src/ipvs/ip_vs_wlc.c index 1d695fbb0..aff8fc26a 100644 --- a/src/ipvs/ip_vs_wlc.c +++ b/src/ipvs/ip_vs_wlc.c @@ -63,7 +63,7 @@ static struct dp_vs_dest *dp_vs_wlc_schedule(struct dp_vs_service *svc, if (unlikely(cur == &svc->dests)) continue; dest = list_entry(cur, struct dp_vs_dest, n_list); - if (dest->flags & DPVS_DEST_F_OVERLOAD) + if (!dp_vs_dest_is_valid(dest)) continue; doh = dp_vs_wlc_dest_overhead(dest); if (loh * rte_atomic16_read(&dest->weight) > diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index ebf967e91..0c29b36b4 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -2241,10 +2241,19 @@ print_service_entry(dpvs_service_compat_t *se, unsigned int format) printf(" -> %-28s %-9u %-11u %-10u %-10u\n", dname, e->weight, e->persistconns, e->actconns, e->inactconns); - } else - printf(" -> %-28s %-7s %-6d %-10u %-10u\n", + } else { + char sep = ' '; + printf(" -> %-28s %-7s %-6d %-10u %-10u", dname, fwd_name(e->conn_flags), e->weight, e->actconns, e->inactconns); + if (e->flags & DPVS_DEST_F_INHIBITED) { + printf("%c%s", sep, "inhibited"); + sep = ','; + } + if (e->flags & DPVS_DEST_F_OVERLOAD) + printf("%c%s",sep, "overload"); + printf("\n"); + } free(dname); } From 4ac9809f7816a16cb86eeb0363e5626145690361 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 1 Jun 2023 18:18:01 +0800 Subject: [PATCH 036/105] ipvs: fix service flush problem Signed-off-by: ywc689 --- src/ipvs/ip_vs_service.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index a98656e76..039c3738c 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -831,6 +831,8 @@ static inline int set_opt_so2msg(sockoptid_t opt) { // return opt - SOCKOPT_SVC_BASE + MSG_TYPE_SVC_SET_BASE; switch (opt) { + case DPVS_SO_SET_FLUSH: + return MSG_TYPE_SVC_SET_FLUSH; case DPVS_SO_SET_ZERO: return MSG_TYPE_SVC_SET_ZERO; case DPVS_SO_SET_ADD: From a60dd1353e859d018917d6dd0a499b5baa97de47 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 7 Jun 2023 15:22:47 +0800 Subject: [PATCH 037/105] uoa: add ipv6 enable macro for uoa example server Signed-off-by: ywc689 --- kmod/uoa/example/Makefile | 2 ++ kmod/uoa/example/udp_serv.c | 23 ++++++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/kmod/uoa/example/Makefile b/kmod/uoa/example/Makefile index 997f67a38..dae636b41 100644 --- a/kmod/uoa/example/Makefile +++ b/kmod/uoa/example/Makefile @@ -24,6 +24,8 @@ all: udp_serv uperf opp CFLAGS = -g -O0 CFLAGS += -I ../../../include/ -I ../../../include/conf -I ../ +CFLAGS += -D WITH_IPV6_ENABLE + udp_serv: udp_serv.c gcc $(CFLAGS) -o udp_serv udp_serv.c diff --git a/kmod/uoa/example/udp_serv.c b/kmod/uoa/example/udp_serv.c index 5149d0b61..32a77c71e 100644 --- a/kmod/uoa/example/udp_serv.c +++ b/kmod/uoa/example/udp_serv.c @@ -48,7 +48,9 @@ void handle_reply(int efd, int fd) { struct sockaddr_storage peer; struct sockaddr_in *sin = NULL; +#ifdef WITH_IPV6_ENABLE struct sockaddr_in6 *sin6 = NULL; +#endif char buff[4096], from[64]; struct uoa_param_map map; socklen_t len, mlen; @@ -89,7 +91,9 @@ void handle_reply(int efd, int fd) len = sizeof(peer); sendto(fd, buff, n, 0, (SA *)&peer, len); - } else { /* AF_INET6 */ + } +#ifdef WITH_IPV6_ENABLE + else { /* AF_INET6 */ sin6 = (struct sockaddr_in6 *)&peer; inet_ntop(AF_INET6, &sin6->sin6_addr, from, sizeof(from)); printf("Receive %d bytes from %s:%d -- %s\n", @@ -110,17 +114,20 @@ void handle_reply(int efd, int fd) len = sizeof(peer); sendto(fd, buff, n, 0, (SA *)&peer, len); } +#endif fflush(stdout); } int main(int argc, char *argv[]) { - int i, sockfd[MAX_SUPP_AF]; + int i, sockfd[MAX_SUPP_AF], nsock = 0; int epfd, nfds; int enable = 1; struct epoll_event events[MAX_EPOLL_EVENTS]; struct sockaddr_in local; +#ifdef WITH_IPV6_ENABLE struct sockaddr_in6 local6; +#endif if (argc > 1) SERV_PORT = atoi(argv[1]); @@ -130,18 +137,22 @@ int main(int argc, char *argv[]) perror("Fail to create INET socket!\n"); exit(1); } + nsock++; +#ifdef WITH_IPV6_ENABLE if ((sockfd[1] = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { perror("Fail to create INET6 socket!"); exit(1); } + nsock++; +#endif if ((epfd = epoll_create1(0)) < 0) { perror("Fail to create epoll fd!\n"); exit(1); } - for (i = 0; i < MAX_SUPP_AF; i++) { + for (i = 0; i < nsock; i++) { setsockopt(sockfd[i], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); setsockopt(sockfd[i], SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); } @@ -156,6 +167,7 @@ int main(int argc, char *argv[]) exit(1); } +#ifdef WITH_IPV6_ENABLE memset(&local6, 0, sizeof(struct sockaddr_in6)); local6.sin6_family = AF_INET6; local6.sin6_port = htons(SERV_PORT); @@ -165,8 +177,9 @@ int main(int argc, char *argv[]) perror("Fail to bind INET6 socket!\n"); exit(1); } +#endif - for (i = 0; i < MAX_SUPP_AF; i++) { + for (i = 0; i < nsock; i++) { struct epoll_event ev; memset(&ev, 0, sizeof(ev)); ev.events = EPOLLIN | EPOLLERR; @@ -189,7 +202,7 @@ int main(int argc, char *argv[]) } } - for (i = 0; i < MAX_SUPP_AF; i++) + for (i = 0; i < nsock; i++) close(sockfd[i]); exit(0); From 850ba85568e55e544aeb07b25f48908cbf6fdb07 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 27 Jun 2023 16:30:42 +0800 Subject: [PATCH 038/105] doc: update dest-check doc Signed-off-by: ywc689 --- doc/dest-check.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/dest-check.md b/doc/dest-check.md index 966b1a4f1..1e80acf5d 100644 --- a/doc/dest-check.md +++ b/doc/dest-check.md @@ -3,14 +3,14 @@ Backends Failure Detection and Inhibition # Concepts -DPVS implements a simple backend failure detection and inhibition mechanism by examining the packet flow it forwards. We call it Passive Health Check because it doesn't send any probe data to the backends. It works for TCP by checking if SYN/ACK packet is replied from the backend, and if not, inhibit scheduling of the backend for a period. The inhibiting period is gained or lost exponentially depending on subsequent checking is failure or success. As for UDP, it works only when the UDP flow is bidirectional, that is, the UDP connections that forwarding inbound or outbound only are always detcted as dead. Thus "dest-check" should be never configured for the UDP services with monodirectional flow. In summury, DPVS Passive Health Check can be used in the following scenarios: +DPVS implements a simple backend failure detection and inhibition mechanism by examining the packet flow it forwards. We call it Passive Health Check because it doesn't send any probe request to the backends. It works for TCP by checking if SYN/ACK packet is replied from the backend, and if not, inhibit scheduling the backend for a period. The inhibiting period is gained or lost exponentially depending on subsequent checking is failure or success. As for UDP, it works only when the UDP flow is bidirectional, that is, the UDP backends with connections that forwarding inbound only or outbound only are always detcted to be failure. Thus "dest-check" should be never configured on the UDP services with monodirectional flow. In summury, DPVS Passive Health Check is applicable to the following scenarios: * TCP FullNat/Nat64/DR/Tunnel/Nat fowarding mode. * UDP FullNat/Nat64/Nat forwarding mode with bidirectional data flow. -It's noted that DPVS Passive Health Check has no way to discover the backend failure unless packet drop has already acctually occurred. A smaller session timeout may be preferred for TCP SYN_SENT/SYN_RECV and UDP ONEWAY states to detect backend fault and remove it from available backend list quickly. +It's noted that DPVS Passive Health Check has no way to detect the backend failure unless packet drop has already acctually occurred. A smaller session timeout may be preferred for TCP SYN_SENT/SYN_RECV and UDP ONEWAY states to accelerate backend fault discovery and remove it from available backend list quickly. -The state transition diagrams below show the interactions of DPVS master and slave lcores for Passive Health Check. +The state transition diagrams below explain the workflow in DPVS master and slave lcores for Passive Health Check. ![master lcore](./pics/health_check-master-lcore.drawio.png) @@ -31,14 +31,14 @@ The backends are detected as UP in the following cases: * TCP synproxy step 3 received SYN/ACK from backend * UDP session state tranfers from ONEWAY to NORMAL -Backend inhibition is performed by setting the inhibition flag into the backend server and changing its weight to zero so that new sessions would not be scheduled it. +Backend inhibition is performed by setting the inhibition flag into the backend server and changing its weight to zero so that new sessions would not be scheduled to it. Four types of lcore msg notice are used: * **Down Notice**: unicast msg, from slave to master, notify master a backend DOWN event is detected * **Up Notice**: unicast msg, from slave to master, notify master a backend UP event is detected * **Close Notice**: multicast msg, from master to all slaves, inhibit scheduling a failed backend -* **Open Notice**: multicast msg, from master to all slaves, restore scheduling a inhibited backend +* **Open Notice**: multicast msg, from master to all slaves, restore scheduling an inhibited backend DPVS allows to specify a per-service Passive Health Check configuration, each configuration including the 5 parameters below: @@ -174,7 +174,7 @@ TCP 192.168.88.1:80 wlc dest-check internal:3,3,3s,60-3600s -> 192.168.88.68:80 FullNat 1 0 5 ``` -Run the above script and we get the outputs below. +Run the script above and we get the outputs below. ``` # while true; do curl -g -s -m 1 192.168.88.1:80 -o /dev/null; [ $? -eq 0 ] && printf . || printf x; sleep 0.5; done @@ -211,7 +211,7 @@ DPVS supports external backend health check with an auxiliary program called `he * UDP Checker * Ping Checker -They shall work independently or together with Passive Health Check. Notes that external checkers rely on dpvs-agent to interact with DPVS. +They shall work independently or together with Passive Health Check. Notes that external checkers rely on dpvs-agent to communicate with DPVS. * Enable external TCP Checker. From 4a4b5799534896046b8aa18e369c37852d4a94eb Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 27 Jun 2023 18:51:56 +0800 Subject: [PATCH 039/105] tools: add healthcheck tool and config.mk Signed-off-by: ywc689 --- .github/workflows/build.yaml | 4 +- Makefile | 6 + config.mk | 33 +++ doc/Worker-Performance-Tuning.md | 2 +- doc/tutorial.md | 2 +- scripts/dpvs_log_rotate.sh | 138 ++++++++++ src/Makefile | 4 +- src/config.mk | 128 ++++++--- tools/Makefile | 7 + tools/healthcheck/.gitignore | 3 + tools/healthcheck/Makefile | 22 ++ tools/healthcheck/go.mod | 10 + tools/healthcheck/go.sum | 6 + tools/healthcheck/license.txt | 13 + tools/healthcheck/main.go | 103 +++++++ tools/healthcheck/pkg/helthcheck/checker.go | 252 ++++++++++++++++++ tools/healthcheck/pkg/helthcheck/configs.go | 94 +++++++ .../pkg/helthcheck/ping_checker.go | 203 ++++++++++++++ .../pkg/helthcheck/ping_checker_test.go | 45 ++++ tools/healthcheck/pkg/helthcheck/server.go | 248 +++++++++++++++++ .../healthcheck/pkg/helthcheck/tcp_checker.go | 122 +++++++++ .../pkg/helthcheck/test/tcp_checker.go | 130 +++++++++ .../pkg/helthcheck/test/udp_checker.go | 119 +++++++++ tools/healthcheck/pkg/helthcheck/types.go | 225 ++++++++++++++++ .../healthcheck/pkg/helthcheck/udp_checker.go | 108 ++++++++ tools/healthcheck/pkg/lb/dpvs_agent.go | 228 ++++++++++++++++ tools/healthcheck/pkg/lb/dpvs_agent_test.go | 49 ++++ tools/healthcheck/pkg/lb/types.go | 65 +++++ tools/healthcheck/pkg/server/server.go | 72 +++++ tools/healthcheck/pkg/utils/net.go | 124 +++++++++ tools/healthcheck/test/README.md | 238 +++++++++++++++++ tools/healthcheck/test/dpvs-agent-api.sh | 31 +++ tools/healthcheck/test/stress-test.sh | 67 +++++ 33 files changed, 2859 insertions(+), 42 deletions(-) create mode 100644 config.mk create mode 100755 scripts/dpvs_log_rotate.sh create mode 100644 tools/healthcheck/.gitignore create mode 100644 tools/healthcheck/Makefile create mode 100644 tools/healthcheck/go.mod create mode 100644 tools/healthcheck/go.sum create mode 100644 tools/healthcheck/license.txt create mode 100644 tools/healthcheck/main.go create mode 100644 tools/healthcheck/pkg/helthcheck/checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/configs.go create mode 100644 tools/healthcheck/pkg/helthcheck/ping_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/ping_checker_test.go create mode 100644 tools/healthcheck/pkg/helthcheck/server.go create mode 100644 tools/healthcheck/pkg/helthcheck/tcp_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/test/tcp_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/test/udp_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/types.go create mode 100644 tools/healthcheck/pkg/helthcheck/udp_checker.go create mode 100644 tools/healthcheck/pkg/lb/dpvs_agent.go create mode 100644 tools/healthcheck/pkg/lb/dpvs_agent_test.go create mode 100644 tools/healthcheck/pkg/lb/types.go create mode 100644 tools/healthcheck/pkg/server/server.go create mode 100644 tools/healthcheck/pkg/utils/net.go create mode 100644 tools/healthcheck/test/README.md create mode 100755 tools/healthcheck/test/dpvs-agent-api.sh create mode 100755 tools/healthcheck/test/stress-test.sh diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1ac36e39f..360635bb4 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -22,13 +22,13 @@ jobs: - name: make run: make -j - build-debug: + build-all: runs-on: self-hosted env: PKG_CONFIG_PATH: /data/dpdk/dpdklib/lib64/pkgconfig steps: - uses: actions/checkout@v2 - name: config - run: sed -i 's/#CFLAGS +=/CFLAGS +=/' src/config.mk && sed -i 's/^#DEBUG := 1/DEBUG := 1/' src/Makefile + run: sed -i 's/=n$/=y/' config.mk - name: make run: make -j diff --git a/Makefile b/Makefile index 3172b2981..44f214765 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ MAKE = make CC = gcc LD = ld +RM = rm SUBDIRS = src tools @@ -29,6 +30,8 @@ export INSDIR export KERNEL = $(shell /bin/uname -r) +include $(CURDIR)/config.mk + all: for i in $(SUBDIRS); do $(MAKE) -C $$i || exit 1; done @@ -43,3 +46,6 @@ distclean: install:all -mkdir -p $(INSDIR) for i in $(SUBDIRS); do $(MAKE) -C $$i install || exit 1; done + +uninstall: + -$(RM) -f $(TARGET) $(INSDIR)/* diff --git a/config.mk b/config.mk new file mode 100644 index 000000000..5d8648f12 --- /dev/null +++ b/config.mk @@ -0,0 +1,33 @@ +# configs +export CONFIG_DPVS_MAX_SOCKET=2 +export CONFIG_DPVS_MAX_LCORE=64 + +## modules +export CONFIG_DPVS_AGENT=n +export CONFIG_IXGEB_PMD=y +export CONFIG_DPVS_LOG=y +export CONFIG_PDUMP=y +export CONFIG_ICMP_REDIRECT_CORE=n + +# debugging and logging +export CONFIG_DEBUG=n +export CONFIG_DPVS_NEIGH_DEBUG=n +export CONFIG_RECORD_BIG_LOOP=n +export CONFIG_DPVS_SAPOOL_DEBUG=n +export CONFIG_DPVS_IPVS_DEBUG=n +export CONFIG_DPVS_SERVICE_DEBUG=n +export CONFIG_SYNPROXY_DEBUG=n +export CONFIG_TIMER_MEASURE=n +export CONFIG_TIMER_DEBUG=n +export DPVS_CFG_PARSER_DEBUG=n +export NETIF_BONDING_DEBUG=n +export CONFIG_TC_DEBUG=n +export CONFIG_DPVS_IPVS_STATS_DEBUG=n +export CONFIG_DPVS_IP_HEADER_DEBUG=n +export CONFIG_DPVS_MBUF_DEBUG=n +export CONFIG_DPVS_IPSET_DEBUG=n +export CONFIG_NDISC_DEBUG=n +export CONFIG_MSG_DEBUG=n +export CONFIG_DPVS_MP_DEBUG=n +export CONFIG_DPVS_NETIF_DEBUG=n +export CONFIG_DPVS_ICMP_DEBUG=n diff --git a/doc/Worker-Performance-Tuning.md b/doc/Worker-Performance-Tuning.md index 8616e2bf8..acbf892d6 100644 --- a/doc/Worker-Performance-Tuning.md +++ b/doc/Worker-Performance-Tuning.md @@ -30,7 +30,7 @@ In case of the following situations, you should consider this performance tuning * There exists big worker loops. - > To observe worker loop time, you should uncomment the macro "CONFIG_RECORD_BIG_LOOP" in src/config.mk,recompile DPVS program and run it. + > To observe worker loop time, you should set "CONFIG_RECORD_BIG_LOOP=y" in `config.mk`,recompile DPVS program and run it. > > Besides, macros "BIG_LOOP_THRESH_SLAVE" and "BIG_LOOP_THRESH_MASTER" define the threshold time of worker loop. Modify them if needed. diff --git a/doc/tutorial.md b/doc/tutorial.md index 9d5e89323..8ea24dea3 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1326,7 +1326,7 @@ Firstly, DPVS runs with `WARNING` log level by default. You can change it in `/e Use low level log such as "INFO" or "DEBUG" may help find more clues to your problem. -Secondly, some modules support more detailed debug log only if you enable it when compile DPVS. The supported flags are defined but commented in [src/config.mk](../src/config.mk), some of which are listed below. Uncomment it and recompile DPVS if you need to debug the corresponding module. +Secondly, some modules support more detailed debug log only if you enable it when compile DPVS. The modular debug options are available in [config.mk](../config.mk), some of which are listed below. Change the value to "y" and recompile DPVS if you want to debug a module. ``` - CONFIG_DPVS_IPVS_DEBUG # for ipvs forwarding debug diff --git a/scripts/dpvs_log_rotate.sh b/scripts/dpvs_log_rotate.sh new file mode 100755 index 000000000..6bb38a84e --- /dev/null +++ b/scripts/dpvs_log_rotate.sh @@ -0,0 +1,138 @@ +#!/bin/env bash + +# Set target directory for cleaning +TARGET_DIR="/var/log/healthcheck" + +# Set log file name pattern +LOG_FILENAME_PATTERN="*\.log\.*" + +# Set the maximum usage percentage and the target usage percentage +MAX_USAGE=80 +TARGET_USAGE=40 + +# Set the minimum number of log files to keep +MIN_FILES=12 + +# Set the maximum number of files to delete in one run +MAX_DELETE=10000 + +OPTS=`getopt -o d:p:u:l:K:D:h --long \ +log-directory:,filename-pattern:,disk-usage-high:,\ +disk-usage-low:,min-files-kept:,max-deletions:,help,\ + -n "$0" -- "$@"` +eval set -- "$OPTS" +while true +do + case "$1" in + -d|--log-directory) + TARGET_DIR="$2" + shift 2 + ;; + -p|--filename-pattern) + LOG_FILENAME_PATTERN="$2" + shift 2 + ;; + -u|--disk-usage-high) + MAX_USAGE="$2" + shift 2 + ;; + -l|--disk-usage-low) + TARGET_USAGE="$2" + shift 2 + ;; + -K|--min-files-kept) + MIN_FILES="$2" + shift 2 + ;; + -D|--max-deletions) + MAX_DELETE="$2" + shift 2 + ;; + -h|--help) + echo "[usage] $0 [ OPTS ]" + echo "OPTS:" + echo " -d|--log-directory DIRECTORY" + echo " -p|--filename-pattern REGEXPR" + echo " -u|--disk-usage-high 0-100" + echo " -l|--disk-usage-low 0-100" + echo " -K|--min-files-kept NUM" + echo " -D|--max-deletions NUM" + echo " -h|--help" + exit 0 + ;; + --) + shift + break + ;; + *) + echo "Param Error!" + exit 1 + ;; + esac +done + +NotRecognized=$(for arg do printf "$arg " ; done) +[ ! -z "$NotRecognized" ] && echo "Unrecognized Opts: ${NotRecognized}" && exit 1 + +echo "CONFIGS:" +echo " log-directory: ${TARGET_DIR}" +echo " filename-pattern: ${LOG_FILENAME_PATTERN}" +echo " disk-usage-high: ${MAX_USAGE}" +echo " disk-usage-low: ${TARGET_USAGE}" +echo " min-files-kept: ${MIN_FILES}" +echo " max-deletions: ${MAX_DELETE}" + +[ ! -d ${TARGET_DIR} ] && echo "invalid --log-directory \"${TARGET_DIR}\", not found!" && exit 1 +echo ${MAX_USAGE} | egrep ^[0-9]+$ >/dev/null; [ $? -ne 0 ] && echo "invalid --disk-usage-high" && exit 1 +echo ${TARGET_USAGE} | egrep ^[0-9]+$ >/dev/null; [ $? -ne 0 ] && echo "invalid --disk-usage-low" && exit 1 +echo ${MIN_FILES} | egrep ^[0-9]+$ >/dev/null; [ $? -ne 0 ] && echo "invalid --min-files-kept" && exit 1 +echo ${MAX_DELETE} | egrep ^[0-9]+$ >/dev/null; [ $? -ne 0 ] && echo "invalid --max-deletions" && exit 1 +res=$(echo "${MAX_USAGE} < 100" | bc); [ "$res" -ne 1 ] && echo "--disk-usage-high must less than 100" && exit 1 +res=$(echo "${MAX_USAGE} > ${TARGET_USAGE}" | bc); [ "$res" -ne 1 ] && echo "--disk-usage-high must greater than --disk-usage-low" && exit 1 + +# Get the current disk usage +CURRENT_USAGE=$(df -P ${TARGET_DIR} | awk 'NR==2 {printf "%d", $5}') + +# Initialize a counter for deleted files +DELETED_FILES=0 + +# Start the cleaning process if the disk usage is higher than the defined MAX_USAGE +if [ "${CURRENT_USAGE}" -gt "${MAX_USAGE}" ]; then + echo "Disk usage is ${CURRENT_USAGE}%, starting cleaning process." + + # Find and delete logs until disk usage reaches TARGET_USAGE or MAX_DELETE files are deleted + while [ "${CURRENT_USAGE}" -gt "${TARGET_USAGE}" ] && [ "${DELETED_FILES}" -lt "${MAX_DELETE}" ]; do + # Check the number of log files + NUM_FILES=$(find ${TARGET_DIR} -type f -name ${LOG_FILENAME_PATTERN} | wc -l) + + # Ensure that at least MIN_FILES log files remain + if [ "${NUM_FILES}" -le "${MIN_FILES}" ]; then + echo "Reached minimum number of log files (${MIN_FILES}), aborting." + exit 1 + fi + + # Find the oldest log file + OLDEST_LOG=$(find ${TARGET_DIR} -type f -name ${LOG_FILENAME_PATTERN} -printf '%T+ %p\n' | sort | head -n1 | cut -d' ' -f2) + + echo "Deleting ${OLDEST_LOG}..." + rm -f "${OLDEST_LOG}" + DELETED_FILES=$((DELETED_FILES+1)) + + # Update current disk usage + CURRENT_USAGE=$(df -P ${TARGET_DIR} | awk 'NR==2 {printf "%d", $5}') + done + + if [ "${DELETED_FILES}" -eq "${MAX_DELETE}" ]; then + echo "Reached the maximum number of deletions (${MAX_DELETE}), aborting." + else + echo "Cleaning process completed. Disk usage is now ${CURRENT_USAGE}%." + fi + +else + echo "Disk usage is ${CURRENT_USAGE}%, no cleaning needed." +fi + +echo "Remaining Files in ${TARGET_DIR} (only show 30 entries):" +ls -lh ${TARGET_DIR} | head -n 30 + +exit 0 diff --git a/src/Makefile b/src/Makefile index b546a0d67..82e75030d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,8 +19,6 @@ # Makefile for dpvs (DPVS main program). # -#DEBUG := 1 # enable for debug - TARGET := dpvs ifneq ("$(wildcard VERSION)","") @@ -59,7 +57,7 @@ ifeq ($(shell test $(GCC_VERSION) -ge 70 && echo 1), 1) CFLAGS += -Wstringop-overflow=0 endif -ifeq ($(DEBUG),) +ifneq ($(CONFIG_DEBUG), y) CFLAGS += -O3 else CFLAGS += -g -O0 -D DEBUG diff --git a/src/config.mk b/src/config.mk index 78fb68ba4..2a1ef13dc 100644 --- a/src/config.mk +++ b/src/config.mk @@ -15,52 +15,110 @@ # GNU General Public License for more details. # -# -# enable as needed. -# -# TODO: use standard way to define compile flags. -# - -CONFIG_IXGEB_PMD=y -CONFIG_PDUMP=y +CFLAGS += -D DPVS_MAX_SOCKET=$(CONFIG_DPVS_MAX_SOCKET) +CFLAGS += -D DPVS_MAX_LCORE=$(CONFIG_DPVS_MAX_LCORE) -CFLAGS += -D DPVS_MAX_SOCKET=2 -CFLAGS += -D DPVS_MAX_LCORE=64 - -CFLAGS += -D CONFIG_DPVS_LOG -#CFLAGS += -D CONFIG_ICMP_REDIRECT_CORE -#CFLAGS += -D CONFIG_DPVS_AGENT - -#CFLAGS += -D CONFIG_DPVS_NEIGH_DEBUG -#CFLAGS += -D CONFIG_RECORD_BIG_LOOP -#CFLAGS += -D CONFIG_DPVS_SAPOOL_DEBUG -#CFLAGS += -D CONFIG_DPVS_IPVS_DEBUG -#CFLAGS += -D CONFIG_DPVS_SERVICE_DEBUG -#CFLAGS += -D CONFIG_SYNPROXY_DEBUG -#CFLAGS += -D CONFIG_TIMER_MEASURE -#CFLAGS += -D CONFIG_TIMER_DEBUG -#CFLAGS += -D DPVS_CFG_PARSER_DEBUG -#CFLAGS += -D NETIF_BONDING_DEBUG -#CFLAGS += -D CONFIG_TC_DEBUG -#CFLAGS += -D CONFIG_DPVS_IPVS_STATS_DEBUG -#CFLAGS += -D CONFIG_DPVS_IP_HEADER_DEBUG -#CFLAGS += -D CONFIG_DPVS_MBUF_DEBUG -#CFLAGS += -D CONFIG_DPVS_IPSET_DEBUG -#CFLAGS += -D CONFIG_NDISC_DEBUG -#CFLAGS += -D CONFIG_MSG_DEBUG -#CFLAGS += -D CONFIG_DPVS_MP_DEBUG -#CFLAGS += -D CONFIG_DPVS_NETIF_DEBUG -#CFLAGS += -D CONFIG_DPVS_ICMP_DEBUG +ifeq ($(CONFIG_DPVS_AGENT), y) +CFLAGS += -D CONFIG_DPVS_AGENT +endif # for ixgbe nic ifeq ($(CONFIG_IXGEB_PMD), y) CFLAGS += -D CONFIG_DPVS_FDIR endif +ifeq ($(CONFIG_DPVS_LOG), y) +CFLAGS += -D CONFIG_DPVS_LOG +endif + ifeq ($(CONFIG_PDUMP), y) CFLAGS += -D CONFIG_DPVS_PDUMP endif +ifeq ($(CONFIG_ICMP_REDIRECT_CORE), y) +CFLAGS += -D CONFIG_ICMP_REDIRECT_CORE +endif + +ifeq ($(CONFIG_DPVS_NEIGH_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_NEIGH_DEBUG +endif + +ifeq ($(CONFIG_RECORD_BIG_LOOP), y) +CFLAGS += -D CONFIG_RECORD_BIG_LOOP +endif + +ifeq ($(CONFIG_DPVS_SAPOOL_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_SAPOOL_DEBUG +endif + +ifeq ($(CONFIG_DPVS_IPVS_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_IPVS_DEBUG +endif + +ifeq ($(CONFIG_DPVS_SERVICE_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_SERVICE_DEBUG +endif + +ifeq ($(CONFIG_SYNPROXY_DEBUG), y) +CFLAGS += -D CONFIG_SYNPROXY_DEBUG +endif + +ifeq ($(CONFIG_TIMER_MEASURE), y) +CFLAGS += -D CONFIG_TIMER_MEASURE +endif + +ifeq ($(CONFIG_TIMER_DEBUG), y) +CFLAGS += -D CONFIG_TIMER_DEBUG +endif + +ifeq ($(DPVS_CFG_PARSER_DEBUG), y) +CFLAGS += -D DPVS_CFG_PARSER_DEBUG +endif + +ifeq ($(NETIF_BONDING_DEBUG), y) +CFLAGS += -D NETIF_BONDING_DEBUG +endif + +ifeq ($(CONFIG_TC_DEBUG), y) +CFLAGS += -D CONFIG_TC_DEBUG +endif + +ifeq ($(CONFIG_DPVS_IPVS_STATS_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_IPVS_STATS_DEBUG +endif + +ifeq ($(CONFIG_DPVS_IP_HEADER_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_IP_HEADER_DEBUG +endif + +ifeq ($(CONFIG_DPVS_MBUF_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_MBUF_DEBUG +endif + +ifeq ($(CONFIG_DPVS_IPSET_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_IPSET_DEBUG +endif + +ifeq ($(CONFIG_NDISC_DEBUG), y) +CFLAGS += -D CONFIG_NDISC_DEBUG +endif + +ifeq ($(CONFIG_MSG_DEBUG), y) +CFLAGS += -D CONFIG_MSG_DEBUG +endif + +ifeq ($(CONFIG_DPVS_MP_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_MP_DEBUG +endif + +ifeq ($(CONFIG_DPVS_NETIF_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_NETIF_DEBUG +endif + +ifeq ($(CONFIG_DPVS_ICMP_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_ICMP_DEBUG +endif + GCC_MAJOR = $(shell echo __GNUC__ | $(CC) -E -x c - | tail -n 1) GCC_MINOR = $(shell echo __GNUC_MINOR__ | $(CC) -E -x c - | tail -n 1) GCC_VERSION = $(GCC_MAJOR)$(GCC_MINOR) diff --git a/tools/Makefile b/tools/Makefile index 064670c31..832a568d1 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -20,6 +20,10 @@ # SUBDIRS = keepalived ipvsadm dpip +ifeq ($(CONFIG_DPVS_AGENT), y) +SUBDIRS += healthcheck +endif + all: config for i in $(SUBDIRS); do $(MAKE) -C $$i || exit 1; done @@ -42,3 +46,6 @@ install: install -m 744 keepalived/bin/keepalived $(INSDIR)/keepalived install -m 744 ipvsadm/ipvsadm $(INSDIR)/ipvsadm install -m 744 dpip/build/dpip $(INSDIR)/dpip +ifeq ($(CONFIG_DPVS_AGENT), y) + install -m 744 healthcheck/healthcheck $(INSDIR)/healthcheck +endif diff --git a/tools/healthcheck/.gitignore b/tools/healthcheck/.gitignore new file mode 100644 index 000000000..a8763e2d1 --- /dev/null +++ b/tools/healthcheck/.gitignore @@ -0,0 +1,3 @@ +healthcheck +*.log +log/* diff --git a/tools/healthcheck/Makefile b/tools/healthcheck/Makefile new file mode 100644 index 000000000..27e506bba --- /dev/null +++ b/tools/healthcheck/Makefile @@ -0,0 +1,22 @@ +TARGET := healthcheck + +GO ?= go +GO_BUILD = CGO_ENABLED=0 $(GO) build +GO_CLEAN = $(GO) clean + +.PHONY: all $(TARGET) clean + +all: $(TARGET) + +$(TARGET): + -$(GO) mod tidy + $(GO_BUILD) -o $@ + +clean: + $(GO_CLEAN) + +license: license.txt +ifeq ($(shell addlicense 2>&1|grep Usage),) + $(error "`addlicense` command not found. You can install it with `go install github.com/google/addlicense`") +endif + -addlicense -f license.txt -v . diff --git a/tools/healthcheck/go.mod b/tools/healthcheck/go.mod new file mode 100644 index 000000000..7c97f9d58 --- /dev/null +++ b/tools/healthcheck/go.mod @@ -0,0 +1,10 @@ +module github.com/iqiyi/dpvs/tools/healthcheck + +go 1.20 + +require ( + github.com/golang/glog v1.1.1 + github.com/google/gops v0.3.27 +) + +require golang.org/x/sys v0.8.0 // indirect diff --git a/tools/healthcheck/go.sum b/tools/healthcheck/go.sum new file mode 100644 index 000000000..dc5c3cfbf --- /dev/null +++ b/tools/healthcheck/go.sum @@ -0,0 +1,6 @@ +github.com/golang/glog v1.1.1 h1:jxpi2eWoU84wbX9iIEyAeeoac3FLuifZpY9tcNUD9kw= +github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/google/gops v0.3.27 h1:BDdWfedShsBbeatZ820oA4DbVOC8yJ4NI8xAlDFWfgI= +github.com/google/gops v0.3.27/go.mod h1:lYqabmfnq4Q6UumWNx96Hjup5BDAVc8zmfIy0SkNCSk= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/tools/healthcheck/license.txt b/tools/healthcheck/license.txt new file mode 100644 index 000000000..d61a47c47 --- /dev/null +++ b/tools/healthcheck/license.txt @@ -0,0 +1,13 @@ +Copyright 2023 IQiYi Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/tools/healthcheck/main.go b/tools/healthcheck/main.go new file mode 100644 index 000000000..064cdabf2 --- /dev/null +++ b/tools/healthcheck/main.go @@ -0,0 +1,103 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "time" + + "github.com/golang/glog" + gops "github.com/google/gops/agent" + + hc "github.com/iqiyi/dpvs/tools/healthcheck/pkg/helthcheck" + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/server" +) + +var ( + notifyChannelSize = flag.Uint("channel_size", + hc.DefaultServerConfig().NotifyChannelSize, + "The size of the notification channel") + + notifyInterval = flag.Duration("notify_interval", + hc.DefaultServerConfig().NotifyInterval, + "The time between notifications") + + fetchInterval = flag.Duration("fetch_interval", + hc.DefaultServerConfig().FetchInterval, + "The time between healthcheck config fetches from DPVS") + + checkInterval = flag.Duration("check_interval", + 3*time.Second, + "The default time interval to run a check") + + checkTimeout = flag.Duration("check_timeout", + 1*time.Second, + "The default timeout before a check fails") + + checkRetry = flag.Uint("check_retry", + 1, + "The default retry count when a check fails") + + dryRun = flag.Bool("dry_run", + hc.DefaultServerConfig().DryRun, + "Skips actual check and always return healthy as result") + + debug = flag.Bool("debug", + hc.DefaultServerConfig().Debug, + "Enable gops for debug") + + lbIfaceType = flag.String("lb_iface_type", + hc.DefaultServerConfig().LbIfaceType, + "Type of load-balancer interface via which to get check objects and update results") + + lbIfaceAddr = flag.String("lb_iface_addr", + hc.DefaultServerConfig().LbIfaceAddr, + "Address of load-balancer interface via which to get check objects and update results") + + lbAutoMethod = flag.Bool("lb_auto_method", + hc.DefaultServerConfig().LbAutoMethod, + "Use default check method for the backends if not specified") +) + +func main() { + flag.Parse() + defer glog.Flush() + + cfg := hc.DefaultServerConfig() + cfg.NotifyChannelSize = *notifyChannelSize + cfg.NotifyInterval = *notifyInterval + cfg.FetchInterval = *fetchInterval + cfg.LbIfaceType = *lbIfaceType + cfg.LbIfaceAddr = *lbIfaceAddr + cfg.LbAutoMethod = *lbAutoMethod + cfg.DryRun = *dryRun + cfg.Debug = *debug + + hc.DefaultCheckConfig.Interval = *checkInterval + hc.DefaultCheckConfig.Timeout = *checkTimeout + hc.DefaultCheckConfig.Retry = *checkRetry + + if cfg.Debug { + if err := gops.Listen(gops.Options{}); err != nil { + glog.Warningf("Unable to start gops: %v", err) + } else { + defer gops.Close() + } + } + + hcs := hc.NewServer(&cfg) + server.ShutdownHandler(hcs) + hcs.Run() +} diff --git a/tools/healthcheck/pkg/helthcheck/checker.go b/tools/healthcheck/pkg/helthcheck/checker.go new file mode 100644 index 000000000..52b2357a4 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/checker.go @@ -0,0 +1,252 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "sync" + "time" + + log "github.com/golang/glog" +) + +const uweightDefault uint16 = 1 + +// Checks provides a map of healthcheck configurations. +type Checkers struct { + Configs map[Id]*CheckerConfig +} + +// Checker represents a healthcheck instance. +type Checker struct { + CheckerConfig + + lock sync.RWMutex + dryrun bool + uweight uint16 + start time.Time + successes uint64 + failures uint64 + failed uint64 + state State + result *Result + + update chan CheckerConfig + notify chan<- *Notification + quit chan bool +} + +// NewCheck returns an initialised Checker. +func NewChecker(notify chan<- *Notification, state State, weight uint16) *Checker { + // FIXME: how to obtain the original weight if the checker's + // initial state is unhealthy? + if state == StateUnhealthy && weight == 0 { + weight = uweightDefault + } + return &Checker{ + state: state, + uweight: weight, + notify: notify, + update: make(chan CheckerConfig, 1), + quit: make(chan bool, 1), + } +} + +// Status returns the current status for this healthcheck instance. +func (hc *Checker) Status() Status { + hc.lock.RLock() + defer hc.lock.RUnlock() + status := Status{ + LastCheck: hc.start, + Failures: hc.failures, + Successes: hc.successes, + State: hc.state, + } + if hc.state == StateHealthy { + status.Weight = hc.uweight + } + if hc.result != nil { + status.Duration = hc.result.Duration + status.Message = hc.result.String() + } + return status +} + +func (hc *Checker) updateConfig(conf *CheckerConfig) { + hc.CheckerConfig = *conf + if conf.State != StateUnhealthy { + hc.lock.Lock() + weight := hc.uweight + hc.uweight = conf.Weight + hc.lock.Unlock() + if weight != conf.Weight { + log.Infof("%v: user weight changed %d -> %d", hc.Id, weight, conf.Weight) + } + } +} + +// execute invokes the given healthcheck checker with the configured timeout. +func (hc *Checker) execute() *Result { + ch := make(chan *Result, 1) + checker := hc.CheckMethod + timeout := hc.Timeout + target := hc.Target + go func() { + // TODO: Determine a way to ensure that this go routine does not linger. + ch <- checker.Check(target, timeout) + }() + select { + case result := <-ch: + return result + case <-time.After(timeout + time.Second): + return &Result{"Timed out", false, timeout, nil} + } +} + +// Notification generates a healthcheck notification for this checker. +func (hc *Checker) Notification() *Notification { + return &Notification{ + Id: hc.Id, + Target: hc.Target, + Status: hc.Status(), + } +} + +// Notify sends a healthcheck notification for this checker. +func (hc *Checker) Notify() { + hc.notify <- hc.Notification() +} + +// healthcheck executes the given checker. +func (hc *Checker) healthcheck() { + if hc.CheckMethod == nil { + return + } + start := time.Now() + + var result *Result + if hc.dryrun { + result = NewResult(start, "dryrun mode; always succeed", true, nil) + } else { + result = hc.execute() + } + + status := "SUCCESS" + if !result.Success { + status = "FAILURE" + } + log.Infof("%v: %s: %v", hc.Id, status, result) + + hc.lock.Lock() + + hc.start = start + hc.result = result + + var state State + if result.Success { + state = StateHealthy + hc.failed = 0 + hc.successes++ + } else { + hc.failed++ + hc.failures++ + state = StateUnhealthy + } + + if hc.state == StateHealthy && hc.failed > 0 && hc.failed <= uint64(hc.CheckerConfig.Retry) { + log.Infof("%v: Failure %d - retrying...", hc.Id, hc.failed) + state = StateHealthy + } + transition := (hc.state != state) + hc.state = state + + hc.lock.Unlock() + + if transition { + hc.Notify() + } +} + +// Run invokes a healthcheck. It waits for the initial configuration to be +// provided via the configuration channel, after which the configured +// healthchecker is invoked at the given interval. If a new configuration +// is provided the healthchecker is updated and checks are scheduled at the +// new interval. Notifications are generated and sent via the notification +// channel whenever a state transition occurs. Run will terminate once a +// value is received on the quit channel. +func (hc *Checker) Run(start <-chan time.Time) { + // Wait for initial configuration. + select { + case config := <-hc.update: + hc.updateConfig(&config) + case <-hc.quit: + return + } + + // Wait for a tick to avoid a thundering herd at startup and to + // stagger healthchecks that have the same interval. + if start != nil { + <-start + } + log.Infof("Starting healthchecker for %v", hc.Id) + + ticker := time.NewTicker(hc.Interval) + hc.healthcheck() + for { + select { + case <-hc.quit: + ticker.Stop() + log.Infof("Stopping healthchecker for %v", hc.Id) + return + + case config := <-hc.update: + if hc.Interval != config.Interval { + ticker.Stop() + if start != nil { + <-start + } + ticker = time.NewTicker(config.Interval) + } + hc.updateConfig(&config) + + case <-ticker.C: + hc.healthcheck() + } + } +} + +// Stop notifies a running healthcheck that it should quit. +func (hc *Checker) Stop() { + select { + case hc.quit <- true: + default: + } +} + +// SetDryrun enables or disables dryrun mode for a healthcheck. +func (hc *Checker) SetDryrun(dryrun bool) { + hc.dryrun = dryrun +} + +// Update queues a healthcheck configuration update for processing. +func (hc *Checker) Update(config *CheckerConfig) { + select { + case hc.update <- *config: + default: + log.Warningf("Unable to update %v, last update still queued", hc.Id) + } +} diff --git a/tools/healthcheck/pkg/helthcheck/configs.go b/tools/healthcheck/pkg/helthcheck/configs.go new file mode 100644 index 000000000..3d95a6ec1 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/configs.go @@ -0,0 +1,94 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "time" +) + +// ServerConfig specifies the configuration for a healthcheck server. +type ServerConfig struct { + NotifyChannelSize uint + NotifyInterval time.Duration + FetchInterval time.Duration + LbIfaceType string + LbIfaceAddr string + LbAutoMethod bool + DryRun bool + Debug bool +} + +func (cfg *ServerConfig) String() string { + return fmt.Sprintf("notitfy-channel-size: %v, ", cfg.NotifyChannelSize) + + fmt.Sprintf("notify-interval: %v, ", cfg.NotifyInterval) + + fmt.Sprintf("fetch-interval: %v, ", cfg.FetchInterval) + + fmt.Sprintf("lb-auto-method: %v, ", cfg.LbAutoMethod) + + fmt.Sprintf("dryrun: %v, ", cfg.DryRun) + + fmt.Sprintf("debug: %v", cfg.Debug) +} + +var defaultServerConfig = ServerConfig{ + NotifyChannelSize: 1000, + NotifyInterval: 15 * time.Second, + FetchInterval: 15 * time.Second, + LbIfaceType: "dpvs-agent", // only type supported now + LbIfaceAddr: "localhost:6600", + LbAutoMethod: true, + DryRun: false, + Debug: false, +} + +// DefaultServerConfig returns the default server configuration. +func DefaultServerConfig() ServerConfig { + return defaultServerConfig +} + +// CheckerConfig contains the configuration for a healthcheck. +type CheckerConfig struct { + Id + + Target + State + Weight uint16 + CheckMethod + + Interval time.Duration + Timeout time.Duration + Retry uint +} + +var DefaultCheckConfig CheckerConfig + +// NewConfig returns an initialised Config. +func NewCheckerConfig(id *Id, checker CheckMethod, + target *Target, state State, weight uint16, + interval, timeout time.Duration, retry uint) *CheckerConfig { + config := CheckerConfig{ + Id: *id, + Target: *target, + State: state, + Weight: weight, + CheckMethod: checker, + Interval: interval, + Timeout: timeout, + Retry: retry, + } + config.BindConfig(&config) + return &config +} diff --git a/tools/healthcheck/pkg/helthcheck/ping_checker.go b/tools/healthcheck/pkg/helthcheck/ping_checker.go new file mode 100644 index 000000000..dae8eda92 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/ping_checker.go @@ -0,0 +1,203 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +// ICMP ping healthcheck implementation. + +package hc + +import ( + "bytes" + "fmt" + "math/rand" + "net" + "os" + "time" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +var _ CheckMethod = (*PingChecker)(nil) + +var nextPingCheckerID uint16 + +func init() { + s := rand.NewSource(int64(os.Getpid())) + nextPingCheckerID = uint16(s.Int63() & 0xffff) +} + +// PingChecker contains configuration specific to a ping healthcheck. +type PingChecker struct { + Config *CheckerConfig + + ID uint16 + Seqnum uint16 +} + +// NewPingChecker returns an initialised PingChecker. +func NewPingChecker() *PingChecker { + checker := PingChecker{ID: nextPingCheckerID} + nextPingCheckerID++ + return &checker +} + +func (hc *PingChecker) BindConfig(conf *CheckerConfig) { + hc.Config = conf +} + +// String returns the string representation of a Ping healthcheck. +func (hc *PingChecker) String() string { + return fmt.Sprintf("PING checker for %s", hc.Config.Id) +} + +// Check executes a ping healthcheck. +func (hc *PingChecker) Check(target Target, timeout time.Duration) *Result { + msg := fmt.Sprintf("ICMP ping to host %v", target.IP) + if target.IP.To4() != nil { + target.Proto = utils.IPProtoICMP + } else { + target.Proto = utils.IPProtoICMPv6 + } + seq := hc.Seqnum + hc.Seqnum++ + echo := newICMPEchoRequest(target.Proto, hc.ID, seq, 64, []byte("Healthcheck")) + start := time.Now() + if timeout == time.Duration(0) { + timeout = DefaultCheckConfig.Timeout + } + err := exchangeICMPEcho(target.Network(), target.IP, timeout, echo) + success := err == nil + if err != nil { + err = fmt.Errorf("ping target %v, %v", target.IP, err) + } + return NewResult(start, msg, success, err) +} + +// NB: The code below borrows heavily from pkg/net/ipraw_test.go. + +type icmpMsg []byte + +const ( + ICMP4_ECHO_REQUEST = 8 + ICMP4_ECHO_REPLY = 0 + ICMP6_ECHO_REQUEST = 128 + ICMP6_ECHO_REPLY = 129 +) + +func newICMPEchoRequest(proto utils.IPProto, id, seqnum, msglen uint16, filler []byte) icmpMsg { + switch proto { + case utils.IPProtoICMP: + return newICMPv4EchoRequest(id, seqnum, msglen, filler) + case utils.IPProtoICMPv6: + return newICMPv6EchoRequest(id, seqnum, msglen, filler) + } + return nil +} + +func newICMPv4EchoRequest(id, seqnum, msglen uint16, filler []byte) icmpMsg { + msg := newICMPInfoMessage(id, seqnum, msglen, filler) + msg[0] = ICMP4_ECHO_REQUEST + cs := icmpChecksum(msg) + // place checksum back in header; using ^= avoids the assumption that the + // checksum bytes are zero + msg[2] ^= uint8(cs & 0xff) + msg[3] ^= uint8(cs >> 8) + return msg +} + +func icmpChecksum(msg icmpMsg) uint16 { + cklen := len(msg) + s := uint32(0) + for i := 0; i < cklen-1; i += 2 { + s += uint32(msg[i+1])<<8 | uint32(msg[i]) + } + if cklen&1 == 1 { + s += uint32(msg[cklen-1]) + } + s = (s >> 16) + (s & 0xffff) + s = s + (s >> 16) + return uint16(^s) +} + +func newICMPv6EchoRequest(id, seqnum, msglen uint16, filler []byte) icmpMsg { + msg := newICMPInfoMessage(id, seqnum, msglen, filler) + msg[0] = ICMP6_ECHO_REQUEST + // Note: For IPv6, the OS will compute and populate the ICMP checksum bytes. + return msg +} + +func newICMPInfoMessage(id, seqnum, msglen uint16, filler []byte) icmpMsg { + b := make([]byte, msglen) + copy(b[8:], bytes.Repeat(filler, (int(msglen)-8)/(len(filler)+1))) + b[0] = 0 // type + b[1] = 0 // code + b[2] = 0 // checksum + b[3] = 0 // checksum + b[4] = uint8(id >> 8) // identifier + b[5] = uint8(id & 0xff) // identifier + b[6] = uint8(seqnum >> 8) // sequence number + b[7] = uint8(seqnum & 0xff) // sequence number + return b +} + +func parseICMPEchoReply(msg icmpMsg) (id, seqnum, chksum uint16) { + id = uint16(msg[4])<<8 | uint16(msg[5]) + seqnum = uint16(msg[6])<<8 | uint16(msg[7]) + chksum = uint16(msg[2])<<8 | uint16(msg[3]) + return +} + +func exchangeICMPEcho(network string, ip net.IP, timeout time.Duration, echo icmpMsg) error { + c, err := net.ListenPacket(network, "") + if err != nil { + return err + } + defer c.Close() + + _, err = c.WriteTo(echo, &net.IPAddr{IP: ip}) + if err != nil { + return err + } + + c.SetDeadline(time.Now().Add(timeout)) + reply := make([]byte, 256) + for { + _, addr, err := c.ReadFrom(reply) + if err != nil { + return err + } + if !ip.Equal(net.ParseIP(addr.String())) { + continue + } + if reply[0] != ICMP4_ECHO_REPLY && reply[0] != ICMP6_ECHO_REPLY { + continue + } + xid, xseqnum, _ := parseICMPEchoReply(echo) + rid, rseqnum, rchksum := parseICMPEchoReply(reply) + if rid != xid || rseqnum != xseqnum { + continue + } + if reply[0] == ICMP4_ECHO_REPLY { + cs := icmpChecksum(reply) + if cs != 0 { + return fmt.Errorf("Bad ICMP checksum: %x", rchksum) + } + } + // TODO(angusc): Validate checksum for IPv6 + break + } + return nil +} diff --git a/tools/healthcheck/pkg/helthcheck/ping_checker_test.go b/tools/healthcheck/pkg/helthcheck/ping_checker_test.go new file mode 100644 index 000000000..686ff15cf --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/ping_checker_test.go @@ -0,0 +1,45 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "net" + "testing" + "time" +) + +var targets = []Target{ + {net.ParseIP("127.0.0.1"), 0, 0}, + {net.ParseIP("192.168.88.30"), 0, 0}, + {net.ParseIP("11.22.33.44"), 0, 0}, + {net.ParseIP("::1"), 0, 0}, + {net.ParseIP("2001::1"), 0, 0}, + {net.ParseIP("2001::68"), 0, 0}, +} + +func TestPingChecker(t *testing.T) { + for _, target := range targets { + checker := NewPingChecker() + id := Id(target.IP.String()) + config := NewCheckerConfig(&id, checker, + &target, StateUnknown, 0, + 3*time.Second, 1*time.Second, 3) + result := checker.Check(target, config.Timeout) + t.Logf("%v", result) + } +} diff --git a/tools/healthcheck/pkg/helthcheck/server.go b/tools/healthcheck/pkg/helthcheck/server.go new file mode 100644 index 000000000..bd26265cb --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/server.go @@ -0,0 +1,248 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "math/rand" + "time" + + log "github.com/golang/glog" + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/lb" + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +// Server contains the data needed to run a healthcheck server. +type Server struct { + config *ServerConfig + comm lb.Comm + + healthchecks map[Id]*Checker + configs chan map[Id]*CheckerConfig + notify chan *Notification + + quit chan bool +} + +// NewServer returns an initialised healthcheck server. +func NewServer(cfg *ServerConfig) *Server { + rand.Seed(time.Now().UnixNano()) + + if cfg == nil { + defaultCfg := DefaultServerConfig() + cfg = &defaultCfg + } + + var comm lb.Comm + switch cfg.LbIfaceType { + case "dpvs-agent": + comm = lb.NewDpvsAgentComm(cfg.LbIfaceAddr) + default: + panic(fmt.Sprintf("lb_iface_type %q not supported", cfg.LbIfaceType)) + } + + return &Server{ + config: cfg, + comm: comm, + + healthchecks: make(map[Id]*Checker), + notify: make(chan *Notification, cfg.NotifyChannelSize), + configs: make(chan map[Id]*CheckerConfig), + + quit: make(chan bool, 1), + } +} + +func (s *Server) NewChecker(typ lb.Checker, proto utils.IPProto) CheckMethod { + // TODO: support user specified Send/Receive data for TCP/UDP checker + var checker CheckMethod + switch typ { + case lb.CheckerTCP: + checker = NewTCPChecker("", "") + case lb.CheckerUDP: + checker = NewUDPChecker("", "") + case lb.CheckerPING: + checker = NewPingChecker() + case lb.CheckerNone: + if s.config.LbAutoMethod { + switch proto { + case utils.IPProtoTCP: + checker = NewTCPChecker("", "") + case utils.IPProtoUDP: + checker = NewUDPChecker("", "") + } + } + } + return checker +} + +// getHealthchecks attempts to get the current healthcheck configurations from DPVS +func (s *Server) getHealthchecks() (*Checkers, error) { + vss, err := s.comm.ListVirtualServices() + if err != nil { + return nil, err + } + results := &Checkers{Configs: make(map[Id]*CheckerConfig)} + for _, vs := range vss { + for _, rs := range vs.RSs { + target := &Target{rs.IP, rs.Port, vs.Protocol} + id := NewId(vs.Id, target) + checker := s.NewChecker(vs.Checker, vs.Protocol) + if checker == nil { + log.Info("Skip checking vs %v with %v", vs.Id, vs.Checker) + continue + } + weight := rs.Weight + state := StateUnknown + if weight > 0 { + state = StateHealthy + } else if rs.Inhibited { + state = StateUnhealthy + } + // TODO: allow users to specify check interval, timeout and retry + config := NewCheckerConfig(id, checker, + target, state, weight, + DefaultCheckConfig.Interval, + DefaultCheckConfig.Timeout, + DefaultCheckConfig.Retry) + results.Configs[*id] = config + } + } + return results, nil +} + +// updater attempts to fetch healthcheck configurations at regular intervals. +// When configurations are successfully retrieved they are provided to the +// manager via the configs channel. +func (s *Server) updater() { + for { + log.Info("Getting healthchecks from DPVS ...") + checkers, err := s.getHealthchecks() + if err != nil { + log.Errorf("Getting healthchecks failed: %v, retry later", err) + time.Sleep(5 * time.Second) + } else if checkers != nil { + log.Infof("DPVS returned %d healthcheck(s)", len(checkers.Configs)) + s.configs <- checkers.Configs + time.Sleep(s.config.FetchInterval) + } else { // It should not happen. + log.Warning("No healthcheck returned from DPVS") + time.Sleep(s.config.FetchInterval) + } + } +} + +// notifier batches healthcheck notifications and sends them to DPVS. +func (s *Server) notifier() { + // TODO: support more concurrency and rate limit + for { + select { + case notification := <-s.notify: + log.Infof("Sending notification >>> %v", notification) + //fmt.Println("Sending notification >>>", notification) + inhibited := false + if notification.Status.State == StateUnhealthy { + inhibited = true + } + vs := &lb.VirtualService{ + Id: notification.Id.Vs(), + Protocol: notification.Target.Proto, + RSs: []lb.RealServer{{ + IP: notification.Target.IP, + Port: notification.Target.Port, + Weight: notification.Status.Weight, + Inhibited: inhibited, + }}, + } + + if err := s.comm.UpdateByChecker([]lb.VirtualService{*vs}); err != nil { + log.Warningf("Failed to Update %v healthy status to %v(weight: %d): %v", + notification.Id, notification.State, notification.Status.Weight, err) + } + } + } +} + +// manager is responsible for controlling the healthchecks that are currently +// running. When healthcheck configurations become available, the manager will +// stop and remove deleted healthchecks, spawn new healthchecks and provide +// the current configurations to each of the running healthchecks. +func (s *Server) manager() { + notifyTicker := time.NewTicker(s.config.NotifyInterval) + var configs map[Id]*CheckerConfig + for { + select { + case configs = <-s.configs: + + // Remove healthchecks that have been deleted. + for id, hc := range s.healthchecks { + if configs[id] == nil { + hc.Stop() + delete(s.healthchecks, id) + } + } + + // Spawn new healthchecks. + for id, conf := range configs { + if s.healthchecks[id] == nil { + hc := NewChecker(s.notify, conf.State, conf.Weight) + hc.SetDryrun(s.config.DryRun) + s.healthchecks[id] = hc + checkTicker := time.NewTicker(time.Duration((1 + rand.Intn( + int(DefaultCheckConfig.Interval.Milliseconds())))) * time.Millisecond) + go hc.Run(checkTicker.C) + } + } + + // Update configurations. + for id, hc := range s.healthchecks { + hc.Update(configs[id]) + } + + case <-notifyTicker.C: + log.Infof("Total checkers: %d", len(s.healthchecks)) + // Send notifications when status changed. + for id, hc := range s.healthchecks { + notification := hc.Notification() + if configs[id].State != notification.State { + // FIXME: Don't resend the notification after a successful one. + hc.notify <- notification + } + } + } + } +} + +// Run runs a healthcheck server. +func (s *Server) Run() { + log.Infof("Starting healthcheck server (%v) ...", s.config) + go s.updater() + go s.notifier() + go s.manager() + + <-s.quit +} + +// Shutdown notifies a healthcheck server to shutdown. +func (s *Server) Shutdown() { + log.Info("Closing healthcheck server ...") + select { + case s.quit <- true: + default: + } +} diff --git a/tools/healthcheck/pkg/helthcheck/tcp_checker.go b/tools/healthcheck/pkg/helthcheck/tcp_checker.go new file mode 100644 index 000000000..5b6026cc0 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/tcp_checker.go @@ -0,0 +1,122 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "io" + "net" + "time" +) + +var _ CheckMethod = (*TCPChecker)(nil) + +// TCPChecker contains configuration specific to a TCP healthcheck. +type TCPChecker struct { + Config *CheckerConfig + + Receive string + Send string +} + +// NewTCPChecker returns an initialised TCPChecker. +func NewTCPChecker(recv, send string) *TCPChecker { + return &TCPChecker{Receive: recv, Send: send} +} + +func (hc *TCPChecker) BindConfig(conf *CheckerConfig) { + hc.Config = conf +} + +// String returns the string representation of a TCP healthcheck. +func (hc *TCPChecker) String() string { + return fmt.Sprintf("TCP checker for %v", hc.Config.Id) +} + +// Check executes a TCP healthcheck. +func (hc *TCPChecker) Check(target Target, timeout time.Duration) *Result { + msg := fmt.Sprintf("TCP connect to %s", target.Addr()) + start := time.Now() + if timeout == time.Duration(0) { + timeout = DefaultCheckConfig.Timeout + } + deadline := start.Add(timeout) + + dial := net.Dialer{ + Timeout: timeout, + } + conn, err := dial.Dial(target.Network(), target.Addr()) + if err != nil { + msg = fmt.Sprintf("%s: failed to dail", msg) + return NewResult(start, msg, false, err) + } + defer conn.Close() + + tcpConn, ok := conn.(*net.TCPConn) + if !ok { + msg = fmt.Sprintf("%s: failed to create tcp socket", msg) + return NewResult(start, msg, false, err) + } + + if hc.Send == "" && hc.Receive == "" { + msg = fmt.Sprintf("%s succeed", msg) + return NewResult(start, msg, true, err) + } + + err = tcpConn.SetDeadline(deadline) + if err != nil { + msg = fmt.Sprintf("%s: failed to set deadline", msg) + return NewResult(start, msg, false, err) + } + + if hc.Send != "" { + err = writeFull(tcpConn, []byte(hc.Send)) + if err != nil { + msg = fmt.Sprintf("%s: failed to send request", msg) + return NewResult(start, msg, false, err) + } + } + + if hc.Receive != "" { + buf := make([]byte, len(hc.Receive)) + n, err := io.ReadFull(tcpConn, buf) + if err != nil { + msg = fmt.Sprintf("%s: failed to read response", msg) + return NewResult(start, msg, false, err) + } + got := string(buf[0:n]) + if got != hc.Receive { + msg = fmt.Sprintf("%s: unexpected response %q", msg, got) + return NewResult(start, msg, false, err) + } + } + + msg = fmt.Sprintf("%s succeed", msg) + return NewResult(start, msg, true, err) +} + +func writeFull(conn net.Conn, b []byte) error { + for len(b) > 0 { + n, err := conn.Write(b) + if err != nil { + return err + } + b = b[n:] + } + return nil +} diff --git a/tools/healthcheck/pkg/helthcheck/test/tcp_checker.go b/tools/healthcheck/pkg/helthcheck/test/tcp_checker.go new file mode 100644 index 000000000..cd8f1707b --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/test/tcp_checker.go @@ -0,0 +1,130 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package main + +import ( + "errors" + "fmt" + "io" + "net" + "time" +) + +func Check(addr, network, send, recv string, timeout time.Duration) *Result { + msg := fmt.Sprintf("TCP connect to %s", addr) + start := time.Now() + if timeout == time.Duration(0) { + timeout = 3 * time.Second + } + deadline := start.Add(timeout) + + dial := net.Dialer{ + Timeout: timeout, + } + conn, err := dial.Dial(network, addr) + if err != nil { + msg = fmt.Sprintf("%s: failed to dail", msg) + return NewResult(start, msg, false, err) + } + defer conn.Close() + + tcpConn, ok := conn.(*net.TCPConn) + if !ok { + msg = fmt.Sprintf("%s: not a TCP conn", msg) + err = errors.New("failed to create tcp socket") + return NewResult(start, msg, false, err) + } + + if send == "" && recv == "" { + msg = fmt.Sprintf("%s: succeed", msg) + return NewResult(start, msg, true, err) + } + + err = tcpConn.SetDeadline(deadline) + if err != nil { + msg = fmt.Sprintf("%s: failed to set deadline", msg) + return NewResult(start, msg, false, err) + } + + if send != "" { + err = writeFull(tcpConn, []byte(send)) + if err != nil { + msg = fmt.Sprintf("%s: failed to send request", msg) + return NewResult(start, msg, false, err) + } + } + + if recv != "" { + buf := make([]byte, len(recv)) + n, err := io.ReadFull(tcpConn, buf) + if err != nil { + msg = fmt.Sprintf("%s: failed to read response", msg) + return NewResult(start, msg, false, err) + } + got := string(buf[0:n]) + if got != recv { + msg = fmt.Sprintf("%s: unexpected response %q", msg, got) + return NewResult(start, msg, false, err) + } + } + + msg = fmt.Sprintf("%s: succeed", msg) + return NewResult(start, msg, true, err) +} + +func writeFull(conn net.Conn, b []byte) error { + for len(b) > 0 { + n, err := conn.Write(b) + if err != nil { + return err + } + b = b[n:] + } + return nil +} + +type Result struct { + Message string + Success bool + time.Duration + Err error +} + +func (r *Result) String() string { + msg := fmt.Sprintf("[result: %v, duration: %v] ", r.Success, r.Duration) + if r.Err != nil { + return msg + r.Err.Error() + } + return msg + r.Message +} + +func NewResult(start time.Time, msg string, success bool, err error) *Result { + duration := time.Since(start) + return &Result{msg, success, duration, err} +} + +func main() { + fmt.Println(Check("192.168.88.30:80", "tcp4", "", "", 10*time.Second)) + fmt.Println(Check("192.168.88.30:80", "tcp4", "1", "cds1sfdafasdfasdfafafasssssssssssssssssssssssssss", 1*time.Second)) + fmt.Println(Check("192.168.88.31:80", "tcp4", "", "", 10*time.Second)) + fmt.Println(Check("10.130.133.208:80", "tcp4", "", "", 0)) + fmt.Println(Check("1.2.1.2:12123", "tcp4", "", "", 0)) + fmt.Println(Check("[2001::30]:80", "tcp6", "", "", 0)) + fmt.Println(Check("[2001::30]:80", "tcp6", "a", "HTTP", 0)) + fmt.Println(Check("[2001::33]:81", "tcp6", "", "", 0)) +} diff --git a/tools/healthcheck/pkg/helthcheck/test/udp_checker.go b/tools/healthcheck/pkg/helthcheck/test/udp_checker.go new file mode 100644 index 000000000..150587126 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/test/udp_checker.go @@ -0,0 +1,119 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package main + +import ( + "errors" + "fmt" + "net" + "os" + "time" +) + +func udpPortCheck(udpConn *net.UDPConn) (bool, error) { + return true, nil +} + +func Check(addr, network, send, recv string, timeout time.Duration) *Result { + msg := fmt.Sprintf("UDP check to %s", addr) + start := time.Now() + if timeout == time.Duration(0) { + timeout = 3 + } + deadline := start.Add(timeout) + + dial := net.Dialer{Timeout: timeout} + conn, err := dial.Dial(network, addr) + if err != nil { + msg = fmt.Sprintf("%s: failed to dail", msg) + return NewResult(start, msg, false, err) + } + defer conn.Close() + + udpConn, ok := conn.(*net.UDPConn) + if !ok { + msg = fmt.Sprintf("%s: not an UDP conn", msg) + err = errors.New("failed to create udp socket") + return NewResult(start, msg, false, err) + } + + err = udpConn.SetDeadline(deadline) + if err != nil { + msg = fmt.Sprintf("%s: failed to set deadline", msg) + return NewResult(start, msg, false, err) + } + + if _, err = udpConn.Write([]byte(send)); err != nil { + msg = fmt.Sprintf("%s: failed to send request", msg) + return NewResult(start, msg, false, err) + } + + buf := make([]byte, len(recv)+1) + n, _, err := udpConn.ReadFrom(buf) + if err != nil { + if send == "" && recv == "" { + if neterr, ok := err.(net.Error); ok { + // When Send and Recv is none and i/o timeout, the dest port state + // is undetermined. Check shall return success in the case. + if neterr.Timeout() { + msg = fmt.Sprintf("%s: %s, port state unkown", msg, err) + return NewResult(start, msg, true, nil) + } + } + } + msg = fmt.Sprintf("%s: failed to read response", msg) + return NewResult(start, msg, false, err) + } + + got := string(buf[0:n]) + if got != recv { + msg = fmt.Sprintf("%s: unexpected response %q", msg, got) + return NewResult(start, msg, false, err) + } + msg = fmt.Sprintf("%s: succeed", msg) + return NewResult(start, msg, true, err) +} + +type Result struct { + Message string + Success bool + time.Duration + Err error +} + +func (r *Result) String() string { + msg := fmt.Sprintf("[result: %v, duration: %v] ", r.Success, r.Duration) + if r.Err != nil { + return msg + r.Err.Error() + } + return msg + r.Message +} + +func NewResult(start time.Time, msg string, success bool, err error) *Result { + duration := time.Since(start) + return &Result{msg, success, duration, err} +} + +func main() { + if len(os.Args) != 6 { + fmt.Printf("%s addr network send recv timeout\n", os.Args[0]) + return + } + timeout, _ := time.ParseDuration(os.Args[5]) + fmt.Println(Check(os.Args[1], os.Args[2], os.Args[3], os.Args[4], timeout)) +} diff --git a/tools/healthcheck/pkg/helthcheck/types.go b/tools/healthcheck/pkg/helthcheck/types.go new file mode 100644 index 000000000..560ebc84e --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/types.go @@ -0,0 +1,225 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "net" + "strconv" + "strings" + "time" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +// Id provides the unique identifier of a given healthcheck. It has format +// of {vs}/{rs}, where {vs} is service id confined by the lb_interface_type, +// and {vs} is the backend id within the service of format ip:proto:port. +// Id should be created using NewId() function. +type Id string + +func NewId(vs string, rs *Target) *Id { + id := Id(fmt.Sprintf("%s/%v", vs, rs)) + return &id +} + +func (id Id) Vs() string { + strId := string(id) + idx := strings.LastIndexByte(strId, '/') + if idx < 0 { + return "" + } + return strId[:idx] +} + +func (id Id) Rs() *Target { + strId := string(id) + idx := strings.LastIndexByte(strId, '/') + if idx < 0 { + return nil + } + return NewTargetFromStr(strId[idx+1:]) +} + +// MethodType is the type of check method supported for now. +type MethodType int + +const ( + MethodTypeNone MethodType = iota + MethodTypeTCP + MethodTypeUDP + MethodTypePING +) + +// String returns the name for the given MethodType. +func (h MethodType) String() string { + switch h { + case MethodTypeTCP: + return "TCP" + case MethodTypeUDP: + return "UDP" + case MethodTypePING: + return "PING" + } + return "(unknown)" +} + +// CheckMethod is the interface that must be implemented by a healthcheck. +type CheckMethod interface { + Check(target Target, timeout time.Duration) *Result + BindConfig(conf *CheckerConfig) + String() string +} + +// State represents the current state of a healthcheck. +type State int + +const ( + StateUnknown State = iota + StateUnhealthy + StateHealthy +) + +var stateNames = map[State]string{ + StateUnknown: "Unknown", + StateUnhealthy: "Unhealthy", + StateHealthy: "Healthy", +} + +// String returns the string representation for the given healthcheck state. +func (s State) String() string { + if name, ok := stateNames[s]; ok { + return name + } + return "" +} + +// Target specifies the target for a healthcheck. +type Target struct { + IP net.IP // IP address of the healthcheck target. + Port uint16 + Proto utils.IPProto +} + +// Create a Target from str of format "IPv4:Proto:Port" or "[IPv6]:Proto:Port". +func NewTargetFromStr(str string) *Target { + idx2 := strings.LastIndexByte(str, ':') + idx1 := strings.LastIndexByte(str[:idx2], ':') + if idx1 < 0 || idx2 < 0 || idx1 >= idx2 { + return nil + } + port, err := strconv.ParseUint(str[idx2:], 10, 16) + if err != nil { + return nil + } + proto := utils.IPProtoFromStr(str[idx1:idx2]) + if proto == 0 { + return nil + } + ip := net.ParseIP(strings.TrimRight(strings.TrimLeft(str[:idx1], "["), "]")) + if ip == nil { + return nil + } + return &Target{ip, uint16(port), proto} +} + +// String returns the string representation of a healthcheck target. +func (t Target) String() string { + if t.IP.To4() != nil { + return fmt.Sprintf("%v:%v:%d", t.IP, t.Proto, t.Port) + } + return fmt.Sprintf("[%v]:%v:%d", t.IP, t.Proto, t.Port) +} + +// Addr returns the IP:Port representation of a healthcheck target +func (t Target) Addr() string { + if t.IP.To4() != nil { + return fmt.Sprintf("%v:%d", t.IP, t.Port) + } + return fmt.Sprintf("[%v]:%d", t.IP, t.Port) +} + +// Network returns the network name for the healthcheck target. +func (t *Target) Network() string { + var network string + version := 4 + if t.IP.To4() == nil { + version = 6 + } + switch t.Proto { + case utils.IPProtoICMP: + network = "ip4:icmp" + case utils.IPProtoICMPv6: + network = "ip6:ipv6-icmp" + case utils.IPProtoTCP: + network = fmt.Sprintf("tcp%d", version) + case utils.IPProtoUDP: + network = fmt.Sprintf("udp%d", version) + default: + return "(unknown)" + } + return network +} + +// Result stores the result of a healthcheck performed by a checker. +type Result struct { + Message string + Success bool + time.Duration + Err error +} + +// String returns the string representation of a healthcheck result. +func (r *Result) String() string { + msg := fmt.Sprintf("[result: %v, duration: %v] ", r.Success, r.Duration) + if r.Err != nil { + return msg + r.Err.Error() + } + return msg + r.Message +} + +func NewResult(start time.Time, msg string, success bool, err error) *Result { + // TODO: Make this clock skew safe. + duration := time.Since(start) + return &Result{msg, success, duration, err} +} + +// Status represents the current status of a healthcheck instance. +type Status struct { + LastCheck time.Time + Duration time.Duration + Failures uint64 + Successes uint64 + State + Weight uint16 + Message string +} + +// Notification stores a status notification for a healthcheck. +type Notification struct { + Id + Target + Status +} + +// String returns the string representation for the given notification. +func (n *Notification) String() string { + return fmt.Sprintf("ID %v, %v, Weight %d, Fail %v, Success %v, Last check %s in %v", n.Id, + stateNames[n.Status.State], n.Status.Weight, n.Status.Failures, n.Status.Successes, + n.Status.LastCheck.Format("2006-01-02 15:04:05.000"), n.Status.Duration) +} diff --git a/tools/healthcheck/pkg/helthcheck/udp_checker.go b/tools/healthcheck/pkg/helthcheck/udp_checker.go new file mode 100644 index 000000000..ceb6d4467 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/udp_checker.go @@ -0,0 +1,108 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "net" + "time" +) + +var _ CheckMethod = (*UDPChecker)(nil) + +// UDPChecker contains configuration specific to a UDP healthcheck. +type UDPChecker struct { + Config *CheckerConfig + + Receive string + Send string +} + +// NewUDPChecker returns an initialised UDPChecker. +func NewUDPChecker(recv, send string) *UDPChecker { + return &UDPChecker{Receive: recv, Send: send} +} + +func (hc *UDPChecker) BindConfig(conf *CheckerConfig) { + hc.Config = conf +} + +// String returns the string representation of a UDP healthcheck. +func (hc *UDPChecker) String() string { + return fmt.Sprintf("UDP checker for %v", hc.Config.Id) +} + +// Check executes a UDP healthcheck. +func (hc *UDPChecker) Check(target Target, timeout time.Duration) *Result { + msg := fmt.Sprintf("UDP check to %s", target.Addr()) + start := time.Now() + if timeout == time.Duration(0) { + timeout = DefaultCheckConfig.Timeout + } + deadline := start.Add(timeout) + + dial := net.Dialer{Timeout: timeout} + conn, err := dial.Dial(target.Network(), target.Addr()) + if err != nil { + msg = fmt.Sprintf("%s: failed to dail", msg) + return NewResult(start, msg, false, err) + } + defer conn.Close() + + udpConn, ok := conn.(*net.UDPConn) + if !ok { + msg = fmt.Sprintf("%s: failed to create udp socket", msg) + return NewResult(start, msg, false, err) + } + + err = udpConn.SetDeadline(deadline) + if err != nil { + msg = fmt.Sprintf("%s: failed to set deadline", msg) + return NewResult(start, msg, false, err) + } + + if _, err = udpConn.Write([]byte(hc.Send)); err != nil { + msg = fmt.Sprintf("%s: failed to send request", msg) + return NewResult(start, msg, false, err) + } + + buf := make([]byte, len(hc.Receive)+1) + n, _, err := udpConn.ReadFrom(buf) + if err != nil { + if hc.Send == "" && hc.Receive == "" { + if neterr, ok := err.(net.Error); ok { + // When hc.Send and hc.Receive is none and i/o timeout, the dest port state + // is undetermined. Check shall return success in the case. + if neterr.Timeout() { + msg = fmt.Sprintf("%s: %s, port state unkown", msg, err) + return NewResult(start, msg, true, nil) + } + } + } + msg = fmt.Sprintf("%s: failed to read response", msg) + return NewResult(start, msg, false, err) + } + + got := string(buf[0:n]) + if got != hc.Receive { + msg = fmt.Sprintf("%s: unexpected response %q", msg, got) + return NewResult(start, msg, false, err) + } + msg = fmt.Sprintf("%s: succeed", msg) + return NewResult(start, msg, true, err) +} diff --git a/tools/healthcheck/pkg/lb/dpvs_agent.go b/tools/healthcheck/pkg/lb/dpvs_agent.go new file mode 100644 index 000000000..0e0072785 --- /dev/null +++ b/tools/healthcheck/pkg/lb/dpvs_agent.go @@ -0,0 +1,228 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package lb + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "strings" + "time" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +var _ Comm = (*DpvsAgentComm)(nil) + +var ( + serverDefault = "localhost:6600" + listUri = LbApi{"/v2/vs", http.MethodGet} + noticeUri = LbApi{"/v2/vs/%s/rs?healthcheck=true", http.MethodPut} + + client *http.Client = &http.Client{Timeout: httpClientTimeout} +) + +const httpClientTimeout = 10 * time.Second + +type DpvsAgentComm struct { + listApi LbApi + noticeApis []LbApi +} + +type LbApi struct { + Url string + HttpMethod string // http.MethodGet, http.MethodPut, ... +} + +type DpvsAgentRs struct { + IP string `json:"ip"` + Port uint16 `json:"port"` + Weight uint16 `json:"weight"` + Inhibited bool `json:"inhibited,omitempty"` +} + +type DpvsAgentRsItem struct { + Spec DpvsAgentRs +} + +type DpvsAgentRsList struct { + Items []DpvsAgentRsItem +} + +type DpvsAgentRsListPut struct { + Items []DpvsAgentRs +} + +type DpvsAgentVs struct { + Addr string + Port uint16 + Proto uint16 + DestCheck []string + Rss DpvsAgentRsList `json:"RSs"` +} + +type DpvsAgentVsList struct { + Items []DpvsAgentVs +} + +func (avs *DpvsAgentVs) serviceId() string { + return strings.ToLower(fmt.Sprintf("%s-%d-%s", avs.Addr, avs.Port, + utils.IPProto(avs.Proto))) +} + +func (avs *DpvsAgentVs) toVs() (*VirtualService, error) { + vip := net.ParseIP(avs.Addr) + if vip == nil { + return nil, fmt.Errorf("invalid Vs Addr %q", avs.Addr) + } + vport := avs.Port + proto := utils.IPProto(avs.Proto) + if proto != utils.IPProtoTCP && proto != utils.IPProtoUDP { + return nil, fmt.Errorf("Vs protocol type 0x%x not supported", avs.Port) + } + checker := CheckerNone + for _, name := range avs.DestCheck { + name = strings.ToLower(name) + switch name { + case "tcp": + checker = CheckerTCP + case "udp": + checker = CheckerUDP + case "ping": + checker = CheckerPING + } + } + vs := &VirtualService{ + Checker: checker, + IP: vip, + Port: vport, + Protocol: proto, + RSs: make([]RealServer, len(avs.Rss.Items)), + } + vs.Id = avs.serviceId() + + for i, ars := range avs.Rss.Items { + rip := net.ParseIP(ars.Spec.IP) + if rip == nil { + return nil, fmt.Errorf("%s: invalid Rs IP %q", vs.Id, ars.Spec.IP) + } + rs := &RealServer{ + IP: rip, + Port: ars.Spec.Port, + Weight: ars.Spec.Weight, + Inhibited: ars.Spec.Inhibited, + } + vs.RSs[i] = *rs + } + return vs, nil +} + +func (avslist *DpvsAgentVsList) toVsList() ([]VirtualService, error) { + if len(avslist.Items) == 0 { + return nil, nil + } + vslist := make([]VirtualService, len(avslist.Items)) + for i, avs := range avslist.Items { + vs, err := avs.toVs() + if err != nil { + return nil, err + } + vslist[i] = *vs + } + return vslist, nil +} + +func NewDpvsAgentComm(server string) *DpvsAgentComm { + if len(server) == 0 { + server = serverDefault + } + addr := "http://" + server + return &DpvsAgentComm{ + listApi: LbApi{addr + listUri.Url, listUri.HttpMethod}, + noticeApis: []LbApi{{addr + noticeUri.Url, noticeUri.HttpMethod}}, + } +} + +func (comm *DpvsAgentComm) ListVirtualServices() ([]VirtualService, error) { + req, err := http.NewRequest(comm.listApi.HttpMethod, comm.listApi.Url, nil) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + data, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + if len(data) == 0 { + return nil, nil + } + //fmt.Printf("Code: %v, Resp: %v, Err: %v\n", resp.StatusCode, string(data), err) + var svcs DpvsAgentVsList + if err = json.Unmarshal(data, &svcs); err != nil { + return nil, err + } + vslist, err := svcs.toVsList() + if err != nil { + return nil, err + } + //fmt.Println(vslist) + return vslist, nil +} + +func (comm *DpvsAgentComm) UpdateByChecker(targets []VirtualService) error { + // TODO: support batch operation + for _, vs := range targets { + for _, rs := range vs.RSs { + ars := &DpvsAgentRsListPut{ + Items: []DpvsAgentRs{ + { + IP: rs.IP.String(), + Port: rs.Port, + Weight: rs.Weight, + Inhibited: rs.Inhibited, + }, + }, + } + data, err := json.Marshal(ars) + if err != nil { + return err + } + for _, notice := range comm.noticeApis { + url := fmt.Sprintf(notice.Url, vs.Id) + req, err := http.NewRequest(notice.HttpMethod, url, bytes.NewBuffer(data)) + req.Header.Set("Content-Type", "application/json") + resp, err := client.Do(req) + if err != nil { + return err + } + //fmt.Println("Code:", resp.Status) + if resp.StatusCode != 200 { + data, _ = io.ReadAll(resp.Body) + return fmt.Errorf("CODE: %v, ERROR: %s", resp.StatusCode, strings.TrimSpace(string(data))) + } + resp.Body.Close() + } + } + } + return nil +} diff --git a/tools/healthcheck/pkg/lb/dpvs_agent_test.go b/tools/healthcheck/pkg/lb/dpvs_agent_test.go new file mode 100644 index 000000000..2d8e00122 --- /dev/null +++ b/tools/healthcheck/pkg/lb/dpvs_agent_test.go @@ -0,0 +1,49 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package lb + +import ( + "testing" + "time" +) + +func TestListAndUpdate(t *testing.T) { + comm := NewDpvsAgentComm("") + vss, err := comm.ListVirtualServices() + if err != nil { + t.Errorf("list error: %v", err) + } + t.Logf("list Results: %v", vss) + if len(vss) < 2 { + return + } + t.Logf("Updating %v", vss[1]) + vss[1].RSs[0].Weight = 0 + vss[1].RSs[0].Inhibited = true + //vss[1].RSs[0].Port = 8081 + //vss[1].RSs[1].Weight = 100 + //vss[1].RSs[1].Inhibited = false + //vss[1].RSs[1].IP = net.ParseIP("1.2.3.4") + if err = comm.UpdateByChecker(vss[1:2]); err != nil { + t.Errorf("inhibit rs error: %v", err) + } + time.Sleep(3 * time.Second) + t.Logf("Restoring %v", vss[1]) + vss[1].RSs[0].Weight = 100 + vss[1].RSs[0].Inhibited = false + if err = comm.UpdateByChecker(vss[1:2]); err != nil { + t.Errorf("restore rs error: %v", err) + } +} diff --git a/tools/healthcheck/pkg/lb/types.go b/tools/healthcheck/pkg/lb/types.go new file mode 100644 index 000000000..bc3f8a02e --- /dev/null +++ b/tools/healthcheck/pkg/lb/types.go @@ -0,0 +1,65 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package lb + +import ( + "net" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +type Checker uint16 + +const ( + CheckerNone Checker = iota + CheckerTCP + CheckerUDP + CheckerPING +) + +type RealServer struct { + IP net.IP + Port uint16 + Weight uint16 + Inhibited bool +} + +type VirtualService struct { + Id string + Checker Checker + Protocol utils.IPProto + Port uint16 + IP net.IP + RSs []RealServer +} + +type Comm interface { + ListVirtualServices() ([]VirtualService, error) + UpdateByChecker(targets []VirtualService) error +} + +func (checker Checker) String() string { + switch checker { + case CheckerNone: + return "checker_none" + case CheckerTCP: + return "checker_tcp" + case CheckerUDP: + return "checker_udp" + case CheckerPING: + return "checker_ping" + } + return "checker_unknown" +} diff --git a/tools/healthcheck/pkg/server/server.go b/tools/healthcheck/pkg/server/server.go new file mode 100644 index 000000000..d6591d0da --- /dev/null +++ b/tools/healthcheck/pkg/server/server.go @@ -0,0 +1,72 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "fmt" + "os" + "os/signal" + "runtime" + "syscall" + + log "github.com/golang/glog" +) + +// Shutdowner is an interface for a server that can be shutdown. +type Shutdowner interface { + Shutdown() +} + +var signalNames = map[syscall.Signal]string{ + syscall.SIGINT: "SIGINT", + syscall.SIGQUIT: "SIGQUIT", + syscall.SIGTERM: "SIGTERM", + syscall.SIGUSR1: "SIGUSR1", +} + +// signalName returns a string containing the standard name for a given signal. +func signalName(s syscall.Signal) string { + if name, ok := signalNames[s]; ok { + return name + } + return fmt.Sprintf("SIG %d", s) +} + +// ShutdownHandler configures signal handling and initiates a shutdown if a +// SIGINT, SIGQUIT or SIGTERM is received by the process. +func ShutdownHandler(server Shutdowner) { + sigc := make(chan os.Signal, 3) + signal.Notify(sigc, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGUSR1) + go func() { + for s := range sigc { + name := s.String() + if sig, ok := s.(syscall.Signal); ok { + if sig == syscall.SIGUSR1 { + dumpStacks() + continue + } + name = signalName(sig) + } + log.Infof("Received %v, initiating shutdown...", name) + server.Shutdown() + } + }() +} + +func dumpStacks() { + buf := make([]byte, 16384) + buf = buf[:runtime.Stack(buf, true)] + log.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf) +} diff --git a/tools/healthcheck/pkg/utils/net.go b/tools/healthcheck/pkg/utils/net.go new file mode 100644 index 000000000..a82e36743 --- /dev/null +++ b/tools/healthcheck/pkg/utils/net.go @@ -0,0 +1,124 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "fmt" + "net" + "syscall" +) + +// AF represents a network address family. +type AF int + +const ( + IPv4 AF = syscall.AF_INET + IPv6 AF = syscall.AF_INET6 +) + +// String returns the string representation of an AF. +func (af AF) String() string { + switch af { + case IPv4: + return "IPv4" + case IPv6: + return "IPv6" + } + return "(unknown)" +} + +// AFs returns the supported address families. +func AFs() []AF { + return []AF{IPv4, IPv6} +} + +// IP specifies an IP address. +type IP [net.IPv6len]byte + +// NewIP returns a seesaw IP initialised from a net.IP address. +func NewIP(nip net.IP) IP { + var ip IP + copy(ip[:], nip.To16()) + return ip +} + +// ParseIP parses the given string and returns a healthcheck IP initialised +// with the resulting IP address. +func ParseIP(ip string) IP { + return NewIP(net.ParseIP(ip)) +} + +// Equal returns true of the given IP addresses are equal, as determined by +// net.IP.Equal(). +func (ip IP) Equal(eip IP) bool { + return ip.IP().Equal(eip.IP()) +} + +// IP returns the net.IP representation of a healthcheck IP address. +func (ip IP) IP() net.IP { + return net.IP(ip[:]) +} + +// AF returns the address family of a healthcheck IP address. +func (ip IP) AF() AF { + if ip.IP().To4() != nil { + return IPv4 + } + return IPv6 +} + +// String returns the string representation of an IP address. +func (ip IP) String() string { + return fmt.Sprintf("%v", ip.IP()) +} + +// IPProto specifies an IP protocol. +type IPProto uint16 + +const ( + IPProtoICMP IPProto = syscall.IPPROTO_ICMP + IPProtoICMPv6 IPProto = syscall.IPPROTO_ICMPV6 + IPProtoTCP IPProto = syscall.IPPROTO_TCP + IPProtoUDP IPProto = syscall.IPPROTO_UDP +) + +// String returns the name for the given protocol value. +func (proto IPProto) String() string { + switch proto { + case IPProtoICMP: + return "ICMP" + case IPProtoICMPv6: + return "ICMPv6" + case IPProtoTCP: + return "TCP" + case IPProtoUDP: + return "UDP" + } + return fmt.Sprintf("IP(%d)", proto) +} + +func IPProtoFromStr(str string) IPProto { + switch str { + case "TCP": + return IPProtoTCP + case "UDP": + return IPProtoUDP + case "ICMP": + return IPProtoICMP + case "ICMPv6": + return IPProtoICMPv6 + } + return 0 +} diff --git a/tools/healthcheck/test/README.md b/tools/healthcheck/test/README.md new file mode 100644 index 000000000..d8977e4b6 --- /dev/null +++ b/tools/healthcheck/test/README.md @@ -0,0 +1,238 @@ +DPVS 健康检查程序压力测试 +--- + +# 测试方法 + +首先,使用 [stress-test.sh](./stress-test.sh) 脚本生成测试业务。 + +* 测试业务列表只需要有 VS 和 RS 配置,不需要配置 VIP、local IP 等。 +* 通过调整脚本 `Step 2` 中的 i, j 两个循环控制变量的范围控制产生的健康检查配置数量的多少。 +* 通过调整脚本 `Step 2` 中循环控制变量 j 的范围控制每个 VS 下配置的 RS 数量的多少,默认每个 VS 配置 5 个 RS。 + +测试业务生成后 RS 初始状态都是 UP(权重为1): + +``` +## 未启动健康检查服务时测试业务状态 +IP Virtual Server version 1.9.4 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.0.1:80 wlc + -> 192.168.19.155:8080 FullNat 1 0 0 + -> 192.168.19.156:8080 FullNat 1 0 0 + -> 192.168.19.157:8080 FullNat 1 0 0 + -> 192.168.19.158:8080 FullNat 1 0 0 + -> 192.168.19.159:8080 FullNat 1 0 0 +TCP 192.168.0.2:80 wlc + -> 192.168.19.160:8080 FullNat 1 0 0 + -> 192.168.19.161:8080 FullNat 1 0 0 + -> 192.168.19.162:8080 FullNat 1 0 0 + -> 192.168.19.163:8080 FullNat 1 0 0 + -> 192.168.19.164:8080 FullNat 1 0 0 +TCP 192.168.0.3:80 wlc + -> 192.168.19.165:8080 FullNat 1 0 0 + -> 192.168.19.166:8080 FullNat 1 0 0 +... +``` + +但实际上这些 RS 是不通的,后续健康检查程序会把所有的 RS 设置为 DOWN(权重为 0,并添加 标志)。 + +``` +## 健康检查完成测试业务状态 +IP Virtual Server version 1.9.4 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.0.1:80 wlc + -> 192.168.19.155:8080 FullNat 0 0 0 inhibited + -> 192.168.19.156:8080 FullNat 0 0 0 inhibited + -> 192.168.19.157:8080 FullNat 0 0 0 inhibited + -> 192.168.19.158:8080 FullNat 0 0 0 inhibited + -> 192.168.19.159:8080 FullNat 0 0 0 inhibited +TCP 192.168.0.2:80 wlc + -> 192.168.19.160:8080 FullNat 0 0 0 inhibited + -> 192.168.19.161:8080 FullNat 0 0 0 inhibited + -> 192.168.19.162:8080 FullNat 0 0 0 inhibited + -> 192.168.19.163:8080 FullNat 0 0 0 inhibited + -> 192.168.19.164:8080 FullNat 0 0 0 inhibited +TCP 192.168.0.3:80 wlc + -> 192.168.19.165:8080 FullNat 0 0 0 inhibited + -> 192.168.19.166:8080 FullNat 0 0 0 inhibited +... +``` + +测试业务创建后,`stress-test.sh` 脚本会循环检测当前的 RS 总数和被置为 DOWN 状态的 RS 数量。当我们启动健康检查程序后, + +```sh +./healthcheck -log_dir=./log +``` + +测试业务的 RS 会陆续由初始的 UP 状态而转为 DOWN 状态,我们根据 RS 被置为 DOWN 的数量的增长速度即可评估健康检查程序的并发性能。 + +# 测试数据 + +* RS 数量:测试脚本自动创建的 RS 总量 +* 初始探测耗时:健康检查程序启动到看到第一个 RS 被置为 DOWN 的时间。 +* 耗时(5分位):从第一个 RS 被置为 DOWN 到 50% 的 RS 被置为 DOWN 的时间。 +* 耗时(9分位):从第一个 RS 被置为 DOWN 到 90% 的 RS 被置为 DOWN 的时间。 +* 总耗时:从第一个 RS 被置为 DOWN 到所有的 RS 被置为 DOWN 的时间。 +* CPU 占用:健康检查程序的 CPU 使用量(用 iftop 命令观测得到)。 +* 内存占用:健康检查程序的内存使用量(用 iftop 命令观测得到)。 + +| RS数量 | 初始探测耗时 | 耗时(5分位) | 耗时(9分位) | 总耗时 | CPU占用 | 内存占用 | +| ------ | ------------ | ------------ | ----------- | ------ | ------- | -------- | +| 0 | 0 | 0 | 0 | 0 | 0.1核 | 100MB | +| 1040 | 6s | 1s | 2s | 2s | 0.1核 | 110MB | +| 5080 | 6s | 1s | 2s | 3s | 0.4核 | 160MB | +| 10160 | 5s | 4s | 6s | 8s | 0.8核 | 200MB | +| 26670 | 5s | 9s | 16s | 34s | 1.8核 | 560MB | +| 52070 | 7s | 7s | 33s | 90s | 4.4核 | 1120MB | + +> 说明: 健康检查程序默认配置的 retry 为 1 次、timeout 为 1s、周期为 3s,因此初始探测时间理论上为 1s(timeout) + 3s (delay loop) + 1s (timeout) = 5s。该数据和我们测试数据基本一致,不计入性能延迟。 + + +# 测试日志 + +**1040 个 RS** + +``` +[2023-06-02.17:08:51] total: 1040, inhibited: 0 +[2023-06-02.17:08:55] total: 1040, inhibited: 0 +[2023-06-02.17:08:56] total: 1040, inhibited: 0 +[2023-06-02.17:08:57] total: 1040, inhibited: 0 +[2023-06-02.17:08:58] total: 1040, inhibited: 321 +[2023-06-02.17:08:59] total: 1040, inhibited: 709 +[2023-06-02.17:09:00] total: 1040, inhibited: 1040 +[2023-06-02.17:09:01] total: 1040, inhibited: 1040 +[2023-06-02.17:09:02] total: 1040, inhibited: 1040 +[2023-06-02.17:09:03] total: 1040, inhibited: 1040 +``` + +**5080 个 RS** + +``` +[2023-06-02.17:02:17] total: 5080, inhibited: 0 +[2023-06-02.17:02:18] total: 5080, inhibited: 0 +[2023-06-02.17:02:19] total: 5080, inhibited: 0 +[2023-06-02.17:02:20] total: 5080, inhibited: 0 +[2023-06-02.17:02:21] total: 5080, inhibited: 1474 +[2023-06-02.17:02:22] total: 5080, inhibited: 3340 +[2023-06-02.17:02:23] total: 5080, inhibited: 5078 +[2023-06-02.17:02:25] total: 5080, inhibited: 5080 +[2023-06-02.17:02:26] total: 5080, inhibited: 5080 +[2023-06-02.17:02:27] total: 5080, inhibited: 5080 +[2023-06-02.17:02:28] total: 5080, inhibited: 5080 +``` + +**10160 个 RS** + +``` +[2023-06-02.16:51:21] total: 10160, inhibited: 0 +[2023-06-02.16:51:23] total: 10160, inhibited: 0 +[2023-06-02.16:51:24] total: 10160, inhibited: 0 +[2023-06-02.16:51:25] total: 10160, inhibited: 0 +[2023-06-02.16:51:27] total: 10160, inhibited: 0 +[2023-06-02.16:51:28] total: 10160, inhibited: 52 +[2023-06-02.16:51:29] total: 10160, inhibited: 2050 +[2023-06-02.16:51:30] total: 10160, inhibited: 4021 +[2023-06-02.16:51:32] total: 10160, inhibited: 6027 +[2023-06-02.16:51:33] total: 10160, inhibited: 8094 +[2023-06-02.16:51:34] total: 10160, inhibited: 10116 +[2023-06-02.16:51:36] total: 10160, inhibited: 10160 +[2023-06-02.16:51:37] total: 10160, inhibited: 10160 +[2023-06-02.16:51:38] total: 10160, inhibited: 10160 +[2023-06-02.16:51:39] total: 10160, inhibited: 10160 +``` + +**26670 个 RS** + +``` +[2023-06-02.16:44:45] total: 26670, inhibited: 0 +[2023-06-02.16:44:46] total: 26670, inhibited: 0 +[2023-06-02.16:44:48] total: 26670, inhibited: 0 +[2023-06-02.16:44:50] total: 26670, inhibited: 0 +[2023-06-02.16:44:51] total: 26670, inhibited: 0 +[2023-06-02.16:44:53] total: 26670, inhibited: 1857 +[2023-06-02.16:44:55] total: 26670, inhibited: 4389 +[2023-06-02.16:44:56] total: 26670, inhibited: 6887 +[2023-06-02.16:44:58] total: 26670, inhibited: 9388 +[2023-06-02.16:45:00] total: 26670, inhibited: 12166 +[2023-06-02.16:45:02] total: 26670, inhibited: 15079 +[2023-06-02.16:45:03] total: 26670, inhibited: 17741 +[2023-06-02.16:45:05] total: 26670, inhibited: 20307 +[2023-06-02.16:45:07] total: 26670, inhibited: 23046 +[2023-06-02.16:45:09] total: 26670, inhibited: 25967 +[2023-06-02.16:45:10] total: 26670, inhibited: 26665 +[2023-06-02.16:45:12] total: 26670, inhibited: 26665 +[2023-06-02.16:45:14] total: 26670, inhibited: 26666 +[2023-06-02.16:45:16] total: 26670, inhibited: 26667 +[2023-06-02.16:45:18] total: 26670, inhibited: 26667 +[2023-06-02.16:45:19] total: 26670, inhibited: 26667 +[2023-06-02.16:45:21] total: 26670, inhibited: 26668 +[2023-06-02.16:45:23] total: 26670, inhibited: 26669 +[2023-06-02.16:45:25] total: 26670, inhibited: 26669 +[2023-06-02.16:45:26] total: 26670, inhibited: 26670 +[2023-06-02.16:45:28] total: 26670, inhibited: 26670 +[2023-06-02.16:45:30] total: 26670, inhibited: 26670 +[2023-06-02.16:45:32] total: 26670, inhibited: 26670 +[2023-06-02.16:45:34] total: 26670, inhibited: 26670 +``` + +**52070 个 RS** + +``` +[2023-06-02.16:37:39] total: 52070, inhibited: 0 +[2023-06-02.16:37:42] total: 52070, inhibited: 0 +[2023-06-02.16:37:44] total: 52070, inhibited: 0 +[2023-06-02.16:37:46] total: 52070, inhibited: 0 +[2023-06-02.16:37:48] total: 52070, inhibited: 1 +[2023-06-02.16:37:51] total: 52070, inhibited: 3032 +[2023-06-02.16:37:53] total: 52070, inhibited: 6743 +[2023-06-02.16:37:55] total: 52070, inhibited: 10129 +[2023-06-02.16:37:58] total: 52070, inhibited: 13849 +[2023-06-02.16:38:00] total: 52070, inhibited: 17478 +[2023-06-02.16:38:03] total: 52070, inhibited: 21177 +[2023-06-02.16:38:05] total: 52070, inhibited: 25168 +[2023-06-02.16:38:08] total: 52070, inhibited: 28867 +[2023-06-02.16:38:10] total: 52070, inhibited: 32909 +[2023-06-02.16:38:13] total: 52070, inhibited: 37034 +[2023-06-02.16:38:16] total: 52070, inhibited: 40798 +[2023-06-02.16:38:18] total: 52070, inhibited: 44471 +[2023-06-02.16:38:21] total: 52070, inhibited: 48355 +[2023-06-02.16:38:23] total: 52070, inhibited: 51830 +[2023-06-02.16:38:26] total: 52070, inhibited: 52025 +[2023-06-02.16:38:29] total: 52070, inhibited: 52030 +[2023-06-02.16:38:31] total: 52070, inhibited: 52034 +[2023-06-02.16:38:34] total: 52070, inhibited: 52035 +[2023-06-02.16:38:36] total: 52070, inhibited: 52035 +[2023-06-02.16:38:39] total: 52070, inhibited: 52035 +[2023-06-02.16:38:41] total: 52070, inhibited: 52035 +[2023-06-02.16:38:44] total: 52070, inhibited: 52035 +[2023-06-02.16:38:46] total: 52070, inhibited: 52035 +[2023-06-02.16:38:49] total: 52070, inhibited: 52035 +[2023-06-02.16:38:51] total: 52070, inhibited: 52037 +[2023-06-02.16:38:53] total: 52070, inhibited: 52042 +[2023-06-02.16:38:56] total: 52070, inhibited: 52042 +[2023-06-02.16:38:58] total: 52070, inhibited: 52047 +[2023-06-02.16:39:01] total: 52070, inhibited: 52049 +[2023-06-02.16:39:03] total: 52070, inhibited: 52052 +[2023-06-02.16:39:06] total: 52070, inhibited: 52053 +[2023-06-02.16:39:08] total: 52070, inhibited: 52057 +[2023-06-02.16:39:11] total: 52070, inhibited: 52060 +[2023-06-02.16:39:13] total: 52070, inhibited: 52060 +[2023-06-02.16:39:16] total: 52070, inhibited: 52065 +[2023-06-02.16:39:18] total: 52070, inhibited: 52070 +[2023-06-02.16:39:21] total: 52070, inhibited: 52070 +[2023-06-02.16:39:23] total: 52070, inhibited: 52070 +[2023-06-02.16:39:25] total: 52070, inhibited: 52070 +[2023-06-02.16:39:28] total: 52070, inhibited: 52070 +``` + +# 结论 + +1. 健康检查程序处理能力约为 3000 RS/s; +2. RS 状态变化不超过 5000 RS/s 时,健康检查程序能够快速摘除或恢复故障的 RS; +3. RS 状态变化 10000 RS/s 时,健康检查程序可以在 8s 内摘除或恢复故障的 RS; +3. 可以支持 50000+ RS/s 的 RS 状态变化,但约 50% 的 RS 故障可能得不到及时发现。 + +此外,在 50000+ 个 RS 配置处于健康状态稳定的场景下,单个 RS 故障的摘除和恢复时间约为 5s,与只有此 1 个 RS 配置时的处理时间区别不大。 + +> 说明: 以上结论采用健康检查程序默认配置时测试得到,测试过程中 DPVS 服务无数据面流量。 diff --git a/tools/healthcheck/test/dpvs-agent-api.sh b/tools/healthcheck/test/dpvs-agent-api.sh new file mode 100755 index 000000000..a5013c206 --- /dev/null +++ b/tools/healthcheck/test/dpvs-agent-api.sh @@ -0,0 +1,31 @@ +# Copyright 2023 IQiYi Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import requests +import json + +def UpdateService(): + payload="{\"Items\":[{\"inhibited\":false,\"ip\":\"192.168.88.68\",\"port\":80,\"weight\":100}]}" + url = "http://127.0.0.1:6600/v2/vs/192.168.88.1-80-TCP/rs?healthcheck=true" + headers = {'content-type': 'application/json'} + r = requests.put(url, headers=headers, data=payload) + print(r, r.json()) + + url = "http://127.0.0.1:6600/v2/vs/192.168.88.1-80-TCP" + headers = {'content-type': 'application/json'} + r = requests.get(url, headers=headers, data=payload) + print(r, r.json()) + +if __name__ == '__main__': + UpdateService() diff --git a/tools/healthcheck/test/stress-test.sh b/tools/healthcheck/test/stress-test.sh new file mode 100755 index 000000000..6ea848f85 --- /dev/null +++ b/tools/healthcheck/test/stress-test.sh @@ -0,0 +1,67 @@ +#!/bin/sh +# Copyright 2023 IQiYi Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +## Step 1. +echo -e "Cleaning existing services ..." +ipvsadm -C +sleep 5 + +now=$(date +%F.%T) +echo -e "[$now] Start" + +## Step 2. +echo -e "Adding test services ..." +rsid=5000 +for i in $(seq 0 32) +do + for j in $(seq 1 255) + do + vip="192.168.${i}.${j}" + flag="-t" + #udp=$((j%2)) + #[ "$udp" -eq 1 ] && flag="-u" + #echo $vip $flag + ipvsadm -A $flag $vip:80 + for k in $(seq 5) + do + seg3=$((rsid/255)) + seg4=$((rsid%255)) + rsid=$((rsid+1)) + rip="192.168.${seg3}.${seg4}" + #echo "-> $rip" + ipvsadm -a $flag $vip:80 -r $rip:8080 -b -w 100 + done + #dpip addr add $vip/32 dev dpdk0 + done +done + +## Step 3. +echo "" +echo "****************************************" +echo -e "Start healthcheck program on your own." +echo "****************************************" +echo "" + +## Step 4. +echo -e "Do Checking ..." +while true +do + now=$(date +%F.%T) + total=$(ipvsadm -ln| grep FullNat -c) + down=$(ipvsadm -ln| grep inhibited -c) + echo "[$now] total: $total, inhibited: $down" + sleep 1 +done From 24d681e9b5144f4282cd2c90381a9d11a80e1709 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 3 Jul 2023 15:58:59 +0800 Subject: [PATCH 040/105] ipvs: fix synproxy window scale setting problem Signed-off-by: ywc689 --- conf/dpvs.bond.conf.sample | 2 +- conf/dpvs.conf.items | 4 +-- conf/dpvs.conf.sample | 2 +- conf/dpvs.conf.single-bond.sample | 2 +- conf/dpvs.conf.single-nic.sample | 2 +- src/ipvs/ip_vs_synproxy.c | 49 +++++++++++++++++++------------ 6 files changed, 37 insertions(+), 24 deletions(-) diff --git a/conf/dpvs.bond.conf.sample b/conf/dpvs.bond.conf.sample index 42c5db371..d8cc1e5e8 100644 --- a/conf/dpvs.bond.conf.sample +++ b/conf/dpvs.bond.conf.sample @@ -358,7 +358,7 @@ ipvs_defs { mss 1452 ttl 63 sack - ! wscale + ! wscale 0 ! timestamp } ! defer_rs_syn diff --git a/conf/dpvs.conf.items b/conf/dpvs.conf.items index 15cbb180a..5b5f9b35e 100644 --- a/conf/dpvs.conf.items +++ b/conf/dpvs.conf.items @@ -258,10 +258,10 @@ ipvs_defs { mss 1452 <1452, 1-65535> ttl 63 <63, 1-255> sack - ! wscale + ! wscale <0, 0-14> ! timestamp } - close_client_window + !close_client_window !defer_rs_syn rs_syn_max_retry 3 <3, 1-99> ack_storm_thresh 10 <10, 1-999> diff --git a/conf/dpvs.conf.sample b/conf/dpvs.conf.sample index 2b817f1aa..14b0846d5 100644 --- a/conf/dpvs.conf.sample +++ b/conf/dpvs.conf.sample @@ -322,7 +322,7 @@ ipvs_defs { mss 1452 ttl 63 sack - ! wscale + ! wscale 0 ! timestamp } close_client_window diff --git a/conf/dpvs.conf.single-bond.sample b/conf/dpvs.conf.single-bond.sample index caa58050d..3fdfbfd33 100644 --- a/conf/dpvs.conf.single-bond.sample +++ b/conf/dpvs.conf.single-bond.sample @@ -263,7 +263,7 @@ ipvs_defs { mss 1452 ttl 63 sack - ! wscale + ! wscale 0 ! timestamp } close_client_window diff --git a/conf/dpvs.conf.single-nic.sample b/conf/dpvs.conf.single-nic.sample index 784ec5e3e..3717ed07b 100644 --- a/conf/dpvs.conf.single-nic.sample +++ b/conf/dpvs.conf.single-nic.sample @@ -237,7 +237,7 @@ ipvs_defs { mss 1452 ttl 63 sack - ! wscale + ! wscale 0 ! timestamp } close_client_window diff --git a/src/ipvs/ip_vs_synproxy.c b/src/ipvs/ip_vs_synproxy.c index fefb2d41a..60c43f325 100644 --- a/src/ipvs/ip_vs_synproxy.c +++ b/src/ipvs/ip_vs_synproxy.c @@ -39,7 +39,7 @@ #define DP_VS_SYNPROXY_SACK_DEFAULT 1 #define DP_VS_SYNPROXY_WSCALE_DEFAULT 0 #define DP_VS_SYNPROXY_TIMESTAMP_DEFAULT 0 -#define DP_VS_SYNPROXY_CLWND_DEFAULT 1 +#define DP_VS_SYNPROXY_CLWND_DEFAULT 0 #define DP_VS_SYNPROXY_DEFER_DEFAULT 0 #define DP_VS_SYNPROXY_DUP_ACK_DEFAULT 10 #define DP_VS_SYNPROXY_MAX_ACK_SAVED_DEFAULT 3 @@ -55,7 +55,7 @@ int dp_vs_synproxy_ctrl_sack = DP_VS_SYNPROXY_SACK_DEFAULT; int dp_vs_synproxy_ctrl_wscale = DP_VS_SYNPROXY_WSCALE_DEFAULT; int dp_vs_synproxy_ctrl_timestamp = DP_VS_SYNPROXY_TIMESTAMP_DEFAULT; int dp_vs_synproxy_ctrl_synack_ttl = DP_VS_SYNPROXY_TTL_DEFAULT; -int dp_synproxy_ctrl_clwnd = DP_VS_SYNPROXY_CLWND_DEFAULT; +int dp_vs_synproxy_ctrl_clwnd = DP_VS_SYNPROXY_CLWND_DEFAULT; int dp_vs_synproxy_ctrl_defer = DP_VS_SYNPROXY_DEFER_DEFAULT; int dp_vs_synproxy_ctrl_conn_reuse = DP_VS_SYNPROXY_CONN_REUSE_DEFAULT; int dp_vs_synproxy_ctrl_conn_reuse_cl = DP_VS_SYNPROXY_CONN_REUSE_CL_DEFAULT; @@ -613,7 +613,7 @@ static void syn_proxy_reuse_mbuf(int af, struct rte_mbuf *mbuf, th->dest = th->source; th->source = tmpport; /* set window size to zero if enabled */ - if (dp_synproxy_ctrl_clwnd && !dp_vs_synproxy_ctrl_defer) + if (dp_vs_synproxy_ctrl_clwnd && !dp_vs_synproxy_ctrl_defer) th->window = 0; /* set seq(cookie) and ack_seq */ th->ack_seq = htonl(ntohl(th->seq) + 1); @@ -1459,7 +1459,7 @@ int dp_vs_synproxy_synack_rcv(struct rte_mbuf *mbuf, struct dp_vs_conn *cp, * The probe will be forward to RS and RS will respond a window update. * So DPVS has no need to send a window update. */ - if (dp_synproxy_ctrl_clwnd && !dp_vs_synproxy_ctrl_defer && cp->ack_num <= 1) + if (dp_vs_synproxy_ctrl_clwnd && !dp_vs_synproxy_ctrl_defer && cp->ack_num <= 1) syn_proxy_send_window_update(tuplehash_out(cp).af, mbuf, cp, pp, th); list_for_each_entry_safe(tmbuf, tmbuf2, &cp->ack_mbuf, list) { @@ -1793,8 +1793,21 @@ static void synack_sack_handler(vector_t tokens) static void synack_wscale_handler(vector_t tokens) { - RTE_LOG(INFO, IPVS, "synproxy_synack_options_wscale ON\n"); - dp_vs_synproxy_ctrl_wscale = 1; + char *str = set_value(tokens); + int wscale; + + assert(str); + wscale = atoi(str); + if (wscale >= 0 && wscale <= DP_VS_SYNPROXY_WSCALE_MAX) { + RTE_LOG(INFO, IPVS, "synproxy_synack_options_wscale = %d\n", wscale); + dp_vs_synproxy_ctrl_wscale = wscale; + } else { + RTE_LOG(WARNING, IPVS, "invalid synproxy_synack_options_wscale %s, using default %d\n", + str, DP_VS_SYNPROXY_WSCALE_DEFAULT); + dp_vs_synproxy_ctrl_init_mss = DP_VS_SYNPROXY_WSCALE_DEFAULT; + } + + FREE_PTR(str); } static void synack_timestamp_handler(vector_t tokens) @@ -1806,7 +1819,7 @@ static void synack_timestamp_handler(vector_t tokens) static void close_client_window_handler(vector_t tokens) { RTE_LOG(INFO, IPVS, "close_client_window ON\n"); - dp_synproxy_ctrl_clwnd = 1; + dp_vs_synproxy_ctrl_clwnd = 1; } static void defer_rs_syn_handler(vector_t tokens) @@ -1914,18 +1927,18 @@ void synproxy_keyword_value_init(void) } /* KW_TYPE_NORMAL keyword */ dp_vs_synproxy_ctrl_init_mss = DP_VS_SYNPROXY_INIT_MSS_DEFAULT; - dp_vs_synproxy_ctrl_sack = 0; - dp_vs_synproxy_ctrl_wscale = 0; - dp_vs_synproxy_ctrl_timestamp = 0; + dp_vs_synproxy_ctrl_sack = DP_VS_SYNPROXY_SACK_DEFAULT; + dp_vs_synproxy_ctrl_wscale = DP_VS_SYNPROXY_WSCALE_DEFAULT; + dp_vs_synproxy_ctrl_timestamp = DP_VS_SYNPROXY_TIMESTAMP_DEFAULT; dp_vs_synproxy_ctrl_synack_ttl = DP_VS_SYNPROXY_TTL_DEFAULT; - dp_synproxy_ctrl_clwnd = 0; - dp_vs_synproxy_ctrl_defer = 0; - dp_vs_synproxy_ctrl_conn_reuse = 0; - dp_vs_synproxy_ctrl_conn_reuse_cl = 0; - dp_vs_synproxy_ctrl_conn_reuse_tw = 0; - dp_vs_synproxy_ctrl_conn_reuse_fw = 0; - dp_vs_synproxy_ctrl_conn_reuse_cw = 0; - dp_vs_synproxy_ctrl_conn_reuse_la = 0; + dp_vs_synproxy_ctrl_clwnd = DP_VS_SYNPROXY_CLWND_DEFAULT; + dp_vs_synproxy_ctrl_defer = DP_VS_SYNPROXY_DEFER_DEFAULT; + dp_vs_synproxy_ctrl_conn_reuse = DP_VS_SYNPROXY_CONN_REUSE_DEFAULT; + dp_vs_synproxy_ctrl_conn_reuse_cl = DP_VS_SYNPROXY_CONN_REUSE_CL_DEFAULT; + dp_vs_synproxy_ctrl_conn_reuse_tw = DP_VS_SYNPROXY_CONN_REUSE_TW_DEFAULT; + dp_vs_synproxy_ctrl_conn_reuse_fw = DP_VS_SYNPROXY_CONN_REUSE_FW_DEFAULT; + dp_vs_synproxy_ctrl_conn_reuse_cw = DP_VS_SYNPROXY_CONN_REUSE_CW_DEFAULT; + dp_vs_synproxy_ctrl_conn_reuse_la = DP_VS_SYNPROXY_CONN_REUSE_LA_DEFAULT; dp_vs_synproxy_ctrl_dup_ack_thresh = DP_VS_SYNPROXY_DUP_ACK_DEFAULT; dp_vs_synproxy_ctrl_max_ack_saved = DP_VS_SYNPROXY_MAX_ACK_SAVED_DEFAULT; dp_vs_synproxy_ctrl_syn_retry = DP_VS_SYNPROXY_SYN_RETRY_DEFAULT; From 9bcd301c344232e43fa90e2df11a3d350528dddd Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 3 Jul 2023 19:12:23 +0800 Subject: [PATCH 041/105] ipvs: adjust outbound window size for synproxy Syn-proxy uses the same wscale option value in inbound direction, i.e., client->vs and vs->rs, but does not do so in outbound direction. When the wscale option value of rs->vs and vs->client are different, rs's window size shall not be advertised to client correctly. It causes serious time delay in bulk data transmission if the wscales differ too much. So window adjustment is applied in outbound direction for synproxy. The table below shows the test results in our layer2 network environments. The backend is a fileserver, and the file upload(.u) or download(.d) time are tested against three TCP windows related configs `synproxy`, `close_client_window` and `wscale` . | synproxy | close_client_window | wscale | 10MB file .u | 100MB file .u | 500MB file .u | 10MB file .d | 100MB file .d | 500MB file .d | | -------- | ------------------- | ------ | ------------ | ------------- | ------------- | ------------ | ------------- | ------------- | | off | x | x | 0.055s | 0.414s | 1.764s | 0.023s | 0.116s | 0.464s | | on | off | 0 | 0.052s | 0.405s | 1.820s | 0.036s | 0.260s | 1.178s | | on | off | 1 | 0.060s | 0.384s | 1.724s | 0.022s | 0.118s | 0.465s | | on | off | 3 | 0.051s | 0.377s | 1.913s | 0.023s | 0.116s | 0.465s | | on | off | 6 | 0.048s | 0.420s | 1.871s | 0.025s | 0.116s | 0.467s | | on | off | 9 | 0.052s | 0.392s | 1.823s | 0.024s | 0.116s | 0.463s | | on | on | 0 | 0.054s | 0.387s | 1.920s | 0.040s | 0.254s | 1.216s | | on | on | 1 | 0.052s | 0.387s | 1.742s | 0.026s | 0.116s | 0.463s | | on | on | 3 | 0.050s | 0.377s | 1.791s | 0.023s | 0.115s | 0.463s | | on | on | 6 | 0.051s | 0.394s | 1.678s | 0.023s | 0.115s | 0.474s | | on | on | 9 | 0.057s | 0.373s | 1.734s | 0.024s | 0.117s | 0.462s | Compared the test results without this patch shown in the table below: | synproxy | close_client_window | wscale | 10MB file .u | 100MB file .u | 500MB file .u | 10MB file .d | 100MB file .d | 500MB file .d | | -------- | ------------------- | ------ | ------------ | ------------- | ------------- | ------------ | ------------- | ------------- | | off | x | x | 0.049s | 0.398s | 1.767s | 0.026s | 0.118s | 0.466s | | on | off | 0 | 0.053s | 0.403s | 1.965s | 0.039s | 0.239s | 1.216s | | on | off | 1 | >10min | x | x | 0.024s | 0.116s | 0.465s | | on | on | 0 | 0.057s | 0.474s | 1.900s | 0.039s | 0.259s | 1.227s | | on | on | 1 | >10min | x | x | 0.024s | 0.116s | 0.469s | It shows the slow uploading problem is solved by the patch, and other TCP window related configs have minor effects on the transmission time. Signed-off-by: ywc689 --- include/ipvs/conn.h | 4 +++- src/ipvs/ip_vs_proto_tcp.c | 12 +++++++++++ src/ipvs/ip_vs_synproxy.c | 44 ++++++++++++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/include/ipvs/conn.h b/include/ipvs/conn.h index fa0bdeb8d..4624185cd 100644 --- a/include/ipvs/conn.h +++ b/include/ipvs/conn.h @@ -139,7 +139,9 @@ struct dp_vs_conn { /* synproxy related members */ struct dp_vs_seq syn_proxy_seq; /* seq used in synproxy */ struct list_head ack_mbuf; /* ack mbuf saved in step2 */ - uint32_t ack_num; /* ack mbuf number stored */ + uint16_t ack_num; /* ack mbuf number stored */ + uint8_t wscale_vs; /* outbound wscale factor to client */ + uint8_t wscale_rs; /* outbound wscale factor from rs */ struct rte_mbuf *syn_mbuf; /* saved rs syn packet for retransmition */ rte_atomic32_t syn_retry_max; /* syn retransmition max packets */ diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 4d1d71f67..7578bae4d 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -429,6 +429,16 @@ static void tcp_out_save_seq(struct rte_mbuf *mbuf, conn->rs_end_ack = th->ack_seq; } +static void tcp_out_adjust_window(struct dp_vs_conn *conn, struct tcphdr *th) +{ + uint32_t wnd_client; + + wnd_client = ntohs(th->window) * (1 << conn->wscale_rs) / (1 << conn->wscale_vs); + if (unlikely(wnd_client > 0xffff)) + wnd_client = 0xffff; + th->window = htons(wnd_client); +} + static void tcp_out_adjust_mss(int af, struct tcphdr *tcph) { unsigned char *ptr; @@ -763,6 +773,8 @@ static int tcp_fnat_out_handler(struct dp_vs_proto *proto, th->source = conn->vport; th->dest = conn->cport; + tcp_out_adjust_window(conn, th); + if (th->syn && th->ack) tcp_out_adjust_mss(af, th); diff --git a/src/ipvs/ip_vs_synproxy.c b/src/ipvs/ip_vs_synproxy.c index 60c43f325..6dbdcb0c2 100644 --- a/src/ipvs/ip_vs_synproxy.c +++ b/src/ipvs/ip_vs_synproxy.c @@ -414,12 +414,11 @@ syn_proxy_v4_cookie_check(struct rte_mbuf *mbuf, uint32_t cookie, th->source, th->dest, seq, rte_atomic32_read(&g_minute_count), DP_VS_SYNPROXY_COUNTER_TRIES); + memset(opt, 0, sizeof(struct dp_vs_synproxy_opt)); if ((uint32_t) -1 == res) /* count is invalid, g_minute_count' >> g_minute_count */ return 0; mssind = (res & DP_VS_SYNPROXY_MSS_MASK) >> DP_VS_SYNPROXY_MSS_BITS; - - memset(opt, 0, sizeof(struct dp_vs_synproxy_opt)); if ((mssind < NUM_MSS) && ((res & DP_VS_SYNPROXY_OTHER_MASK) == 0)) { opt->mss_clamp = msstab[mssind] + 1; opt->sack_ok = (res & DP_VS_SYNPROXY_SACKOK_MASK) >> DP_VS_SYNPROXY_SACKOK_BIT; @@ -451,12 +450,11 @@ syn_proxy_v6_cookie_check(struct rte_mbuf *mbuf, uint32_t cookie, th->source, th->dest, seq, rte_atomic32_read(&g_minute_count), DP_VS_SYNPROXY_COUNTER_TRIES); + memset(opt, 0, sizeof(struct dp_vs_synproxy_opt)); if ((uint32_t) -1 == res) /* count is invalid, g_minute_count' >> g_minute_count */ return 0; mssind = (res & DP_VS_SYNPROXY_MSS_MASK) >> DP_VS_SYNPROXY_MSS_BITS; - - memset(opt, 0, sizeof(struct dp_vs_synproxy_opt)); if ((mssind < NUM_MSS) && ((res & DP_VS_SYNPROXY_OTHER_MASK) == 0)) { opt->mss_clamp = msstab[mssind] + 1; opt->sack_ok = (res & DP_VS_SYNPROXY_SACKOK_MASK) >> DP_VS_SYNPROXY_SACKOK_BIT; @@ -479,6 +477,40 @@ syn_proxy_v6_cookie_check(struct rte_mbuf *mbuf, uint32_t cookie, * Synproxy implementation */ +static unsigned char syn_proxy_parse_wscale_opt(struct rte_mbuf *mbuf, struct tcphdr *th) +{ + int length; + unsigned char opcode, opsize; + unsigned char *ptr; + + length = (th->doff * 4) - sizeof(struct tcphdr); + ptr = (unsigned char *)(th + 1); + while (length > 0) { + opcode = *ptr++; + switch (opcode) { + case TCPOPT_EOL: + return 0; + case TCPOPT_NOP: + length--; + continue; + default: + opsize = *ptr++; + if (opsize < 2) /* silly options */ + return 0; + if (opsize > length) /* partial options */ + return 0; + if (opcode == TCPOPT_WINDOW) { + if (*ptr > DP_VS_SYNPROXY_WSCALE_MAX) /* invalid wscale opt */ + return 0; + return *ptr; + } + ptr += opsize -2; + length -= opsize; + } + } + return 0; /* should never reach here */ +} + /* Replace tcp options in tcp header, called by syn_proxy_reuse_mbuf() */ static void syn_proxy_parse_set_opts(struct rte_mbuf *mbuf, struct tcphdr *th, struct dp_vs_synproxy_opt *opt) @@ -1191,6 +1223,9 @@ int dp_vs_synproxy_ack_rcv(int af, struct rte_mbuf *mbuf, return 0; } + if (opt.wscale_ok) + (*cpp)->wscale_vs = dp_vs_synproxy_ctrl_wscale; + /* Do nothing but print a error msg when fail, because session will be * correctly freed in dp_vs_conn_expire */ if (EDPVS_OK != (res = syn_proxy_send_rs_syn(af, th, *cpp, mbuf, pp, &opt))) { @@ -1409,6 +1444,7 @@ int dp_vs_synproxy_synack_rcv(struct rte_mbuf *mbuf, struct dp_vs_conn *cp, if ((th->syn) && (th->ack) && (!th->rst) && (cp->flags & DPVS_CONN_F_SYNPROXY) && (cp->state == DPVS_TCP_S_SYN_SENT)) { + cp->wscale_rs = syn_proxy_parse_wscale_opt(mbuf, th); cp->syn_proxy_seq.delta = ntohl(cp->syn_proxy_seq.isn) - ntohl(th->seq); cp->state = DPVS_TCP_S_ESTABLISHED; dp_vs_conn_set_timeout(cp, pp); From 920552d49f96718d179c9c556b952ce9cf74fd36 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 10 Jul 2023 14:18:11 +0800 Subject: [PATCH 042/105] Add dpvs-agent source code --- tools/dpvs-agent/.gitignore | 2 + tools/dpvs-agent/Makefile | 32 + tools/dpvs-agent/README.md | 4 + .../cmd/device/delete_device_name_addr.go | 45 + .../cmd/device/delete_device_name_netlink.go | 49 + .../device/delete_device_name_netlink_addr.go | 68 + .../cmd/device/delete_device_name_route.go | 59 + .../cmd/device/delete_device_name_vlan.go | 46 + .../cmd/device/get_device_name_nic.go | 78 + tools/dpvs-agent/cmd/device/ioctl.go | 23 + .../cmd/device/put_device_name_addr.go | 57 + .../cmd/device/put_device_name_netlink.go | 46 + .../device/put_device_name_netlink_addr.go | 72 + .../cmd/device/put_device_name_nic.go | 63 + .../cmd/device/put_device_name_route.go | 66 + .../cmd/device/put_device_name_vlan.go | 71 + .../device/todo_delete_device_name_linux.go | 25 + .../todo_delete_device_name_linux_addr.go | 117 + .../dpvs-agent/cmd/device/todo_get_device.go | 1 + .../cmd/device/todo_get_device_name_addr.go | 1 + .../cmd/device/todo_get_device_name_linux.go | 1 + .../device/todo_get_device_name_linux_addr.go | 1 + .../cmd/device/todo_get_device_name_route.go | 1 + .../cmd/device/todo_get_device_name_vlan.go | 1 + .../cmd/device/todo_put_device_name_linux.go | 3 + .../device/todo_put_device_name_linux_addr.go | 132 + .../dpvs-agent/cmd/dpvs-agent-server/Makefile | 26 + .../cmd/dpvs-agent-server/api_init.go | 181 + .../dpvs-agent/cmd/dpvs-agent-server/main.go | 55 + .../dpvs-agent/cmd/ipvs/delete_vs_vip_port.go | 45 + .../cmd/ipvs/delete_vs_vip_port_allow.go | 56 + .../cmd/ipvs/delete_vs_vip_port_deny.go | 56 + .../cmd/ipvs/delete_vs_vip_port_laddr.go | 52 + .../cmd/ipvs/delete_vs_vip_port_rs.go | 56 + tools/dpvs-agent/cmd/ipvs/get_vs.go | 71 + tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go | 79 + .../cmd/ipvs/get_vs_vip_port_laddr.go | 50 + .../cmd/ipvs/post_vs_vip_port_rs.go | 59 + tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go | 96 + .../cmd/ipvs/put_vs_vip_port_allow.go | 58 + .../cmd/ipvs/put_vs_vip_port_deny.go | 58 + .../cmd/ipvs/put_vs_vip_port_laddr.go | 55 + .../dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go | 74 + .../cmd/ipvs/todo_get_vs_vip_port_rs.go | 1 + tools/dpvs-agent/dpvs-agent-api.yaml | 1373 +++++ tools/dpvs-agent/go.mod | 40 + tools/dpvs-agent/go.sum | 232 + tools/dpvs-agent/models/acl_addr_list.go | 116 + tools/dpvs-agent/models/addr_range.go | 53 + tools/dpvs-agent/models/cert_auth_spec.go | 50 + tools/dpvs-agent/models/dest_check_spec.go | 84 + tools/dpvs-agent/models/error.go | 27 + tools/dpvs-agent/models/inet_addr_spec.go | 56 + .../models/local_address_expand_list.go | 116 + .../models/local_address_spec_expand.go | 62 + .../models/local_address_spec_tiny.go | 53 + .../models/local_address_tiny_list.go | 116 + tools/dpvs-agent/models/match_spec.go | 156 + tools/dpvs-agent/models/nic_device_detail.go | 232 + .../models/nic_device_queue_data.go | 27 + tools/dpvs-agent/models/nic_device_spec.go | 150 + .../dpvs-agent/models/nic_device_spec_list.go | 116 + tools/dpvs-agent/models/nic_device_stats.go | 342 ++ .../models/real_server_expand_list.go | 116 + .../models/real_server_spec_expand.go | 150 + .../models/real_server_spec_tiny.go | 129 + .../models/real_server_tiny_list.go | 116 + tools/dpvs-agent/models/route_spec.go | 71 + tools/dpvs-agent/models/server_stats.go | 77 + tools/dpvs-agent/models/status.go | 114 + .../dpvs-agent/models/virtual_server_list.go | 116 + .../models/virtual_server_spec_expand.go | 438 ++ .../models/virtual_server_spec_tiny.go | 183 + tools/dpvs-agent/models/vlan_spec.go | 56 + tools/dpvs-agent/pkg/ipc/pool/conn.go | 316 ++ tools/dpvs-agent/pkg/ipc/pool/pool.go | 523 ++ tools/dpvs-agent/pkg/ipc/pool/util.go | 12 + tools/dpvs-agent/pkg/ipc/proto/reader.go | 335 ++ tools/dpvs-agent/pkg/ipc/proto/writer.go | 167 + tools/dpvs-agent/pkg/ipc/types/certificate.go | 369 ++ tools/dpvs-agent/pkg/ipc/types/const.go | 334 ++ tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go | 56 + tools/dpvs-agent/pkg/ipc/types/dpvsstats.go | 114 + tools/dpvs-agent/pkg/ipc/types/getmodel.go | 169 + tools/dpvs-agent/pkg/ipc/types/inetaddr.go | 571 +++ tools/dpvs-agent/pkg/ipc/types/iprange.go | 43 + tools/dpvs-agent/pkg/ipc/types/kni.go | 314 ++ tools/dpvs-agent/pkg/ipc/types/laddr.go | 492 ++ tools/dpvs-agent/pkg/ipc/types/method.go | 1 + tools/dpvs-agent/pkg/ipc/types/netif.go | 728 +++ tools/dpvs-agent/pkg/ipc/types/realserver.go | 633 +++ tools/dpvs-agent/pkg/ipc/types/route.go | 470 ++ tools/dpvs-agent/pkg/ipc/types/sockmsg.go | 132 + tools/dpvs-agent/pkg/ipc/types/utility.go | 11 + .../dpvs-agent/pkg/ipc/types/virtualserver.go | 693 +++ tools/dpvs-agent/pkg/ipc/types/vlan.go | 312 ++ .../restapi/configure_dpvs_agent.go | 172 + tools/dpvs-agent/restapi/doc.go | 19 + tools/dpvs-agent/restapi/embedded_spec.go | 4449 +++++++++++++++++ .../device/delete_device_name_addr.go | 56 + .../delete_device_name_addr_parameters.go | 145 + .../delete_device_name_addr_responses.go | 98 + .../delete_device_name_addr_urlbuilder.go | 115 + .../device/delete_device_name_netlink.go | 56 + .../device/delete_device_name_netlink_addr.go | 56 + ...ete_device_name_netlink_addr_parameters.go | 101 + ...lete_device_name_netlink_addr_responses.go | 98 + ...ete_device_name_netlink_addr_urlbuilder.go | 99 + .../delete_device_name_netlink_parameters.go | 71 + .../delete_device_name_netlink_responses.go | 98 + .../delete_device_name_netlink_urlbuilder.go | 99 + .../device/delete_device_name_route.go | 56 + .../delete_device_name_route_parameters.go | 101 + .../delete_device_name_route_responses.go | 98 + .../delete_device_name_route_urlbuilder.go | 99 + .../device/delete_device_name_vlan.go | 56 + .../delete_device_name_vlan_parameters.go | 71 + .../delete_device_name_vlan_responses.go | 98 + .../delete_device_name_vlan_urlbuilder.go | 99 + .../restapi/operations/device/get_device.go | 56 + .../operations/device/get_device_name_addr.go | 56 + .../device/get_device_name_addr_parameters.go | 153 + .../device/get_device_name_addr_responses.go | 98 + .../device/get_device_name_addr_urlbuilder.go | 124 + .../device/get_device_name_netlink.go | 56 + .../device/get_device_name_netlink_addr.go | 56 + ...get_device_name_netlink_addr_parameters.go | 116 + .../get_device_name_netlink_addr_responses.go | 98 + ...get_device_name_netlink_addr_urlbuilder.go | 115 + .../get_device_name_netlink_parameters.go | 116 + .../get_device_name_netlink_responses.go | 98 + .../get_device_name_netlink_urlbuilder.go | 115 + .../operations/device/get_device_name_nic.go | 56 + .../device/get_device_name_nic_parameters.go | 153 + .../device/get_device_name_nic_responses.go | 102 + .../device/get_device_name_nic_urlbuilder.go | 124 + .../device/get_device_name_route.go | 56 + .../get_device_name_route_parameters.go | 116 + .../device/get_device_name_route_responses.go | 98 + .../get_device_name_route_urlbuilder.go | 115 + .../operations/device/get_device_name_vlan.go | 56 + .../device/get_device_name_vlan_parameters.go | 116 + .../device/get_device_name_vlan_responses.go | 98 + .../device/get_device_name_vlan_urlbuilder.go | 115 + .../device/get_device_parameters.go | 92 + .../operations/device/get_device_responses.go | 55 + .../device/get_device_urlbuilder.go | 105 + .../operations/device/put_device_name_addr.go | 56 + .../device/put_device_name_addr_parameters.go | 145 + .../device/put_device_name_addr_responses.go | 141 + .../device/put_device_name_addr_urlbuilder.go | 115 + .../device/put_device_name_netlink.go | 56 + .../device/put_device_name_netlink_addr.go | 56 + ...put_device_name_netlink_addr_parameters.go | 101 + .../put_device_name_netlink_addr_responses.go | 98 + ...put_device_name_netlink_addr_urlbuilder.go | 99 + .../put_device_name_netlink_parameters.go | 71 + .../put_device_name_netlink_responses.go | 98 + .../put_device_name_netlink_urlbuilder.go | 99 + .../operations/device/put_device_name_nic.go | 56 + .../device/put_device_name_nic_parameters.go | 218 + .../device/put_device_name_nic_responses.go | 98 + .../device/put_device_name_nic_urlbuilder.go | 131 + .../device/put_device_name_route.go | 56 + .../put_device_name_route_parameters.go | 101 + .../device/put_device_name_route_responses.go | 141 + .../put_device_name_route_urlbuilder.go | 99 + .../operations/device/put_device_name_vlan.go | 56 + .../device/put_device_name_vlan_parameters.go | 101 + .../device/put_device_name_vlan_responses.go | 98 + .../device/put_device_name_vlan_urlbuilder.go | 99 + .../restapi/operations/dpvs_agent_api.go | 736 +++ .../virtualserver/delete_vs_vip_port.go | 56 + .../virtualserver/delete_vs_vip_port_allow.go | 56 + .../delete_vs_vip_port_allow_parameters.go | 101 + .../delete_vs_vip_port_allow_responses.go | 211 + .../delete_vs_vip_port_allow_urlbuilder.go | 99 + .../virtualserver/delete_vs_vip_port_deny.go | 56 + .../delete_vs_vip_port_deny_parameters.go | 101 + .../delete_vs_vip_port_deny_responses.go | 211 + .../delete_vs_vip_port_deny_urlbuilder.go | 99 + .../virtualserver/delete_vs_vip_port_laddr.go | 56 + .../delete_vs_vip_port_laddr_parameters.go | 101 + .../delete_vs_vip_port_laddr_responses.go | 186 + .../delete_vs_vip_port_laddr_urlbuilder.go | 99 + .../delete_vs_vip_port_parameters.go | 71 + .../delete_vs_vip_port_responses.go | 143 + .../virtualserver/delete_vs_vip_port_rs.go | 56 + .../delete_vs_vip_port_rs_parameters.go | 101 + .../delete_vs_vip_port_rs_responses.go | 211 + .../delete_vs_vip_port_rs_urlbuilder.go | 99 + .../delete_vs_vip_port_urlbuilder.go | 99 + .../operations/virtualserver/get_vs.go | 56 + .../virtualserver/get_vs_parameters.go | 92 + .../virtualserver/get_vs_responses.go | 59 + .../virtualserver/get_vs_urlbuilder.go | 105 + .../virtualserver/get_vs_vip_port.go | 56 + .../virtualserver/get_vs_vip_port_allow.go | 56 + .../get_vs_vip_port_allow_parameters.go | 71 + .../get_vs_vip_port_allow_responses.go | 98 + .../get_vs_vip_port_allow_urlbuilder.go | 99 + .../virtualserver/get_vs_vip_port_deny.go | 56 + .../get_vs_vip_port_deny_parameters.go | 71 + .../get_vs_vip_port_deny_responses.go | 98 + .../get_vs_vip_port_deny_urlbuilder.go | 99 + .../virtualserver/get_vs_vip_port_laddr.go | 56 + .../get_vs_vip_port_laddr_parameters.go | 116 + .../get_vs_vip_port_laddr_responses.go | 102 + .../get_vs_vip_port_laddr_urlbuilder.go | 115 + .../get_vs_vip_port_parameters.go | 116 + .../get_vs_vip_port_responses.go | 102 + .../virtualserver/get_vs_vip_port_rs.go | 56 + .../get_vs_vip_port_rs_parameters.go | 116 + .../get_vs_vip_port_rs_responses.go | 98 + .../get_vs_vip_port_rs_urlbuilder.go | 115 + .../get_vs_vip_port_urlbuilder.go | 115 + .../virtualserver/post_vs_vip_port_allow.go | 56 + .../post_vs_vip_port_allow_parameters.go | 101 + .../post_vs_vip_port_allow_responses.go | 229 + .../post_vs_vip_port_allow_urlbuilder.go | 99 + .../virtualserver/post_vs_vip_port_deny.go | 56 + .../post_vs_vip_port_deny_parameters.go | 101 + .../post_vs_vip_port_deny_responses.go | 229 + .../post_vs_vip_port_deny_urlbuilder.go | 99 + .../virtualserver/post_vs_vip_port_rs.go | 56 + .../post_vs_vip_port_rs_parameters.go | 101 + .../post_vs_vip_port_rs_responses.go | 229 + .../post_vs_vip_port_rs_urlbuilder.go | 99 + .../virtualserver/put_vs_vip_port.go | 56 + .../virtualserver/put_vs_vip_port_allow.go | 56 + .../put_vs_vip_port_allow_parameters.go | 101 + .../put_vs_vip_port_allow_responses.go | 229 + .../put_vs_vip_port_allow_urlbuilder.go | 99 + .../virtualserver/put_vs_vip_port_deny.go | 56 + .../put_vs_vip_port_deny_parameters.go | 101 + .../put_vs_vip_port_deny_responses.go | 229 + .../put_vs_vip_port_deny_urlbuilder.go | 99 + .../virtualserver/put_vs_vip_port_laddr.go | 56 + .../put_vs_vip_port_laddr_parameters.go | 101 + .../put_vs_vip_port_laddr_responses.go | 229 + .../put_vs_vip_port_laddr_urlbuilder.go | 99 + .../put_vs_vip_port_parameters.go | 101 + .../put_vs_vip_port_responses.go | 229 + .../virtualserver/put_vs_vip_port_rs.go | 56 + .../put_vs_vip_port_rs_parameters.go | 145 + .../put_vs_vip_port_rs_responses.go | 229 + .../put_vs_vip_port_rs_urlbuilder.go | 115 + .../put_vs_vip_port_urlbuilder.go | 99 + tools/dpvs-agent/restapi/server.go | 507 ++ 249 files changed, 34985 insertions(+) create mode 100644 tools/dpvs-agent/.gitignore create mode 100644 tools/dpvs-agent/Makefile create mode 100644 tools/dpvs-agent/README.md create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_addr.go create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_netlink.go create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_route.go create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_vlan.go create mode 100644 tools/dpvs-agent/cmd/device/get_device_name_nic.go create mode 100644 tools/dpvs-agent/cmd/device/ioctl.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_addr.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_netlink.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_nic.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_route.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_vlan.go create mode 100644 tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go create mode 100644 tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_route.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go create mode 100644 tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go create mode 100644 tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go create mode 100644 tools/dpvs-agent/cmd/dpvs-agent-server/Makefile create mode 100644 tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go create mode 100644 tools/dpvs-agent/cmd/dpvs-agent-server/main.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/cmd/ipvs/get_vs.go create mode 100644 tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go create mode 100644 tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/dpvs-agent-api.yaml create mode 100644 tools/dpvs-agent/go.mod create mode 100644 tools/dpvs-agent/go.sum create mode 100644 tools/dpvs-agent/models/acl_addr_list.go create mode 100644 tools/dpvs-agent/models/addr_range.go create mode 100644 tools/dpvs-agent/models/cert_auth_spec.go create mode 100644 tools/dpvs-agent/models/dest_check_spec.go create mode 100644 tools/dpvs-agent/models/error.go create mode 100644 tools/dpvs-agent/models/inet_addr_spec.go create mode 100644 tools/dpvs-agent/models/local_address_expand_list.go create mode 100644 tools/dpvs-agent/models/local_address_spec_expand.go create mode 100644 tools/dpvs-agent/models/local_address_spec_tiny.go create mode 100644 tools/dpvs-agent/models/local_address_tiny_list.go create mode 100644 tools/dpvs-agent/models/match_spec.go create mode 100644 tools/dpvs-agent/models/nic_device_detail.go create mode 100644 tools/dpvs-agent/models/nic_device_queue_data.go create mode 100644 tools/dpvs-agent/models/nic_device_spec.go create mode 100644 tools/dpvs-agent/models/nic_device_spec_list.go create mode 100644 tools/dpvs-agent/models/nic_device_stats.go create mode 100644 tools/dpvs-agent/models/real_server_expand_list.go create mode 100644 tools/dpvs-agent/models/real_server_spec_expand.go create mode 100644 tools/dpvs-agent/models/real_server_spec_tiny.go create mode 100644 tools/dpvs-agent/models/real_server_tiny_list.go create mode 100644 tools/dpvs-agent/models/route_spec.go create mode 100644 tools/dpvs-agent/models/server_stats.go create mode 100644 tools/dpvs-agent/models/status.go create mode 100644 tools/dpvs-agent/models/virtual_server_list.go create mode 100644 tools/dpvs-agent/models/virtual_server_spec_expand.go create mode 100644 tools/dpvs-agent/models/virtual_server_spec_tiny.go create mode 100644 tools/dpvs-agent/models/vlan_spec.go create mode 100644 tools/dpvs-agent/pkg/ipc/pool/conn.go create mode 100644 tools/dpvs-agent/pkg/ipc/pool/pool.go create mode 100644 tools/dpvs-agent/pkg/ipc/pool/util.go create mode 100644 tools/dpvs-agent/pkg/ipc/proto/reader.go create mode 100644 tools/dpvs-agent/pkg/ipc/proto/writer.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/certificate.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/const.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/dpvsstats.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/getmodel.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/inetaddr.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/iprange.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/kni.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/laddr.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/method.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/netif.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/realserver.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/route.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/sockmsg.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/utility.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/virtualserver.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/vlan.go create mode 100644 tools/dpvs-agent/restapi/configure_dpvs_agent.go create mode 100644 tools/dpvs-agent/restapi/doc.go create mode 100644 tools/dpvs-agent/restapi/embedded_spec.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_route.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_route_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_route_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_route_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_nic.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_nic_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_nic_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_nic_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_route.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_route_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_route_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_route_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_vlan.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_nic.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_nic_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_nic_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_route.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_route_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_route_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_route_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_vlan.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/dpvs_agent_api.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/server.go diff --git a/tools/dpvs-agent/.gitignore b/tools/dpvs-agent/.gitignore new file mode 100644 index 000000000..496ec7999 --- /dev/null +++ b/tools/dpvs-agent/.gitignore @@ -0,0 +1,2 @@ +bin/ +cmd/dpvs-agent-server/dpvs-agent diff --git a/tools/dpvs-agent/Makefile b/tools/dpvs-agent/Makefile new file mode 100644 index 000000000..fb8e5ff18 --- /dev/null +++ b/tools/dpvs-agent/Makefile @@ -0,0 +1,32 @@ +MAKE = make +SUBDIRS = cmd/dpvs-agent-server +INSDIR = $(PWD)/bin +export INSDIR + +OPENAPISPEC = dpvs-agent-api.yaml + +all: + for i in $(SUBDIRS); do $(MAKE) -C $$i || exit 1; done + +clean: + for i in $(SUBDIRS); do $(MAKE) -C $$i clean || exit 1; done + +install:all + -mkdir -p $(INSDIR) + for i in $(SUBDIRS); do $(MAKE) -C $$i install || exit 1; done + +uninstall: + for i in $(SUBDIRS); do $(MAKE) -C $$i uninstall || exit 1; done + +openapi: $(OPENAPISPEC) +ifeq ($(shell swagger version),) + $(error "golang `swagger` command not found. You can install it with `go get github.com/go-swagger/go-swagger@v0.30.4`") +endif + swagger generate server -A dpvs-agent -f $< + git checkout cmd/dpvs-agent-server/main.go + +license: +ifeq ($(shell addlicense 2>&1|grep Usage),) + $(error "`addlicense` command not found. You can install it with `go install github.com/google/addlicense`") +endif + @addlicense -check -c "IQiYi Inc." -l apache -ignore dpvs/** . || /bin/true diff --git a/tools/dpvs-agent/README.md b/tools/dpvs-agent/README.md new file mode 100644 index 000000000..0c25a01d1 --- /dev/null +++ b/tools/dpvs-agent/README.md @@ -0,0 +1,4 @@ +#build +``` +swagger generate server -A dpvs-agent -f ./dpvs-agent-api.yaml +``` diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_addr.go b/tools/dpvs-agent/cmd/device/delete_device_name_addr.go new file mode 100644 index 000000000..68635af05 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_addr.go @@ -0,0 +1,45 @@ +package device + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delDeviceAddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelDeviceAddr(cp *pool.ConnPool, parentLogger hclog.Logger) *delDeviceAddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelDeviceAddr") + } + return &delDeviceAddr{connPool: cp, logger: logger} +} + +// dpip addr add 192.168.88.16/32 dev dpdk0.102 +func (h *delDeviceAddr) Handle(params apiDevice.DeleteDeviceNameAddrParams) middleware.Responder { + addr := types.NewInetAddrDetail() + addr.SetAddr(params.Spec.Addr) + addr.SetIfName(params.Name) + + result := addr.Del(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Delete addr from device success.", "Device Name", params.Name, "Addr", params.Spec.Addr) + return apiDevice.NewDeleteDeviceNameAddrOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Delete a not exist addr from device done.", "Device Name", params.Name, "Addr", params.Spec.Addr, "result", result.String()) + return apiDevice.NewDeleteDeviceNameAddrOK() + default: + h.logger.Error("Delete addr from device failed.", "Device Name", params.Name, "Addr", params.Spec.Addr, "result", result.String()) + } + + return apiDevice.NewDeleteDeviceNameAddrInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go b/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go new file mode 100644 index 000000000..d4fd6ba54 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go @@ -0,0 +1,49 @@ +package device + +import ( + "fmt" + + "github.com/vishvananda/netlink" + + "github.com/dpvs-agent/pkg/ipc/pool" + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +// ip link set xxx down +type setDeviceNetlinkDown struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewSetDeviceNetlinkDown(cp *pool.ConnPool, parentLogger hclog.Logger) *setDeviceNetlinkDown { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("SetDeviceNetlinkDown") + } + return &setDeviceNetlinkDown{connPool: cp, logger: logger} +} + +func (h *setDeviceNetlinkDown) Handle(params apiDevice.DeleteDeviceNameNetlinkParams) middleware.Responder { + cmd := fmt.Sprintf("ip link set %s down", params.Name) + dev, err := netlink.LinkByName(params.Name) + if err != nil { + h.logger.Error("Get iface failed.", "Name", params.Name, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkInternalServerError() + } + + if err := netlink.LinkSetDown(dev); err != nil { + h.logger.Error("Set iface down failed.", "cmd", cmd, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkInternalServerError() + } + + if err := netlink.LinkDel(dev); err != nil { + h.logger.Error("Delete iface failed.", "Name", params.Name, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkInternalServerError() + } + + h.logger.Info("Set down and remove iface success.", "cmd", cmd) + return apiDevice.NewDeleteDeviceNameNetlinkOK() +} diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go b/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go new file mode 100644 index 000000000..0ed8b943e --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go @@ -0,0 +1,68 @@ +package device + +import ( + "fmt" + "net" + "strings" + + "github.com/vishvananda/netlink" + + "github.com/dpvs-agent/pkg/ipc/pool" + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delDeviceNetlinkAddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelDeviceNetlinkAddr(cp *pool.ConnPool, parentLogger hclog.Logger) *delDeviceNetlinkAddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelDeviceNetlinkAddr") + } + return &delDeviceNetlinkAddr{connPool: cp, logger: logger} +} + +func (h *delDeviceNetlinkAddr) Handle(params apiDevice.DeleteDeviceNameNetlinkAddrParams) middleware.Responder { + var cidr string + if strings.Count(params.Spec.Addr, "/") == 0 { + ip := net.ParseIP(params.Spec.Addr) + if ip == nil { + return apiDevice.NewDeleteDeviceNameNetlinkAddrInternalServerError() + } + + if ip.To4() != nil { + cidr = params.Spec.Addr + "/32" + } else { + cidr = params.Spec.Addr + "/128" + } + } + + ip, ipnet, err := net.ParseCIDR(cidr) + if err != nil { + return apiDevice.NewDeleteDeviceNameNetlinkAddrInternalServerError() + } + + cmd := fmt.Sprintf("ip addr del %s dev %s", cidr, params.Name) + + ipnet.IP = ip + addr := &netlink.Addr{IPNet: ipnet} + + link, err := netlink.LinkByName(params.Name) + if err != nil { + h.logger.Error("Get linux network device by name failed.", "device Name", params.Name, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkAddrInternalServerError() + } + + if err := netlink.AddrDel(link, addr); err != nil { + h.logger.Error("linux network operation failed.", "cmd", cmd, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkAddrInternalServerError() + } + + h.logger.Info("linux network operation success.", "cmd", cmd) + return apiDevice.NewDeleteDeviceNameNetlinkAddrOK() +} diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_route.go b/tools/dpvs-agent/cmd/device/delete_device_name_route.go new file mode 100644 index 000000000..eabc0f976 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_route.go @@ -0,0 +1,59 @@ +package device + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delDeviceRoute struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelDeviceRoute(cp *pool.ConnPool, parentLogger hclog.Logger) *delDeviceRoute { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelDeviceRoute") + } + return &delDeviceRoute{connPool: cp, logger: logger} +} + +// dpip del route 192.168.88.16/32 dev dpdk0.102 +func (h *delDeviceRoute) Handle(params apiDevice.DeleteDeviceNameRouteParams) middleware.Responder { + + // dest [addr], [mask] and [dev name] is useful of delete route only + route := types.NewRouteDetail() + route.SetDevice(params.Name) + if params.Spec == nil { + // FIXME: front error + return apiDevice.NewDeleteDeviceNameRouteInternalServerError() + } + + route.SetDst(params.Spec.Dst) + route.SetScope(params.Spec.Scope) + /* + route.SetSrc(params.Spec.Src) + route.SetGateway(params.Spec.Gateway) + route.SetScope(params.Spec.Scope) + route.SetMtu(params.Spec.Mtu) + route.SetMetric(params.Spec.Metric) + */ + result := route.Del(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Delete route success.", "Device Name", params.Name, "route Dst", params.Spec.Dst) + return apiDevice.NewDeleteDeviceNameRouteOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Delete not exist route done.", "Device Name", params.Name, "route Dst", params.Spec.Dst, "result", result.String()) + return apiDevice.NewDeleteDeviceNameRouteOK() + default: + h.logger.Error("Delete route failed.", "Device Name", params.Name, "route Dst", params.Spec.Dst, "result", result.String()) + } + + return apiDevice.NewDeleteDeviceNameRouteInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go b/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go new file mode 100644 index 000000000..abd2e5620 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go @@ -0,0 +1,46 @@ +package device + +import ( + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delDeviceVlan struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelDeviceVlan(cp *pool.ConnPool, parentLogger hclog.Logger) *delDeviceVlan { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelDeviceVlan") + } + return &delDeviceVlan{connPool: cp, logger: logger} +} + +// dpip vlan del dpdk0.102 +func (h *delDeviceVlan) Handle(params apiDevice.DeleteDeviceNameVlanParams) middleware.Responder { + // vlan device delete is need device name only + vlan := types.NewVlanDevice() + vlan.SetIfName(params.Name) + + result := vlan.Del(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Delete dpvs vlan success.", "Vlan Name", params.Name) + return apiDevice.NewDeleteDeviceNameVlanOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Delete dpvs vlan done.", "Vlan Name", params.Name, "result", result.String()) + return apiDevice.NewDeleteDeviceNameVlanOK() + default: + h.logger.Error("Delete dpvs vlan failed.", "Vlan Name", params.Name, "result", result.String()) + } + + return apiDevice.NewDeleteDeviceNameVlanInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/get_device_name_nic.go b/tools/dpvs-agent/cmd/device/get_device_name_nic.go new file mode 100644 index 000000000..2cedd92a2 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/get_device_name_nic.go @@ -0,0 +1,78 @@ +package device + +import ( + "strings" + + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type getDeviceNameNic struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewGetDeviceNameNic(cp *pool.ConnPool, parentLogger hclog.Logger) *getDeviceNameNic { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("GetDeviceNameNic") + } + return &getDeviceNameNic{connPool: cp, logger: logger} +} + +// dpip link show xxx +func (h *getDeviceNameNic) Handle(params apiDevice.GetDeviceNameNicParams) middleware.Responder { + name := make([]byte, 0x10) + copy(name[:], params.Name[:]) + + desc := types.NewNetifNicDesc() + list, err := desc.GetPortList(h.connPool, h.logger) + if err != types.EDPVS_OK { + h.logger.Info("Get netif ports failed.", "Error", err.String()) + return apiDevice.NewGetDeviceNameNicInternalServerError() + } + + h.logger.Info("Get netif port success.", "port list", list) + exist := false + specModels := new(models.NicDeviceSpecList) + specModels.Items = make([]*models.NicDeviceSpec, len(list.Entries)) + + for i, entry := range list.Entries { + specModels.Items[i] = new(models.NicDeviceSpec) + if strings.EqualFold(strings.ToLower(string(name)), strings.ToLower(entry.GetName())) { + exist = true + } + + portName := entry.GetName() + desc.SetName(portName) + detail, err := desc.GetPortBasic(h.connPool, h.logger) + if err != types.EDPVS_OK { + h.logger.Error("Get netif port base info failed.", "portName", portName, "Error", err.String()) + return apiDevice.NewGetDeviceNameNicInternalServerError() + } + h.logger.Info("Get netif port base info success.", "portName", portName, "port detail", detail) + + stats, err := desc.GetPortStats(h.connPool, h.logger) + if err != types.EDPVS_OK { + h.logger.Error("Get netif port stats info failed.", "portName", portName, "Error", err.String()) + return apiDevice.NewGetDeviceNameNicInternalServerError() + } + h.logger.Info("Get netif port stats info success.", "portName", portName, "port stats", stats) + + specModels.Items[i].Detail = detail.GetModel() + specModels.Items[i].Stats = stats.GetModel() + } + + if exist { + if *params.Stats { + } + } + + return apiDevice.NewGetDeviceNameNicOK().WithPayload(specModels) +} diff --git a/tools/dpvs-agent/cmd/device/ioctl.go b/tools/dpvs-agent/cmd/device/ioctl.go new file mode 100644 index 000000000..ab3297857 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/ioctl.go @@ -0,0 +1,23 @@ +package device + +import ( + "golang.org/x/sys/unix" +) + +func ioctl(fd int, code, data uintptr) error { + _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), code, data) + if errno != 0 { + return errno + } + return nil +} + +type socketAddr4Request struct { + name [unix.IFNAMSIZ]byte + addr unix.RawSockaddrInet4 +} + +type socketAddr6Request struct { + name [unix.IFNAMSIZ]byte + addr unix.RawSockaddrInet6 +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_addr.go b/tools/dpvs-agent/cmd/device/put_device_name_addr.go new file mode 100644 index 000000000..03cd75c82 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_addr.go @@ -0,0 +1,57 @@ +package device + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceAddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceAddr(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceAddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceAddr") + } + return &putDeviceAddr{connPool: cp, logger: logger} +} + +// dpip addr add 192.168.88.16/32 dev dpdk0.102 +func (h *putDeviceAddr) Handle(params apiDevice.PutDeviceNameAddrParams) middleware.Responder { + addr := types.NewInetAddrDetail() + + if params.Spec == nil { + return apiDevice.NewPutDeviceNameAddrInternalServerError() + } + + addr.SetAddr(params.Spec.Addr) + addr.SetScope(params.Spec.Scope) + addr.SetBCast(params.Spec.Broadcast) + addr.SetIfName(params.Name) + if params.Sapool != nil && *params.Sapool { + addr.SetFlags("sapool") + } + // addr.SetValidLft(prarms.Spec.ValidLft) + // addr.SetPreferedLft(prarms.Spec.ValidLft) + + result := addr.Add(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Add addr from device success.", "Device Name", params.Name, "Addr", params.Spec.Addr) + return apiDevice.NewPutDeviceNameAddrOK() + case types.EDPVS_EXIST: + h.logger.Warn("Device already exist addr, add done.", "Device Name", params.Name, "Addr", params.Spec.Addr, "result", result.String()) + return apiDevice.NewPutDeviceNameAddrOK() + default: + h.logger.Error("Add addr from device failed.", "Device Name", params.Name, "Addr", params.Spec.Addr, "result", result.String()) + } + + return apiDevice.NewPutDeviceNameAddrInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_netlink.go b/tools/dpvs-agent/cmd/device/put_device_name_netlink.go new file mode 100644 index 000000000..1a643647c --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_netlink.go @@ -0,0 +1,46 @@ +package device + +import ( + "fmt" + "syscall" + + "github.com/vishvananda/netlink" + + "github.com/dpvs-agent/pkg/ipc/pool" + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +// ip link set xxx up +type setDeviceNetlinkUp struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewSetDeviceNetlinkUp(cp *pool.ConnPool, parentLogger hclog.Logger) *setDeviceNetlinkUp { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("SetDeviceNetlinkUp") + } + return &setDeviceNetlinkUp{connPool: cp, logger: logger} +} + +func (h *setDeviceNetlinkUp) Handle(params apiDevice.PutDeviceNameNetlinkParams) middleware.Responder { + dev := &netlink.Device{LinkAttrs: netlink.LinkAttrs{MTU: 1500, Name: params.Name}} + + if err := netlink.LinkAdd(dev); err != syscall.EEXIST { + h.logger.Error("Check device isExist failed.", "Device Name", params.Name, "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkInternalServerError() + } + + if err := netlink.LinkSetUp(dev); err != nil { + h.logger.Error("Set device link up failed.", "Device Name", params.Name, "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkInternalServerError() + } + + cmd := fmt.Sprintf("ip link set %s up", params.Name) + h.logger.Info("Set device link up success.", "cmd", cmd) + return apiDevice.NewPutDeviceNameNetlinkOK() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go b/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go new file mode 100644 index 000000000..a114ba8fe --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go @@ -0,0 +1,72 @@ +package device + +import ( + "fmt" + "net" + "strings" + + "github.com/vishvananda/netlink" + + "github.com/dpvs-agent/pkg/ipc/pool" + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceNetlinkAddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceNetlinkAddr(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceNetlinkAddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceNetlinkAddr") + } + return &putDeviceNetlinkAddr{connPool: cp, logger: logger} +} + +// ip addr add 10.0.0.1/32 dev eth0 +func (h *putDeviceNetlinkAddr) Handle(params apiDevice.PutDeviceNameNetlinkAddrParams) middleware.Responder { + // h.logger.Info("/v2/device/", params.Name, "/netlink/addr ", params.Spec.Addr) + var cidr string + if strings.Count(params.Spec.Addr, "/") == 0 { + ip := net.ParseIP(params.Spec.Addr) + if ip == nil { + h.logger.Info("Parse IP failed.", "Addr", params.Spec.Addr) + return apiDevice.NewPutDeviceNameNetlinkAddrInternalServerError() + } + if ip.To4() != nil { + cidr = params.Spec.Addr + "/32" + } else { + cidr = params.Spec.Addr + "/128" + } + } else { + cidr = params.Spec.Addr + } + + ip, ipnet, err := net.ParseCIDR(cidr) + if err != nil { + h.logger.Error("Parse CIDR failed.", "cidr", cidr, "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkAddrInternalServerError() + } + + ipnet.IP = ip + addr := &netlink.Addr{IPNet: ipnet} + + link, err := netlink.LinkByName(params.Name) + if err != nil { + h.logger.Error("netlink.LinkByName() failed.", "Device Name", params.Name, "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkAddrInternalServerError() + } + + if err := netlink.AddrAdd(link, addr); err != nil { + h.logger.Error("netlink.AddrAdd() failed.", "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkAddrInternalServerError() + } + + cmd := fmt.Sprintf("ip addr add %s dev %s", cidr, params.Name) + h.logger.Info("Device add Addr success.", "cmd", cmd) + return apiDevice.NewPutDeviceNameNetlinkAddrOK() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_nic.go b/tools/dpvs-agent/cmd/device/put_device_name_nic.go new file mode 100644 index 000000000..419026058 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_nic.go @@ -0,0 +1,63 @@ +package device + +import ( + "fmt" + + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceNameNic struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceNameNic(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceNameNic { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceNameNic") + } + return &putDeviceNameNic{connPool: cp, logger: logger} +} + +// ITEM [promisc|forward2kni|tc-ingress|tc-egress] / [link] +// VALUE [on|off] / [up|down] +// dpip link set nic-name $ITEM $VALUE +func (h *putDeviceNameNic) Handle(params apiDevice.PutDeviceNameNicParams) middleware.Responder { + set := false + cmd := "" + desc := types.NewNetifNicDesc() + if !set { + set = desc.SetFwd2Kni(params.Name, *params.Forward2Kni) + cmd = fmt.Sprintf("dpip link set %s %s", params.Name, params.Forward2Kni) + } + if !set { + set = desc.SetLink(params.Name, *params.Link) + cmd = fmt.Sprintf("dpip link set %s %s", params.Name, params.Link) + } + if !set { + set = desc.SetPromisc(params.Name, *params.Promisc) + cmd = fmt.Sprintf("dpip link set %s %s", params.Name, params.Promisc) + } + + if !set { + h.logger.Error("dpdk link port set failed.", "Name", params.Name) + return apiDevice.NewPutDeviceNameNicInternalServerError() + } + + result := desc.Set(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Set dpdk port success.", "cmd", cmd) + return apiDevice.NewPutDeviceNameNicOK() + default: + h.logger.Info("Set dpdk port failed.", "cmd", cmd, "result", result.String()) + } + + return apiDevice.NewPutDeviceNameNicInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_route.go b/tools/dpvs-agent/cmd/device/put_device_name_route.go new file mode 100644 index 000000000..d9ddea942 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_route.go @@ -0,0 +1,66 @@ +package device + +import ( + "fmt" + + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceRoute struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceRoute(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceRoute { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceRoute") + } + return &putDeviceRoute{connPool: cp, logger: logger} +} + +// dpip route add 192.168.88.16/32 dev dpdk0.102 scope kni_host +func (h *putDeviceRoute) Handle(params apiDevice.PutDeviceNameRouteParams) middleware.Responder { + + // dest [addr], [mask] and [dev name] is useful of delete route only + route := types.NewRouteDetail() + route.SetDevice(params.Name) + if params.Spec == nil { + // FIXME return front invalid + return apiDevice.NewPutDeviceNameRouteInternalServerError() + } + + src := "" + route.SetDst(params.Spec.Dst) + if route.SetSrc(params.Spec.Src) { + src = fmt.Sprintf("src %s", params.Spec.Src) + } + + gateway := "" + if route.SetGateway(params.Spec.Gateway) { + gateway = fmt.Sprintf("via %s", params.Spec.Gateway) + } + route.SetScope(params.Spec.Scope) + route.SetMtu(params.Spec.Mtu) + route.SetMetric(params.Spec.Metric) + + cmd := fmt.Sprintf("dpip route add %s %s dev %s %s", params.Spec.Dst, gateway, params.Name, src) + result := route.Add(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Set dpdk route success.", "cmd", cmd) + return apiDevice.NewPutDeviceNameRouteCreated() + // case types.EDPVS_EXIST: + // FIXME: update ? return apiDevice.NewPutDeviceNameRouteOK() + default: + h.logger.Info("Set dpdk route failed.", "cmd", cmd, "result", result.String()) + } + + return apiDevice.NewPutDeviceNameRouteInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_vlan.go b/tools/dpvs-agent/cmd/device/put_device_name_vlan.go new file mode 100644 index 000000000..4ec011bd7 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_vlan.go @@ -0,0 +1,71 @@ +package device + +import ( + "fmt" + "strconv" + "strings" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceVlan struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceVlan(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceVlan { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceVlan") + } + return &putDeviceVlan{connPool: cp, logger: logger} +} + +// dpip vlan add dpdk0.102 link dpdk0 id 102 +func (h *putDeviceVlan) Handle(params apiDevice.PutDeviceNameVlanParams) middleware.Responder { + vlanName := strings.ToLower(params.Name) + + items := strings.Split(vlanName, ".") + if len(items) != 2 { + return apiDevice.NewPutDeviceNameVlanInternalServerError() + } + + dev := params.Spec.Device + if len(dev) == 0 { + dev = items[0] + } + + id := params.Spec.ID + if len(id) == 0 { + id = items[1] + } + + cmd := fmt.Sprintf("dpip vlan add %s link %s id %s", params.Name, dev, id) + + vlan := types.NewVlanDevice() + vlan.SetIfName(vlanName) + vlan.SetRealDev(dev) + i, err := strconv.Atoi(id) + if err != nil { + return apiDevice.NewPutDeviceNameVlanInternalServerError() + } + vlan.SetId(uint16(i)) + + result := vlan.Add(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Set dpdk vlan success.", "cmd", cmd) + return apiDevice.NewDeleteDeviceNameVlanOK() + default: + h.logger.Error("Set dpdk vlan failed.", "cmd", cmd, "result", result.String()) + } + + return apiDevice.NewDeleteDeviceNameVlanInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go new file mode 100644 index 000000000..9e8771521 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go @@ -0,0 +1,25 @@ +package device + +/* +import ( + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" +) + +type putDeviceLinux struct { + connPool *pool.ConnPool +} + +func NewPutDeviceLinux(cp *pool.ConnPool) *putDeviceLinux { + return &putDeviceVlan{connPool: cp} +} + +// dpip vlan add dpdk0.102 link dpdk0 id 102 +func (h *putDeviceLinux) Handle(params apiDevice.PutDeviceNameLinuxParams) middleware.Responder { +} +*/ diff --git a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go new file mode 100644 index 000000000..ce1c644e4 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go @@ -0,0 +1,117 @@ +package device + +/* +// SIOCDIFADDR + +import ( + "net" + "strconv" + "strings" + "unsafe" + + "golang.org/x/sys/unix" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" +) + +type deleteDeviceNameLinuxAddr struct { + connPool *pool.ConnPool +} + +func NewDeleteDeviceNameLinuxAddr(cp *pool.ConnPool) *deleteDeviceNameLinuxAddr { + return &deleteDeviceNameLinuxAddr{connPool: cp} +} + +func (h *deleteDeviceNameLinuxAddr) Handler(params *apiDevice.DeleteDeviceNameLinuxAddrParams) middleware.Responder { + if len(params.Spec.Addr) == 0 { + return apiDevice.NewDeleteDeviceNameLinuxAddrInternalServerError() + } + + items := strings.Split(params.Spec.Addr, "/") + + addr := net.ParseIP(items[0]) + if addr == nil { + return apiDevice.NewDeleteDeviceNameLinuxAddrInternalServerError() + } + + if addr.To4() != nil { + mask := 32 + if len(items) > 1 { + m, err := strconv.Atoi(items[1]) + if err == nil { + mask = m + } + } + if err := delAddr4(params.Name, addr, mask); err != nil { + return apiDevice.NewDeleteDeviceNameLinuxAddrInternalServerError() + } + } else { + mask := 128 + if len(items) > 1 { + m, err := strconv.Atoi(items[1]) + if err == nil { + mask = m + } + } + if err := setAddr6(params.Name, addr, mask); err != nil { + return apiDevice.NewDeleteDeviceNameLinuxAddrInternalServerError() + } + } + return apiDevice.NewDeleteDeviceNameLinuxAddrOK() +} + +func delAddr4(name string, ip net.IP, mask int) error { + fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0) + if err != nil { + return err + } + + defer unix.Close(fd) + sa := socketAddr4Request{} + sa.addr.Family = unix.AF_INET + copy(sa.name[:], name) + + buf, err := ip.MarshalText() + if err != nil { + return err + } + + copy(sa.addr.Addr[:], buf) + // delete address + if err := ioctl(fd, unix.SIOCDIFADDR, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + return nil +} + +func delAddr6(name string, ip net.IP, mask int) error { + fd, err := unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0) + if err != nil { + return err + } + + defer unix.Close(fd) + sa := socketAddr6Request{} + sa.addr.Family = unix.AF_INET6 + copy(sa.name[:], name) + + buf, err := ip.MarshalText() + if err != nil { + return err + } + + copy(sa.addr.Addr[:], buf) + // delete address + if err := ioctl(fd, unix.SIOCDIFADDR, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + return nil +} +*/ diff --git a/tools/dpvs-agent/cmd/device/todo_get_device.go b/tools/dpvs-agent/cmd/device/todo_get_device.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go new file mode 100644 index 000000000..a1f95a889 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go @@ -0,0 +1,3 @@ +package device + +// http://blog.pytool.com/language/clang/socket/linux-socket-ifreq/ diff --git a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go new file mode 100644 index 000000000..b56f455b6 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go @@ -0,0 +1,132 @@ +package device + +/* +import ( + "net" + "strconv" + "strings" + "unsafe" + + "golang.org/x/sys/unix" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" +) + +// ip addr add 192.168.88.68/32 dev dpdk0.102.kni + +type putDeviceNameLinuxAddr struct { + connPool *pool.ConnPool +} + +func NewPutDeviceNameLinux(cp *pool.ConnPool) *putDeviceNameLinuxAddr { + return &putDeviceNameLinuxAddr{connPool: cp} +} + +func (h *putDeviceNameLinuxAddr) Handler(params *apiDevice.PutDeviceNameLinuxAddrParams) middleware.Responder { + if len(params.Spec.Addr) == 0 { + return apiDevice.NewPutDeviceNameLinuxAddrInternalServerError() + } + + items := strings.Split(params.Spec.Addr, "/") + + addr := net.ParseIP(items[0]) + if addr == nil { + return apiDevice.NewPutDeviceNameLinuxAddrInternalServerError() + } + + if addr.To4() != nil { + mask := 32 + if len(items) > 1 { + m, err := strconv.Atoi(items[1]) + if err == nil { + mask = m + } + } + if err := setAddr4(params.Name, addr, mask); err != nil { + return apiDevice.NewPutDeviceNameLinuxAddrInternalServerError() + } + } else { + mask := 128 + if len(items) > 1 { + m, err := strconv.Atoi(items[1]) + if err == nil { + mask = m + } + } + if err := setAddr6(params.Name, addr, mask); err != nil { + return apiDevice.NewPutDeviceNameLinuxAddrInternalServerError() + } + } + + return apiDevice.NewPutDeviceNameLinuxAddrOK() +} + +func setAddr4(name string, ip net.IP, mask int) error { + fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0) + if err != nil { + return err + } + + defer unix.Close(fd) + sa := socketAddr4Request{} + sa.addr.Family = unix.AF_INET + copy(sa.name[:], name) + + buf, err := ip.MarshalText() + if err != nil { + return err + } + + copy(sa.addr.Addr[:], buf) + // Set address + if err := ioctl(fd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + // Set netmask + mbuf := net.CIDRMask(mask, 32) + copy(sa.addr.Addr[:], []byte(mbuf)) + if err := ioctl(fd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + return nil +} + +func setAddr6(name string, ip net.IP, mask int) error { + fd, err := unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0) + if err != nil { + return err + } + + defer unix.Close(fd) + sa := socketAddr6Request{} + sa.addr.Family = unix.AF_INET6 + copy(sa.name[:], name) + + buf, err := ip.MarshalText() + if err != nil { + return err + } + + copy(sa.addr.Addr[:], buf) + // Set address + if err := ioctl(fd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + // Set netmask + mbuf := net.CIDRMask(mask, 128) + copy(sa.addr.Addr[:], []byte(mbuf)) + if err := ioctl(fd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + return nil +} +*/ diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile b/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile new file mode 100644 index 000000000..9ba2dd914 --- /dev/null +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile @@ -0,0 +1,26 @@ +TARGET := dpvs-agent + +GO ?= go +LD_FLAGS = -ldflags="-s -w" +GO_BUILD = CGO_ENABLED=0 $(GO) build $(LD_FLAGS) +GO_CLEAN = $(GO) clean +INSTALL = install +RM = rm + +.PHONY: all $(TARGET) clean install + +all: $(TARGET) + +$(TARGET): + $(GO_BUILD) -o $@ + +clean: + $(GO_CLEAN) + -$(RM) $(TARGET) + +install: $(TARGET) + $(INSTALL) -m 0755 -d $(INSDIR) + $(INSTALL) -m 0744 $(TARGET) $(INSDIR) + +uninstall: + -$(RM) -f $(TARGET) $(INSDIR)/$(TARGET) diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go new file mode 100644 index 000000000..f4d5393e9 --- /dev/null +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go @@ -0,0 +1,181 @@ +package main + +import ( + "context" + "errors" + "net" + "os" + "strings" + "time" + + "github.com/hashicorp/go-hclog" + "github.com/lestrrat-go/file-rotatelogs" + + "github.com/dpvs-agent/cmd/device" + "github.com/dpvs-agent/cmd/ipvs" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/restapi" + "github.com/dpvs-agent/restapi/operations" +) + +var ( + IpcSocket string = "/var/run/dpvs.ipc" +) + +type DpvsAgentServer struct { + LogDir string `long:"log-dir" description:"default log dir is /var/log/ And log name dpvs-agent.log" default:"/var/log/"` + IpcSocketPath string `long:"ipc-sockopt-path" description:"default ipc socket path /var/run/dpvs.ipc" default:"/var/run/dpvs.ipc"` + restapi.Server +} + +func unixDialer(ctx context.Context) (net.Conn, error) { + retry := 0 + d := net.Dialer{Timeout: 10 * time.Second} + raddr := net.UnixAddr{Name: "/var/run/dpvs.ipc", Net: "unix"} + for { + conn, err := d.DialContext(ctx, "unix", raddr.String()) + if err == nil { + return conn, nil + } + // FIXME: A weird fact was observed in tests of large concurrency that the previous + // "DailContext" returned the error "resource temporarily unavailable" occasionally. + // No solution to it has found yet, thus just retry as a compromise. + if strings.Contains(err.Error(), "resource temporarily unavailable") != true { + return nil, err + } + retry++ + if retry > 10 { + return nil, err + } + } + return nil, errors.New("unknown error") +} + +func (agent *DpvsAgentServer) instantiateAPI(restAPI *operations.DpvsAgentAPI) { + if strings.HasSuffix(agent.IpcSocketPath, ".ipc") { + s, err := os.Stat(agent.IpcSocketPath) + if err == nil { + if !s.IsDir() { + IpcSocket = agent.IpcSocketPath + } + } + } + + cp := pool.NewConnPool(&pool.Options{ + Dialer: unixDialer, + PoolSize: 1024, + // PoolTimeout: -1, + // IdleTimeout: -1, + // IdleCheckFrequency: -1, + }) + + logDir := "/var/log/" + if len(agent.LogDir) > 1 { // avoid root path '/' set + s, err := os.Stat(agent.LogDir) + if err == nil { + if s.IsDir() { + logDir = agent.LogDir + } + } + } + + sep := "/" + if strings.HasSuffix(logDir, "/") { + sep = "" + } + + logFile := strings.Join([]string{logDir, "dpvs-agent.log"}, sep) + // logOpt := &hclog.LoggerOptions{Name: logFile} + var logOpt *hclog.LoggerOptions + logFileNamePattern := strings.Join([]string{logFile, "%Y%m%d%H%M"}, "-") + logRotationInterval := 1 * time.Hour + + logF, err := rotatelogs.New( + logFileNamePattern, + rotatelogs.WithLinkName(logFile), + rotatelogs.WithRotationTime(logRotationInterval), + ) + // f, err := os.Create(logFile) + if err == nil { + logOpt = &hclog.LoggerOptions{Name: logFile, Output: logF} + } else { + os.Exit(-1) + } + + hclog.SetDefault(hclog.New(logOpt)) + + logger := hclog.Default().Named("main") + + // delete + restAPI.VirtualserverDeleteVsVipPortHandler = ipvs.NewDelVsItem(cp, logger) + restAPI.VirtualserverDeleteVsVipPortLaddrHandler = ipvs.NewDelVsLaddr(cp, logger) + restAPI.VirtualserverDeleteVsVipPortRsHandler = ipvs.NewDelVsRs(cp, logger) + restAPI.VirtualserverDeleteVsVipPortDenyHandler = ipvs.NewDelVsDeny(cp, logger) + restAPI.VirtualserverDeleteVsVipPortAllowHandler = ipvs.NewDelVsAllow(cp, logger) + + // get + restAPI.VirtualserverGetVsHandler = ipvs.NewGetVs(cp, logger) + restAPI.VirtualserverGetVsVipPortHandler = ipvs.NewGetVsVipPort(cp, logger) + restAPI.VirtualserverGetVsVipPortLaddrHandler = ipvs.NewGetVsLaddr(cp, logger) + + // put + restAPI.VirtualserverPutVsVipPortHandler = ipvs.NewPutVsItem(cp, logger) + restAPI.VirtualserverPutVsVipPortLaddrHandler = ipvs.NewPutVsLaddr(cp, logger) + restAPI.VirtualserverPutVsVipPortRsHandler = ipvs.NewPutVsRs(cp, logger) + restAPI.VirtualserverPutVsVipPortDenyHandler = ipvs.NewPutVsDeny(cp, logger) + restAPI.VirtualserverPutVsVipPortAllowHandler = ipvs.NewPutVsAllow(cp, logger) + + // post + restAPI.VirtualserverPostVsVipPortRsHandler = ipvs.NewPostVsRs(cp, logger) + + // get + // restAPI.DeviceGetDeviceNameAddrHandler + // restAPI.DeviceGetDeviceNameRouteHandler + // restAPI.DeviceGetDeviceNameVlanHandler + restAPI.DeviceGetDeviceNameNicHandler = device.NewGetDeviceNameNic(cp, logger) + + // put + restAPI.DevicePutDeviceNameNetlinkHandler = device.NewSetDeviceNetlinkUp(cp, logger) + restAPI.DevicePutDeviceNameAddrHandler = device.NewPutDeviceAddr(cp, logger) + restAPI.DevicePutDeviceNameRouteHandler = device.NewPutDeviceRoute(cp, logger) + restAPI.DevicePutDeviceNameVlanHandler = device.NewPutDeviceVlan(cp, logger) + restAPI.DevicePutDeviceNameNetlinkAddrHandler = device.NewPutDeviceNetlinkAddr(cp, logger) + restAPI.DevicePutDeviceNameNicHandler = device.NewPutDeviceNameNic(cp, logger) + + // delete + restAPI.DeviceDeleteDeviceNameAddrHandler = device.NewDelDeviceAddr(cp, logger) + restAPI.DeviceDeleteDeviceNameRouteHandler = device.NewDelDeviceRoute(cp, logger) + restAPI.DeviceDeleteDeviceNameVlanHandler = device.NewDelDeviceVlan(cp, logger) + restAPI.DeviceDeleteDeviceNameNetlinkAddrHandler = device.NewDelDeviceNetlinkAddr(cp, logger) +} + +func (agent *DpvsAgentServer) InstantiateServer(api *operations.DpvsAgentAPI) *restapi.Server { + agent.instantiateAPI(api) + + server := restapi.NewServer(api) + server.ConfigureAPI() + + server.EnabledListeners = make([]string, len(agent.EnabledListeners)) + copy(server.EnabledListeners, agent.EnabledListeners) + server.CleanupTimeout = agent.CleanupTimeout + server.GracefulTimeout = agent.GracefulTimeout + server.MaxHeaderSize = agent.MaxHeaderSize + server.SocketPath = agent.SocketPath + server.Host = agent.Host + server.Port = agent.Port + server.ListenLimit = agent.ListenLimit + server.KeepAlive = agent.KeepAlive + server.ReadTimeout = agent.ReadTimeout + server.WriteTimeout = agent.WriteTimeout + server.TLSHost = agent.TLSHost + server.TLSPort = agent.TLSPort + server.TLSCertificate = agent.TLSCertificate + server.TLSCertificateKey = agent.TLSCertificateKey + server.TLSCACertificate = agent.TLSCACertificate + server.TLSListenLimit = agent.TLSListenLimit + server.TLSKeepAlive = agent.TLSKeepAlive + server.TLSReadTimeout = agent.TLSReadTimeout + server.TLSWriteTimeout = agent.TLSWriteTimeout + + return server +} diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/main.go b/tools/dpvs-agent/cmd/dpvs-agent-server/main.go new file mode 100644 index 000000000..11912e77e --- /dev/null +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/main.go @@ -0,0 +1,55 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package main + +import ( + "log" + "os" + + "github.com/go-openapi/loads" + flags "github.com/jessevdk/go-flags" + + "github.com/dpvs-agent/restapi" + "github.com/dpvs-agent/restapi/operations" +) + +// This file was generated by the swagger tool. +// Make sure not to overwrite this file after you generated it because all your edits would be lost! +func main() { + swaggerSpec, err := loads.Embedded(restapi.SwaggerJSON, restapi.FlatSwaggerJSON) + if err != nil { + log.Fatalln(err) + } + + api := operations.NewDpvsAgentAPI(swaggerSpec) + + agent := &DpvsAgentServer{} + + parser := flags.NewParser(agent, flags.Default) + parser.ShortDescription = "dpvs agent" + parser.LongDescription = "dpvs agent api" + for _, optsGroup := range api.CommandLineOptionsGroups { + _, err := parser.AddGroup(optsGroup.ShortDescription, optsGroup.LongDescription, optsGroup.Options) + if err != nil { + log.Fatalln(err) + } + } + + if _, err := parser.Parse(); err != nil { + code := 1 + if fe, ok := err.(*flags.Error); ok { + if fe.Type == flags.ErrHelp { + code = 0 + } + } + os.Exit(code) + } + + server := agent.InstantiateServer(api) + defer server.Shutdown() + + if err := server.Serve(); err != nil { + log.Fatalln(err) + } + +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go new file mode 100644 index 000000000..f9c4a645c --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go @@ -0,0 +1,45 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsItem struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsItem(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsItem { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPort") + } + return &delVsItem{connPool: cp, logger: logger} +} + +func (h *delVsItem) Handle(params apiVs.DeleteVsVipPortParams) middleware.Responder { + vs := types.NewVirtualServerSpec() + if err := vs.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortFailure() + } + + result := vs.Del(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Del virtual server success.", "VipPort", params.VipPort) + return apiVs.NewDeleteVsVipPortOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Del a not exist virtual server done.", "VipPort", params.VipPort, "result", result.String()) + return apiVs.NewDeleteVsVipPortNotFound() + default: + h.logger.Error("Del virtual server failed.", "VipPort", params.VipPort, "result", result.String()) + } + return apiVs.NewDeleteVsVipPortFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go new file mode 100644 index 000000000..0d8678f2b --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +package ipvs + +import ( + "net" + + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsAllow struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsAllow(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsAllow { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPortAllow") + } + return &delVsAllow{connPool: cp, logger: logger} +} + +func (h *delVsAllow) Handle(params apiVs.DeleteVsVipPortAllowParams) middleware.Responder { + spec := types.NewCertificateAuthoritySpec() + if err := spec.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortAllowInvalidFrontend() + } + + failed := false + for _, allow := range params.ACL.Items { + if net.ParseIP(allow.Addr) == nil { + h.logger.Error("Invalid ip addr del.", "VipPort", params.VipPort, "Addr", allow.Addr) + return apiVs.NewDeleteVsVipPortAllowInvalidFrontend() + } + spec.SetSrc(allow.Addr) + + if result := spec.Del(h.connPool, false, h.logger); result != types.EDPVS_OK { + failed = true + h.logger.Error("IP Addr delete from white list failed.", "VipPort", params.VipPort, "Addr", allow.Addr, "result", result.String()) + continue + } + h.logger.Info("IP Addr delete from white list success.", "VipPort", params.VipPort, "Addr", allow.Addr) + } + + if failed { + return apiVs.NewDeleteVsVipPortAllowInvalidBackend() + } + + return apiVs.NewDeleteVsVipPortAllowOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go new file mode 100644 index 000000000..1352386d8 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +package ipvs + +import ( + "net" + + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsDeny struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsDeny(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsDeny { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPortDeny") + } + return &delVsDeny{connPool: cp, logger: logger} +} + +func (h *delVsDeny) Handle(params apiVs.DeleteVsVipPortDenyParams) middleware.Responder { + spec := types.NewCertificateAuthoritySpec() + if err := spec.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortDenyInvalidFrontend() + } + + failed := false + for _, deny := range params.ACL.Items { + if net.ParseIP(deny.Addr) == nil { + h.logger.Error("Invalid ip addr del.", "VipPort", params.VipPort, "Addr", deny.Addr) + return apiVs.NewDeleteVsVipPortDenyInvalidFrontend() + } + spec.SetSrc(deny.Addr) + + if result := spec.Del(h.connPool, true, h.logger); result != types.EDPVS_OK { + h.logger.Error("IP Addr delete from black list failed.", "VipPort", params.VipPort, "Addr", deny.Addr, "result", result.String()) + failed = true + continue + } + h.logger.Info("IP Addr delete from black list success.", "VipPort", params.VipPort, "Addr", deny.Addr) + } + + if failed { + return apiVs.NewDeleteVsVipPortDenyInvalidBackend() + } + + return apiVs.NewDeleteVsVipPortDenyOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go new file mode 100644 index 000000000..4780c7424 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go @@ -0,0 +1,52 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsLaddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsLaddr(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsLaddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPortLaddr") + } + return &delVsLaddr{connPool: cp, logger: logger} +} + +func (h *delVsLaddr) Handle(params apiVs.DeleteVsVipPortLaddrParams) middleware.Responder { + laddr := types.NewLocalAddrFront() + if err := laddr.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortLaddrInvalidFrontend() + } + + lds := make([]*types.LocalAddrDetail, 1) + lds[0] = types.NewLocalAddrDetail() + lds[0].SetAfByAddr(params.Spec.Addr) + lds[0].SetAddr(params.Spec.Addr) + lds[0].SetIfName(params.Spec.Device) + + result := laddr.Del(lds, h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Delete local ip from virtual server success.", "VipPort", params.VipPort, "Addr", params.Spec.Addr, "Device", params.Spec.Device) + return apiVs.NewDeleteVsVipPortLaddrOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Delete not exist local ip from virtual server done.", "VipPort", params.VipPort, "Addr", params.Spec.Addr, "Device", params.Spec.Device) + return apiVs.NewDeleteVsVipPortLaddrOK() + default: + h.logger.Error("Delete local ip from virtual server failed.", "VipPort", params.VipPort, "Addr", params.Spec.Addr, "Device", params.Spec.Device, "result", result.String()) + } + + return apiVs.NewDeleteVsVipPortLaddrFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go new file mode 100644 index 000000000..222635645 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsRs struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsRs(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsRs { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPortRs") + } + return &delVsRs{connPool: cp, logger: logger} +} + +func (h *delVsRs) Handle(params apiVs.DeleteVsVipPortRsParams) middleware.Responder { + rs := types.NewRealServerFront() + if err := rs.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortRsInvalidFrontend() + } + + rss := make([]*types.RealServerSpec, len(params.Rss.Items)) + for i, s := range params.Rss.Items { + rss[i] = types.NewRealServerSpec() + rss[i].SetAf(rs.GetAf()) + rss[i].SetProto(rs.GetProto()) + rss[i].SetPort(s.Port) + rss[i].SetAddr(s.IP) + rss[i].SetWeight(uint32(s.Weight)) + // rss[i].SetConnFlags(types.DPVS_FWD_MODE_FNAT) + } + result := rs.Del(rss, h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Del rs from virtual server success.", "VipPort", params.VipPort, "rss", rss) + return apiVs.NewDeleteVsVipPortRsOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("There is some not exist rs with virtual server delete done.", "VipPort", params.VipPort, "rss", rss) + return apiVs.NewDeleteVsVipPortRsOK() + default: + h.logger.Error("Del rs from virtual server failed.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + } + + return apiVs.NewDeleteVsVipPortRsFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs.go b/tools/dpvs-agent/cmd/ipvs/get_vs.go new file mode 100644 index 000000000..a6d8c1025 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/get_vs.go @@ -0,0 +1,71 @@ +package ipvs + +import ( + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type getVs struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewGetVs(cp *pool.ConnPool, parentLogger hclog.Logger) *getVs { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("GetVs") + } + return &getVs{connPool: cp, logger: logger} +} + +func (h *getVs) Handle(params apiVs.GetVsParams) middleware.Responder { + front := types.NewVirtualServerFront() + vss, err := front.Get(h.connPool, h.logger) + if err != nil { + h.logger.Error("Get virtual server list failed.", "Error", err.Error()) + // FIXME: Invalid + return apiVs.NewGetVsOK() + } + + h.logger.Info("Get all virtual server done.", "vss", vss) + vsModels := new(models.VirtualServerList) + vsModels.Items = make([]*models.VirtualServerSpecExpand, len(vss)) + for i, vs := range vss { + front := types.NewRealServerFront() + + err := front.ParseVipPortProto(vs.ID()) + if err != nil { + h.logger.Error("Convert to virtual server failed. virtual server", "ID", vs.ID(), "Error", err.Error()) + continue + } + front.SetNumDests(vs.GetNumDests()) + + rss, err := front.Get(h.connPool, h.logger) + if err != nil { + h.logger.Error("Get real server list of virtual server failed.", "ID", vs.ID(), "Error", err.Error()) + continue + } + + h.logger.Info("Get real server list of virtual server success.", "ID", vs.ID(), "rss", rss) + + vsModels.Items[i] = vs.GetModel() + vsStats := (*types.ServerStats)(vsModels.Items[i].Stats) + vsModels.Items[i].RSs = new(models.RealServerExpandList) + vsModels.Items[i].RSs.Items = make([]*models.RealServerSpecExpand, len(rss)) + + for j, rs := range rss { + rsModel := rs.GetModel() + rsStats := (*types.ServerStats)(rsModel.Stats) + vsModels.Items[i].RSs.Items[j] = rsModel + vsStats.Increase(rsStats) + } + } + + return apiVs.NewGetVsOK().WithPayload(vsModels) +} diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go new file mode 100644 index 000000000..873e6d533 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go @@ -0,0 +1,79 @@ +package ipvs + +import ( + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type getVsVipPort struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewGetVsVipPort(cp *pool.ConnPool, parentLogger hclog.Logger) *getVsVipPort { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("GetVsVipPort") + } + return &getVsVipPort{connPool: cp, logger: logger} +} + +func (h *getVsVipPort) Handle(params apiVs.GetVsVipPortParams) middleware.Responder { + var vss []*types.VirtualServerSpec + spec := types.NewVirtualServerSpec() + err := spec.ParseVipPortProto(params.VipPort) + if err != nil { + h.logger.Warn("Convert to virtual server failed. Get All virtual server.", "VipPort", params.VipPort, "Error", err.Error()) + front := types.NewVirtualServerFront() + vss, err = front.Get(h.connPool, h.logger) + } else { + vss, err = spec.Get(h.connPool, h.logger) + } + + if err != nil { + h.logger.Error("Get virtual server list failed.", "Error", err.Error()) + return apiVs.NewGetVsVipPortNotFound() + } + + vsModels := new(models.VirtualServerList) + vsModels.Items = make([]*models.VirtualServerSpecExpand, len(vss)) + + for i, vs := range vss { + front := types.NewRealServerFront() + + err := front.ParseVipPortProto(vs.ID()) + if err != nil { + h.logger.Error("Convert to virtual server failed. virtual server", "ID", vs.ID(), "Error", err.Error()) + continue + } + front.SetNumDests(vs.GetNumDests()) + + rss, err := front.Get(h.connPool, h.logger) + if err != nil { + h.logger.Error("Get real server list of virtual server failed.", "ID", vs.ID(), "Error", err.Error()) + continue + } + + h.logger.Info("Get real server list of virtual server success.", "ID", vs.ID(), "rss", rss) + + vsModels.Items[i] = vs.GetModel() + vsStats := (*types.ServerStats)(vsModels.Items[i].Stats) + vsModels.Items[i].RSs = new(models.RealServerExpandList) + vsModels.Items[i].RSs.Items = make([]*models.RealServerSpecExpand, len(rss)) + + for j, rs := range rss { + rsModel := rs.GetModel() + rsStats := (*types.ServerStats)(rsModel.Stats) + vsModels.Items[i].RSs.Items[j] = rsModel + vsStats.Increase(rsStats) + } + } + + return apiVs.NewGetVsVipPortOK().WithPayload(vsModels) +} diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go new file mode 100644 index 000000000..adac60936 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go @@ -0,0 +1,50 @@ +package ipvs + +import ( + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type getVsLaddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewGetVsLaddr(cp *pool.ConnPool, parentLogger hclog.Logger) *getVsLaddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("GetVsVipPortLaddr") + } + return &getVsLaddr{connPool: cp, logger: logger} +} + +func (h *getVsLaddr) Handle(params apiVs.GetVsVipPortLaddrParams) middleware.Responder { + laddr := types.NewLocalAddrFront() + if err := laddr.ParseVipPortProto(params.VipPort); err != nil { + // FIXME: return all laddr + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewGetVsVipPortLaddrNotFound() + } + + lds, err := laddr.Get(h.connPool, h.logger) + if err != nil { + h.logger.Error("Get virtual server laddr failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewGetVsVipPortLaddrNotFound() + } + + h.logger.Info("Get virtual server laddr success.", "VipPort", params.VipPort, "local addr details", "lds", lds) + laddrModels := new(models.LocalAddressExpandList) + laddrModels.Items = make([]*models.LocalAddressSpecExpand, len(lds)) + for i, detail := range lds { + h.logger.Info("Virtual Server", "VipPort", params.VipPort, "detail", detail) + laddrModels.Items[i] = detail.GetModel() + } + + return apiVs.NewGetVsVipPortLaddrOK().WithPayload(laddrModels) +} diff --git a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go new file mode 100644 index 000000000..4f577cca0 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go @@ -0,0 +1,59 @@ +package ipvs + +import ( + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type postVsRs struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPostVsRs(cp *pool.ConnPool, parentLogger hclog.Logger) *postVsRs { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PostVsVipPortRs") + } + return &postVsRs{connPool: cp, logger: logger} +} + +func (h *postVsRs) Handle(params apiVs.PostVsVipPortRsParams) middleware.Responder { + front := types.NewRealServerFront() + if err := front.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPostVsVipPortRsInvalidFrontend() + } + + rss := make([]*types.RealServerSpec, len(params.Rss.Items)) + for i, rs := range params.Rss.Items { + var fwdmode types.DpvsFwdMode + fwdmode.FromString(rs.Mode) + rss[i] = types.NewRealServerSpec() + rss[i].SetAf(front.GetAf()) + rss[i].SetPort(rs.Port) + rss[i].SetWeight(uint32(rs.Weight)) + rss[i].SetProto(front.GetProto()) + rss[i].SetAddr(rs.IP) + rss[i].SetInhibited(rs.Inhibited) + rss[i].SetOverloaded(rs.Inhibited) + rss[i].SetFwdMode(fwdmode) + } + + result := front.Update(rss, h.connPool, h.logger) + switch result { + case types.EDPVS_EXIST, types.EDPVS_OK: + h.logger.Info("Set real server to virtual server success.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPostVsVipPortRsOK() + default: + h.logger.Error("Set real server to virtual server failed.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPostVsVipPortRsFailure() + } + return apiVs.NewPostVsVipPortRsInvalidBackend() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go new file mode 100644 index 000000000..c6c09f285 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go @@ -0,0 +1,96 @@ +package ipvs + +import ( + "strings" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + "golang.org/x/sys/unix" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsItem struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsItem(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsItem { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPort") + } + return &putVsItem{connPool: cp, logger: logger} +} + +// ipvsadm -A vip:port -s wrr +func (h *putVsItem) Handle(params apiVs.PutVsVipPortParams) middleware.Responder { + vs := types.NewVirtualServerSpec() + err := vs.ParseVipPortProto(params.VipPort) + if err != nil { + h.logger.Error("Convert to virtual server failed", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortInvalidFrontend() + } + + schedName := "" + + if params.Spec != nil { + schedName = params.Spec.SchedName + + vs.SetFwmark(params.Spec.Fwmark) + vs.SetConnTimeout(params.Spec.ConnTimeout) // establish time out + vs.SetBps(params.Spec.Bps) + vs.SetLimitProportion(params.Spec.LimitProportion) + + if params.Spec.Timeout != 0 { + vs.SetTimeout(params.Spec.Timeout) // persistence time out + vs.SetFlagsPersistent() + } + + if params.Spec.ExpireQuiescent != nil && *params.Spec.ExpireQuiescent { + vs.SetFlagsExpireQuiescent() + } + + if params.Spec.SyncProxy != nil && *params.Spec.SyncProxy { + vs.SetFlagsSyncProxy() + } + } + + vs.SetSchedName(schedName) + if strings.EqualFold(vs.GetSchedName(), "conhash") { + vs.SetFlagsHashSrcIP() + + if vs.GetProto() == unix.IPPROTO_UDP { + // if strings.EqualFold(strings.ToLower(params.Spec.HashTaget), "qid") {vs.SetFlagsHashQuicID()} + } + } + + result := vs.Add(h.connPool, h.logger) + h.logger.Info("Add virtual server done.", "vs", vs, "result", result.String()) + switch result { + case types.EDPVS_OK: + // return 201 + h.logger.Info("Created new virtual server success.", "VipPort", params.VipPort) + return apiVs.NewPutVsVipPortCreated() + case types.EDPVS_EXIST: + h.logger.Info("The virtual server already exist! Try to update.", "VipPort", params.VipPort) + reason := vs.Update(h.connPool, h.logger) + if reason != types.EDPVS_OK { + // return 461 + h.logger.Error("Update virtual server failed.", "VipPort", params.VipPort, "reason", reason.String()) + return apiVs.NewPutVsVipPortInvalidBackend() + } + h.logger.Info("Update virtual server success.", "VipPort", params.VipPort) + // return 200 + return apiVs.NewPutVsVipPortOK() + default: + h.logger.Error("Add virtual server failed.", "result", result.String()) + return apiVs.NewPutVsVipPortInvalidBackend() + } + + return apiVs.NewPutVsVipPortOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go new file mode 100644 index 000000000..dabcc000b --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go @@ -0,0 +1,58 @@ +package ipvs + +import ( + // "fmt" + "net" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsAllow struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsAllow(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsAllow { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPortAllow") + } + return &putVsAllow{connPool: cp, logger: logger} +} + +func (h *putVsAllow) Handle(params apiVs.PutVsVipPortAllowParams) middleware.Responder { + spec := types.NewCertificateAuthoritySpec() + if err := spec.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortAllowInvalidFrontend() + } + + failed := false + for _, allow := range params.ACL.Items { + if net.ParseIP(allow.Addr) == nil { + h.logger.Error("Invalid ip addr add.", "VipPort", params.VipPort, "Addr", allow.Addr) + return apiVs.NewPutVsVipPortAllowInvalidFrontend() + } + spec.SetSrc(allow.Addr) + + if result := spec.Add(h.connPool, false, h.logger); result != types.EDPVS_OK { + failed = true + h.logger.Error("Add ip addr to white list failed.", "VipPort", params.VipPort, "Addr", allow.Addr, "result", result.String()) + continue + } + h.logger.Info("Add ip addr to white list success.", "VipPort", params.VipPort, "Addr", allow.Addr) + } + + if failed { + return apiVs.NewPutVsVipPortAllowInvalidBackend() + } + + return apiVs.NewPutVsVipPortAllowOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go new file mode 100644 index 000000000..984dff17a --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go @@ -0,0 +1,58 @@ +package ipvs + +import ( + // "fmt" + "net" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsDeny struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsDeny(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsDeny { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPortDeny") + } + return &putVsDeny{connPool: cp, logger: logger} +} + +func (h *putVsDeny) Handle(params apiVs.PutVsVipPortDenyParams) middleware.Responder { + spec := types.NewCertificateAuthoritySpec() + if err := spec.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortDenyInvalidFrontend() + } + + failed := false + for _, deny := range params.ACL.Items { + if net.ParseIP(deny.Addr) == nil { + h.logger.Error("Invalid ip addr add.", "VipPort", params.VipPort, "Addr", deny.Addr) + return apiVs.NewPutVsVipPortDenyInvalidFrontend() + } + spec.SetSrc(deny.Addr) + + if result := spec.Add(h.connPool, true, h.logger); result != types.EDPVS_OK { + h.logger.Error("Add ip addr to black list failed.", "VipPort", params.VipPort, "Addr", deny.Addr, "result", result.String()) + failed = true + continue + } + h.logger.Info("Add ip addr to black list success.", "VipPort", params.VipPort, "Addr", deny.Addr) + } + + if failed { + return apiVs.NewPutVsVipPortDenyInvalidBackend() + } + + return apiVs.NewPutVsVipPortDenyOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go new file mode 100644 index 000000000..6551abea3 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go @@ -0,0 +1,55 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsLaddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsLaddr(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsLaddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPortLaddr") + } + return &putVsLaddr{connPool: cp, logger: logger} +} + +func (h *putVsLaddr) Handle(params apiVs.PutVsVipPortLaddrParams) middleware.Responder { + laddr := types.NewLocalAddrFront() + + err := laddr.ParseVipPortProto(params.VipPort) + if err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortLaddrInvalidFrontend() + } + + lds := make([]*types.LocalAddrDetail, 1) + + lds[0] = types.NewLocalAddrDetail() + lds[0].SetAf(laddr.GetAf()) + lds[0].SetAddr(params.Spec.Addr) + lds[0].SetIfName(params.Spec.Device) + + result := laddr.Add(lds, h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Set virtual server Local IP success.", "VipPort", params.VipPort, "Local Addr", params.Spec.Addr) + return apiVs.NewPutVsVipPortLaddrOK() + case types.EDPVS_EXIST: + h.logger.Warn("Local IP already exist.", "VipPort", params.VipPort, "Local Addr", params.Spec.Addr, "result", result.String()) + return apiVs.NewPutVsVipPortLaddrOK() + default: + h.logger.Error("Set virtual server Local IP failed.", "VipPort", params.VipPort, "Local Addr", params.Spec.Addr, "result", result.String()) + } + + return apiVs.NewPutVsVipPortLaddrFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go new file mode 100644 index 000000000..05380108c --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go @@ -0,0 +1,74 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsRs struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsRs(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsRs { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPortRs") + } + return &putVsRs{connPool: cp, logger: logger} +} + +func (h *putVsRs) Handle(params apiVs.PutVsVipPortRsParams) middleware.Responder { + front := types.NewRealServerFront() + if err := front.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortRsInvalidFrontend() + } + + var rss []*types.RealServerSpec + if params.Rss != nil { + rss = make([]*types.RealServerSpec, len(params.Rss.Items)) + for i, rs := range params.Rss.Items { + var fwdmode types.DpvsFwdMode + fwdmode.FromString(rs.Mode) + rss[i] = types.NewRealServerSpec() + rss[i].SetAf(front.GetAf()) + rss[i].SetAddr(rs.IP) + rss[i].SetPort(rs.Port) + rss[i].SetProto(front.GetProto()) + rss[i].SetWeight(uint32(rs.Weight)) + rss[i].SetFwdMode(fwdmode) + rss[i].SetInhibited(rs.Inhibited) + rss[i].SetOverloaded(rs.Inhibited) + } + } + + healthCheck := false + if params.Healthcheck != nil { + healthCheck = *params.Healthcheck + } + + result := front.Edit(healthCheck, rss, h.connPool, h.logger) + + // h.logger.Info("Set real server sets done.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + switch result { + case types.EDPVS_EXIST, types.EDPVS_OK: + h.logger.Info("Set real server sets success.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPutVsVipPortRsOK() + case types.EDPVS_NOTEXIST: + if healthCheck { + h.logger.Error("Edit not exist real server.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPutVsVipPortRsInvalidFrontend() + } + h.logger.Error("Unreachable branch") + default: + h.logger.Error("Set real server sets failed.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPutVsVipPortRsInvalidBackend() + } + return apiVs.NewPutVsVipPortRsFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go new file mode 100644 index 000000000..91ce6808a --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go @@ -0,0 +1 @@ +package ipvs diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml new file mode 100644 index 000000000..230751c80 --- /dev/null +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -0,0 +1,1373 @@ +swagger: "2.0" +info: + description: "dpvs agent api" + version: "1.0.0" + title: "dpvs agent" +host: "petstore.swagger.io" +basePath: "/v2" +tags: +- name: "virtualserver" + description: "virtualserver" +- name: "route" + description: "route" +- name: "laddr" + description: "laddr" +- name: "tunnel" + description: "tunnel" +- name: "inetaddr" + description: "inet addr" +- name: "white_list" + description: "white list" +- name: "black_list" + description: "black list" +- name: "arp" + description: "arp" +schemes: +- "http" +parameters: + service-id: + name: VipPort + in: path + type: string + required: true + realserver-id: + name: RipPort + in: path + type: string + required: true + device-name: + name: name + in: path + type: string + required: true + vs-config: + name: spec + in: body + schema: + "$ref": "#/definitions/VirtualServerSpecTiny" + rs-config: + name: spec + in: body + schema: + "$ref": "#/definitions/RealServerSpecTiny" + rss-config: + name: rss + in: body + schema: + "$ref": "#/definitions/RealServerTinyList" + acl-config: + name: acl + in: body + schema: + "$ref": "#/definitions/AclAddrList" + laddr-config: + name: spec + in: body + schema: + "$ref": "#/definitions/LocalAddressSpecTiny" + route-config: + name: spec + in: body + schema: + "$ref": "#/definitions/RouteSpec" + vlan-config: + name: spec + in: body + schema: + "$ref": "#/definitions/VlanSpec" + device-addr: + name: spec + in: body + schema: + "$ref": "#/definitions/InetAddrSpec" + healthcheck: + name: healthcheck + in: query + type: boolean + default: false + required: false + stats: + name: stats + in: query + type: boolean + default: false + required: false + verbose: + name: verbose + in: query + type: boolean + default: false + required: false + sapool: + name: sapool + in: query + type: boolean + default: false + required: false + promisc: + name: promisc + in: query + type: string + enum: + - unset + - on + - off + default: unset + required: false + link: + name: link + in: query + type: string + enum: + - unset + - up + - down + default: unset + required: false + forward2kni: + name: forward2Kni + in: query + type: string + enum: + - unset + - on + - off + default: unset + required: false +definitions: + CertAuthSpec: + properties: + addr: + type: string + InetAddrSpec: + properties: + addr: + type: string + broadcast: + type: string + scope: + type: string + VlanSpec: + properties: + name: + type: string + device: + type: string + id: + type: string + RouteSpec: + properties: + src: + type: string + dst: + type: string + gateway: + type: string + prefixSrc: + type: string + device: + type: string + scope: + type: string + mtu: + type: integer + format: uint32 + metric: + type: integer + format: uint32 + LocalAddressSpecExpand: + type: object + properties: + af: + type: integer + format: uint32 + conns: + type: integer + format: uint32 + portConflict: + type: integer + format: uint64 + addr: + type: string + device: + type: string + LocalAddressSpecTiny: + properties: + addr: + type: string + device: + type: string + AclAddrList: + type: object + properties: + Items: + type: array + items: + "$ref": "#/definitions/CertAuthSpec" + LocalAddressExpandList: + properties: + Items: + type: array + items: + "$ref": "#/definitions/LocalAddressSpecExpand" + LocalAddressTinyList: + properties: + Items: + type: array + items: + "$ref": "#/definitions/LocalAddressSpecTiny" + RealServerTinyList: + type: object + properties: + Items: + type: array + items: + "$ref": "#/definitions/RealServerSpecTiny" + RealServerExpandList: + type: "object" + properties: + Items: + type: array + items: + "$ref": "#/definitions/RealServerSpecExpand" + RealServerSpecExpand: + type: object + properties: + Spec: + "$ref": "#/definitions/RealServerSpecTiny" + Stats: + "$ref": "#/definitions/ServerStats" + RealServerSpecTiny: + type: object + properties: + ip: + type: "string" + port: + type: "integer" + format: "uint16" + x-omitempty: false + weight: + type: "integer" + format: "uint16" + x-omitempty: false + mode: + type: "string" + enum: + - "FNAT" + - "SNAT" + - "DR" + - "TUNNEL" + - "NAT" + inhibited: + type: "boolean" + default: false + overloaded: + type: "boolean" + default: false + NicDeviceSpecList: + type: object + properties: + Items: + type: array + items: + "$ref": "#/definitions/NicDeviceSpec" + NicDeviceSpec: + type: object + properties: + detail: + "$ref": "#/definitions/NicDeviceDetail" + stats: + "$ref": "#/definitions/NicDeviceStats" + #extra: + # "$ref": "#/definitions/NicDeviceStats" + #NicDeviceExtra: padding + NicDeviceDetail: + type: object + properties: + name: + type: string + addr: + type: string + status: + type: string + enum: + - "UP" + - "DOWN" + duplex: + type: string + enum: + - "half-duplex" + - "full-duplex" + autoneg: + type: string + enum: + - "fixed-nego" + - "auto-nego" + speed: + type: integer + format: uint32 + nRxQ: + type: integer + format: uint8 + nTxQ: + type: integer + format: uint8 + socketID: + type: integer + format: uint8 + ID: + type: integer + format: uint16 + MTU: + type: integer + format: uint16 + Flags: + type: integer + format: uint16 + NicDeviceStats: + type: object + properties: + id: + type: integer + format: "uint16" + bufAvail: + type: integer + format: "uint32" + bufInuse: + type: integer + format: "uint32" + inPkts: + type: integer + format: "uint64" + outPkts: + type: integer + format: "uint64" + inBytes: + type: integer + format: "uint64" + outBytes: + type: integer + format: "uint64" + inMissed: + type: integer + format: "uint64" + inErrors: + type: integer + format: "uint64" + outErrors: + type: integer + format: "uint64" + rxNoMbuf: + type: integer + format: "uint64" + inPktsQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + outPktsQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + inBytesQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + outBytesQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + errorBytesQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + NicDeviceQueueData: + type: integer + format: "uint64" + Error: + type: "string" + Status: + description: Status of an individual component + type: object + properties: + state: + type: string + description: State the component is in + enum: + - Ok + - Warning + - Failure + - Disabled + msg: + type: string + description: Human readable status/error/warning message + ServerStats: + type: "object" + properties: + Conns: + type: "integer" + format: "uint64" + InPkts: + type: "integer" + format: "uint64" + InBytes: + type: "integer" + format: "uint64" + OutPkts: + type: "integer" + format: "uint64" + OutBytes: + type: "integer" + format: "uint64" + Cps: + type: "integer" + format: "uint32" + InPps: + type: "integer" + format: "uint32" + InBps: + type: "integer" + format: "uint32" + OutPps: + type: "integer" + format: "uint32" + OutBps: + type: "integer" + format: "uint32" + AddrRange: + type: "object" + properties: + Start: + type: "string" + End: + type: "string" + MatchSpec: + type: "object" + properties: + Src: + "$ref": "#/definitions/AddrRange" + Dest: + "$ref": "#/definitions/AddrRange" + InIfName: + type: string + OutIfName: + type: string + DestCheckSpec: + type: "string" + enum: + - passive + - tcp + - udp + - ping + + VirtualServerList: + type: object + properties: + Items: + type: array + items: + "$ref": "#/definitions/VirtualServerSpecExpand" + VirtualServerSpecExpand: + type: "object" + properties: + Af: + type: "integer" + format: "uint32" + Proto: + type: "integer" + format: "uint16" + Port: + type: "integer" + format: "uint16" + Fwmark: + type: "integer" + format: "uint32" + Flags: + type: "string" + SyncProxy: + type: "string" + enum: + - "true" + - "false" + ExpireQuiescent: + type: "string" + enum: + - "true" + - "false" + Timeout: + type: "integer" + format: "uint32" + ConnTimeout: + type: "integer" + format: "uint32" + Netmask: + type: "integer" + format: "uint32" + Bps: + type: "integer" + format: "uint32" + LimitProportion: + type: "integer" + format: "uint32" + Addr: + type: "string" + SchedName: + type: "string" + enum: + - rr + - wrr + - wlc + - connhash + DestCheck: + type: array + items: + "$ref": "#/definitions/DestCheckSpec" + Stats: + "$ref": "#/definitions/ServerStats" + RSs: + "$ref": "#/definitions/RealServerExpandList" + Match: + "$ref": "#/definitions/MatchSpec" + VirtualServerSpecTiny: + type: "object" + properties: + #Af: + # type: "integer" + # format: "uint16" + #Port: + # type: "integer" + # format: "uint16" + Fwmark: + type: "integer" + format: "uint32" + #Flags: + # type: "integer" + # format: "uint32" + SyncProxy: + type: "boolean" + default: false + ExpireQuiescent: + type: "boolean" + default: false + Timeout: + type: "integer" + format: "uint32" + ConnTimeout: + type: "integer" + format: "uint32" + #Netmask: + # type: "integer" + # format: "uint32" + Bps: + type: "integer" + format: "uint32" + LimitProportion: + type: "integer" + format: "uint32" + #Addr: + # type: "string" + SchedName: + type: "string" + enum: + - rr + - wrr + - wlc + - connhash + Match: + "$ref": "#/definitions/MatchSpec" +paths: + /device: + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/stats" + summary: "display all net device list" + responses: + '200': + description: Success + schema: + type: string + /device/{name}/addr: + #description: dpip addr add 192.168.88.16/32 dev dpdk0.102 + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/stats" + - "$ref": "#/parameters/verbose" + - "$ref": "#/parameters/device-name" + summary: "display special net device ip addr" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/sapool" + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/device-addr" + summary: "add/update special net device ip addr" + responses: + '200': + description: Update exist ip addr Success + schema: + type: string + '201': + description: Add new ip addr Success + schema: + type: string + '500': + description: Failed + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/sapool" + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/device-addr" + summary: "delete special net device ip addr" + responses: + '200': + description: delete ip addr from device Success + schema: + type: string + '500': + description: Failed + schema: + type: string + /device/{name}/route: + #description: dpip route add 192.168.88.16/32 dev dpdk0.102 scope kni_host + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/stats" + - "$ref": "#/parameters/device-name" + summary: "display special net device route" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/route-config" + summary: "add/update special net device route" + responses: + '200': + description: Update exist route Success + schema: + type: string + '201': + description: Add new route Success + schema: + type: string + '500': + description: Failed + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/route-config" + summary: "delete special net device route" + responses: + '200': + description: delete route Success + schema: + type: string + '500': + description: Failed + schema: + type: string + /device/{name}/netlink: + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/stats" + summary: "ip link show dev ${name}" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + summary: "ip link set ${name} up" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Not Found + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + summary: "ip link set ${name} down" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Not Found + schema: + type: string + /device/{name}/netlink/addr: + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/stats" + summary: "ip addr show lo: Display special linux net device addr detail" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/device-addr" + summary: "ip addr add 10.0.0.1/32 dev eth0: Set ip cird to linux net device" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Not Found + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/device-addr" + summary: "ip addr del 10.0.0.1/32 dev eth0: Delete ip cird fron linux net device" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Not Found + schema: + type: string + #/device/{name}/cpu + /device/{name}/nic: + #description: dpip link show + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/verbose" + - "$ref": "#/parameters/stats" + summary: "dpip link show ${nic-name} -s -v" + responses: + '200': + description: Success + schema: + #type: string + "$ref": "#/definitions/NicDeviceSpecList" + '500': + description: Failure + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/forward2kni" + - "$ref": "#/parameters/link" + - "$ref": "#/parameters/promisc" + summary: "dpip link set ${nic-name} [forward2kni,link,promisc,tc-ingress,tc-egress] [on/up,off/down]" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Failure + schema: + type: string + /device/{name}/vlan: + #description: dpip vlan add dpdk0.102 link dpdk0 id 102 + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/stats" + summary: "display all net device list" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/vlan-config" + summary: "add/update special net device " + responses: + '200': + description: Success + schema: + type: string + '500': + description: Failed + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + summary: "delete special net device" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Failed + schema: + type: string + /vs: + get: + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/stats" + summary: "display all vip:port:proto and rsip:port list" + responses: + '200': + description: Success + schema: + "$ref": "#/definitions/VirtualServerList" + # items: + # "$ref": "#/definitions/VirtualServer" + /vs/{VipPort}: + get: + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/stats" + summary: "get a specific virtual server" + responses: + '200': + description: Success + schema: + # type: string + # items: + "$ref": "#/definitions/VirtualServerList" + '404': + description: Service not found + schema: + type: string + delete: + summary: "Delete a vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Service not found + schema: + type: string + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + put: + summary: "create or update virtual server" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/vs-config" + responses: + '200': + description: Updated + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: "Error while creating virtual server" + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + /vs/{VipPort}/laddr: + get: + tags: + - "virtualserver" + parameters: + #- "$ref": "#/parameters/realserver-id" + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/stats" + responses: + '200': + description: Success + schema: + "$ref": "#/definitions/LocalAddressExpandList" + #type: string + #items: + # "$ref": "#/definitions/VirtualServer" + '404': + description: Service not found + schema: + type: string + put: + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/laddr-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: "Error while creating virtual server" + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + delete: + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/laddr-config" + responses: + '200': + description: Success + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: "Error while creating virtual server" + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + /vs/{VipPort}/rs: + get: + tags: + - "virtualserver" + parameters: + #- "$ref": "#/parameters/realserver-id" + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/stats" + responses: + '200': + description: Success + schema: + type: string + #items: + # "$ref": "#/definitions/VirtualServer" + '404': + description: Service not found + schema: + type: string + delete: + summary: "Delete a set of real server from vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/rss-config" + responses: + '200': + description: Success + '404': + description: Service not found + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + put: + summary: "Add a set of real server to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/rss-config" + - "$ref": "#/parameters/healthcheck" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + post: + summary: "Update fully real server list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/rss-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + /vs/{VipPort}/deny: + get: + tags: + - "virtualserver" + parameters: + #- "$ref": "#/parameters/realserver-id" + - "$ref": "#/parameters/service-id" + responses: + '200': + description: Success + schema: + type: string + #items: + # "$ref": "#/definitions/VirtualServer" + '404': + description: Service not found + schema: + type: string + delete: + summary: "Delete a set of ip form black list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + '404': + description: Service not found + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + put: + summary: "Add a set of ip from black list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + post: + summary: "Update a fully black ip list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + /vs/{VipPort}/allow: + get: + tags: + - "virtualserver" + parameters: + #- "$ref": "#/parameters/realserver-id" + - "$ref": "#/parameters/service-id" + responses: + '200': + description: Success + schema: + type: string + #items: + # "$ref": "#/definitions/VirtualServer" + '404': + description: Service not found + schema: + type: string + delete: + summary: "Delete a set of ip form white list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + '404': + description: Service not found + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + put: + summary: "Add a set of ip from white list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + post: + summary: "Update a fully white ip list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" diff --git a/tools/dpvs-agent/go.mod b/tools/dpvs-agent/go.mod new file mode 100644 index 000000000..b5198bfc6 --- /dev/null +++ b/tools/dpvs-agent/go.mod @@ -0,0 +1,40 @@ +module github.com/dpvs-agent + +go 1.20 + +require ( + github.com/go-openapi/errors v0.20.3 + github.com/go-openapi/loads v0.21.2 + github.com/go-openapi/runtime v0.26.0 + github.com/go-openapi/spec v0.20.9 + github.com/go-openapi/strfmt v0.21.7 + github.com/go-openapi/swag v0.22.3 + github.com/go-openapi/validate v0.22.1 + github.com/hashicorp/go-hclog v1.5.0 + github.com/jessevdk/go-flags v1.5.0 + github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible + github.com/vishvananda/netlink v1.1.0 + golang.org/x/net v0.10.0 + golang.org/x/sys v0.8.0 +) + +require ( + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/go-openapi/analysis v0.21.4 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/jonboulle/clockwork v0.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/lestrrat-go/strftime v1.0.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/oklog/ulid v1.3.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect + go.mongodb.org/mongo-driver v1.11.3 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/tools/dpvs-agent/go.sum b/tools/dpvs-agent/go.sum new file mode 100644 index 000000000..f6f0a32b6 --- /dev/null +++ b/tools/dpvs-agent/go.sum @@ -0,0 +1,232 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= +github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= +github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= +github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= +github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= +github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= +github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= +github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc= +github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= +github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= +github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= +github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= +github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k= +github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= +github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= +github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= +github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= +go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= +go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= +go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y= +go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/dpvs-agent/models/acl_addr_list.go b/tools/dpvs-agent/models/acl_addr_list.go new file mode 100644 index 000000000..06f092792 --- /dev/null +++ b/tools/dpvs-agent/models/acl_addr_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// ACLAddrList Acl addr list +// +// swagger:model AclAddrList +type ACLAddrList struct { + + // items + Items []*CertAuthSpec `json:"Items"` +} + +// Validate validates this Acl addr list +func (m *ACLAddrList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *ACLAddrList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this Acl addr list based on the context it is used +func (m *ACLAddrList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *ACLAddrList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *ACLAddrList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ACLAddrList) UnmarshalBinary(b []byte) error { + var res ACLAddrList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/addr_range.go b/tools/dpvs-agent/models/addr_range.go new file mode 100644 index 000000000..4324dde7a --- /dev/null +++ b/tools/dpvs-agent/models/addr_range.go @@ -0,0 +1,53 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// AddrRange addr range +// +// swagger:model AddrRange +type AddrRange struct { + + // end + End string `json:"End,omitempty"` + + // start + Start string `json:"Start,omitempty"` +} + +// Validate validates this addr range +func (m *AddrRange) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this addr range based on context it is used +func (m *AddrRange) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *AddrRange) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *AddrRange) UnmarshalBinary(b []byte) error { + var res AddrRange + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/cert_auth_spec.go b/tools/dpvs-agent/models/cert_auth_spec.go new file mode 100644 index 000000000..61648012e --- /dev/null +++ b/tools/dpvs-agent/models/cert_auth_spec.go @@ -0,0 +1,50 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// CertAuthSpec cert auth spec +// +// swagger:model CertAuthSpec +type CertAuthSpec struct { + + // addr + Addr string `json:"addr,omitempty"` +} + +// Validate validates this cert auth spec +func (m *CertAuthSpec) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this cert auth spec based on context it is used +func (m *CertAuthSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *CertAuthSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *CertAuthSpec) UnmarshalBinary(b []byte) error { + var res CertAuthSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/dest_check_spec.go b/tools/dpvs-agent/models/dest_check_spec.go new file mode 100644 index 000000000..2e2e9cf9a --- /dev/null +++ b/tools/dpvs-agent/models/dest_check_spec.go @@ -0,0 +1,84 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// DestCheckSpec dest check spec +// +// swagger:model DestCheckSpec +type DestCheckSpec string + +func NewDestCheckSpec(value DestCheckSpec) *DestCheckSpec { + return &value +} + +// Pointer returns a pointer to a freshly-allocated DestCheckSpec. +func (m DestCheckSpec) Pointer() *DestCheckSpec { + return &m +} + +const ( + + // DestCheckSpecPassive captures enum value "passive" + DestCheckSpecPassive DestCheckSpec = "passive" + + // DestCheckSpecTCP captures enum value "tcp" + DestCheckSpecTCP DestCheckSpec = "tcp" + + // DestCheckSpecUDP captures enum value "udp" + DestCheckSpecUDP DestCheckSpec = "udp" + + // DestCheckSpecPing captures enum value "ping" + DestCheckSpecPing DestCheckSpec = "ping" +) + +// for schema +var destCheckSpecEnum []interface{} + +func init() { + var res []DestCheckSpec + if err := json.Unmarshal([]byte(`["passive","tcp","udp","ping"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + destCheckSpecEnum = append(destCheckSpecEnum, v) + } +} + +func (m DestCheckSpec) validateDestCheckSpecEnum(path, location string, value DestCheckSpec) error { + if err := validate.EnumCase(path, location, value, destCheckSpecEnum, true); err != nil { + return err + } + return nil +} + +// Validate validates this dest check spec +func (m DestCheckSpec) Validate(formats strfmt.Registry) error { + var res []error + + // value enum + if err := m.validateDestCheckSpecEnum("", "body", m); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// ContextValidate validates this dest check spec based on context it is used +func (m DestCheckSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} diff --git a/tools/dpvs-agent/models/error.go b/tools/dpvs-agent/models/error.go new file mode 100644 index 000000000..f0f02dcac --- /dev/null +++ b/tools/dpvs-agent/models/error.go @@ -0,0 +1,27 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" +) + +// Error error +// +// swagger:model Error +type Error string + +// Validate validates this error +func (m Error) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this error based on context it is used +func (m Error) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} diff --git a/tools/dpvs-agent/models/inet_addr_spec.go b/tools/dpvs-agent/models/inet_addr_spec.go new file mode 100644 index 000000000..9a4e53e75 --- /dev/null +++ b/tools/dpvs-agent/models/inet_addr_spec.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// InetAddrSpec inet addr spec +// +// swagger:model InetAddrSpec +type InetAddrSpec struct { + + // addr + Addr string `json:"addr,omitempty"` + + // broadcast + Broadcast string `json:"broadcast,omitempty"` + + // scope + Scope string `json:"scope,omitempty"` +} + +// Validate validates this inet addr spec +func (m *InetAddrSpec) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this inet addr spec based on context it is used +func (m *InetAddrSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *InetAddrSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *InetAddrSpec) UnmarshalBinary(b []byte) error { + var res InetAddrSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/local_address_expand_list.go b/tools/dpvs-agent/models/local_address_expand_list.go new file mode 100644 index 000000000..c4e52dca9 --- /dev/null +++ b/tools/dpvs-agent/models/local_address_expand_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// LocalAddressExpandList local address expand list +// +// swagger:model LocalAddressExpandList +type LocalAddressExpandList struct { + + // items + Items []*LocalAddressSpecExpand `json:"Items"` +} + +// Validate validates this local address expand list +func (m *LocalAddressExpandList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LocalAddressExpandList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this local address expand list based on the context it is used +func (m *LocalAddressExpandList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LocalAddressExpandList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *LocalAddressExpandList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LocalAddressExpandList) UnmarshalBinary(b []byte) error { + var res LocalAddressExpandList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/local_address_spec_expand.go b/tools/dpvs-agent/models/local_address_spec_expand.go new file mode 100644 index 000000000..0b25fb723 --- /dev/null +++ b/tools/dpvs-agent/models/local_address_spec_expand.go @@ -0,0 +1,62 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// LocalAddressSpecExpand local address spec expand +// +// swagger:model LocalAddressSpecExpand +type LocalAddressSpecExpand struct { + + // addr + Addr string `json:"addr,omitempty"` + + // af + Af uint32 `json:"af,omitempty"` + + // conns + Conns uint32 `json:"conns,omitempty"` + + // device + Device string `json:"device,omitempty"` + + // port conflict + PortConflict uint64 `json:"portConflict,omitempty"` +} + +// Validate validates this local address spec expand +func (m *LocalAddressSpecExpand) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this local address spec expand based on context it is used +func (m *LocalAddressSpecExpand) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *LocalAddressSpecExpand) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LocalAddressSpecExpand) UnmarshalBinary(b []byte) error { + var res LocalAddressSpecExpand + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/local_address_spec_tiny.go b/tools/dpvs-agent/models/local_address_spec_tiny.go new file mode 100644 index 000000000..79806b25e --- /dev/null +++ b/tools/dpvs-agent/models/local_address_spec_tiny.go @@ -0,0 +1,53 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// LocalAddressSpecTiny local address spec tiny +// +// swagger:model LocalAddressSpecTiny +type LocalAddressSpecTiny struct { + + // addr + Addr string `json:"addr,omitempty"` + + // device + Device string `json:"device,omitempty"` +} + +// Validate validates this local address spec tiny +func (m *LocalAddressSpecTiny) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this local address spec tiny based on context it is used +func (m *LocalAddressSpecTiny) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *LocalAddressSpecTiny) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LocalAddressSpecTiny) UnmarshalBinary(b []byte) error { + var res LocalAddressSpecTiny + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/local_address_tiny_list.go b/tools/dpvs-agent/models/local_address_tiny_list.go new file mode 100644 index 000000000..3c04085a4 --- /dev/null +++ b/tools/dpvs-agent/models/local_address_tiny_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// LocalAddressTinyList local address tiny list +// +// swagger:model LocalAddressTinyList +type LocalAddressTinyList struct { + + // items + Items []*LocalAddressSpecTiny `json:"Items"` +} + +// Validate validates this local address tiny list +func (m *LocalAddressTinyList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LocalAddressTinyList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this local address tiny list based on the context it is used +func (m *LocalAddressTinyList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LocalAddressTinyList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *LocalAddressTinyList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LocalAddressTinyList) UnmarshalBinary(b []byte) error { + var res LocalAddressTinyList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/match_spec.go b/tools/dpvs-agent/models/match_spec.go new file mode 100644 index 000000000..8d78ed4ca --- /dev/null +++ b/tools/dpvs-agent/models/match_spec.go @@ -0,0 +1,156 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// MatchSpec match spec +// +// swagger:model MatchSpec +type MatchSpec struct { + + // dest + Dest *AddrRange `json:"Dest,omitempty"` + + // in if name + InIfName string `json:"InIfName,omitempty"` + + // out if name + OutIfName string `json:"OutIfName,omitempty"` + + // src + Src *AddrRange `json:"Src,omitempty"` +} + +// Validate validates this match spec +func (m *MatchSpec) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateDest(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSrc(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *MatchSpec) validateDest(formats strfmt.Registry) error { + if swag.IsZero(m.Dest) { // not required + return nil + } + + if m.Dest != nil { + if err := m.Dest.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Dest") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Dest") + } + return err + } + } + + return nil +} + +func (m *MatchSpec) validateSrc(formats strfmt.Registry) error { + if swag.IsZero(m.Src) { // not required + return nil + } + + if m.Src != nil { + if err := m.Src.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Src") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Src") + } + return err + } + } + + return nil +} + +// ContextValidate validate this match spec based on the context it is used +func (m *MatchSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateDest(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateSrc(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *MatchSpec) contextValidateDest(ctx context.Context, formats strfmt.Registry) error { + + if m.Dest != nil { + if err := m.Dest.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Dest") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Dest") + } + return err + } + } + + return nil +} + +func (m *MatchSpec) contextValidateSrc(ctx context.Context, formats strfmt.Registry) error { + + if m.Src != nil { + if err := m.Src.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Src") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Src") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *MatchSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *MatchSpec) UnmarshalBinary(b []byte) error { + var res MatchSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_detail.go b/tools/dpvs-agent/models/nic_device_detail.go new file mode 100644 index 000000000..ee0a65216 --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_detail.go @@ -0,0 +1,232 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// NicDeviceDetail nic device detail +// +// swagger:model NicDeviceDetail +type NicDeviceDetail struct { + + // flags + Flags uint16 `json:"Flags,omitempty"` + + // ID + ID uint16 `json:"ID,omitempty"` + + // m t u + MTU uint16 `json:"MTU,omitempty"` + + // addr + Addr string `json:"addr,omitempty"` + + // autoneg + // Enum: [fixed-nego auto-nego] + Autoneg string `json:"autoneg,omitempty"` + + // duplex + // Enum: [half-duplex full-duplex] + Duplex string `json:"duplex,omitempty"` + + // n rx q + NRxQ uint8 `json:"nRxQ,omitempty"` + + // n tx q + NTxQ uint8 `json:"nTxQ,omitempty"` + + // name + Name string `json:"name,omitempty"` + + // socket ID + SocketID uint8 `json:"socketID,omitempty"` + + // speed + Speed uint32 `json:"speed,omitempty"` + + // status + // Enum: [UP DOWN] + Status string `json:"status,omitempty"` +} + +// Validate validates this nic device detail +func (m *NicDeviceDetail) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateAutoneg(formats); err != nil { + res = append(res, err) + } + + if err := m.validateDuplex(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStatus(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var nicDeviceDetailTypeAutonegPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["fixed-nego","auto-nego"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + nicDeviceDetailTypeAutonegPropEnum = append(nicDeviceDetailTypeAutonegPropEnum, v) + } +} + +const ( + + // NicDeviceDetailAutonegFixedDashNego captures enum value "fixed-nego" + NicDeviceDetailAutonegFixedDashNego string = "fixed-nego" + + // NicDeviceDetailAutonegAutoDashNego captures enum value "auto-nego" + NicDeviceDetailAutonegAutoDashNego string = "auto-nego" +) + +// prop value enum +func (m *NicDeviceDetail) validateAutonegEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, nicDeviceDetailTypeAutonegPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *NicDeviceDetail) validateAutoneg(formats strfmt.Registry) error { + if swag.IsZero(m.Autoneg) { // not required + return nil + } + + // value enum + if err := m.validateAutonegEnum("autoneg", "body", m.Autoneg); err != nil { + return err + } + + return nil +} + +var nicDeviceDetailTypeDuplexPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["half-duplex","full-duplex"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + nicDeviceDetailTypeDuplexPropEnum = append(nicDeviceDetailTypeDuplexPropEnum, v) + } +} + +const ( + + // NicDeviceDetailDuplexHalfDashDuplex captures enum value "half-duplex" + NicDeviceDetailDuplexHalfDashDuplex string = "half-duplex" + + // NicDeviceDetailDuplexFullDashDuplex captures enum value "full-duplex" + NicDeviceDetailDuplexFullDashDuplex string = "full-duplex" +) + +// prop value enum +func (m *NicDeviceDetail) validateDuplexEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, nicDeviceDetailTypeDuplexPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *NicDeviceDetail) validateDuplex(formats strfmt.Registry) error { + if swag.IsZero(m.Duplex) { // not required + return nil + } + + // value enum + if err := m.validateDuplexEnum("duplex", "body", m.Duplex); err != nil { + return err + } + + return nil +} + +var nicDeviceDetailTypeStatusPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["UP","DOWN"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + nicDeviceDetailTypeStatusPropEnum = append(nicDeviceDetailTypeStatusPropEnum, v) + } +} + +const ( + + // NicDeviceDetailStatusUP captures enum value "UP" + NicDeviceDetailStatusUP string = "UP" + + // NicDeviceDetailStatusDOWN captures enum value "DOWN" + NicDeviceDetailStatusDOWN string = "DOWN" +) + +// prop value enum +func (m *NicDeviceDetail) validateStatusEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, nicDeviceDetailTypeStatusPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *NicDeviceDetail) validateStatus(formats strfmt.Registry) error { + if swag.IsZero(m.Status) { // not required + return nil + } + + // value enum + if err := m.validateStatusEnum("status", "body", m.Status); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this nic device detail based on context it is used +func (m *NicDeviceDetail) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *NicDeviceDetail) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NicDeviceDetail) UnmarshalBinary(b []byte) error { + var res NicDeviceDetail + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_queue_data.go b/tools/dpvs-agent/models/nic_device_queue_data.go new file mode 100644 index 000000000..ac8deb299 --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_queue_data.go @@ -0,0 +1,27 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" +) + +// NicDeviceQueueData nic device queue data +// +// swagger:model NicDeviceQueueData +type NicDeviceQueueData uint64 + +// Validate validates this nic device queue data +func (m NicDeviceQueueData) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this nic device queue data based on context it is used +func (m NicDeviceQueueData) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_spec.go b/tools/dpvs-agent/models/nic_device_spec.go new file mode 100644 index 000000000..ee30a33d5 --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_spec.go @@ -0,0 +1,150 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NicDeviceSpec nic device spec +// +// swagger:model NicDeviceSpec +type NicDeviceSpec struct { + + // detail + Detail *NicDeviceDetail `json:"detail,omitempty"` + + // stats + Stats *NicDeviceStats `json:"stats,omitempty"` +} + +// Validate validates this nic device spec +func (m *NicDeviceSpec) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateDetail(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStats(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceSpec) validateDetail(formats strfmt.Registry) error { + if swag.IsZero(m.Detail) { // not required + return nil + } + + if m.Detail != nil { + if err := m.Detail.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("detail") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("detail") + } + return err + } + } + + return nil +} + +func (m *NicDeviceSpec) validateStats(formats strfmt.Registry) error { + if swag.IsZero(m.Stats) { // not required + return nil + } + + if m.Stats != nil { + if err := m.Stats.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("stats") + } + return err + } + } + + return nil +} + +// ContextValidate validate this nic device spec based on the context it is used +func (m *NicDeviceSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateDetail(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateStats(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceSpec) contextValidateDetail(ctx context.Context, formats strfmt.Registry) error { + + if m.Detail != nil { + if err := m.Detail.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("detail") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("detail") + } + return err + } + } + + return nil +} + +func (m *NicDeviceSpec) contextValidateStats(ctx context.Context, formats strfmt.Registry) error { + + if m.Stats != nil { + if err := m.Stats.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("stats") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *NicDeviceSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NicDeviceSpec) UnmarshalBinary(b []byte) error { + var res NicDeviceSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_spec_list.go b/tools/dpvs-agent/models/nic_device_spec_list.go new file mode 100644 index 000000000..47ed4981f --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_spec_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NicDeviceSpecList nic device spec list +// +// swagger:model NicDeviceSpecList +type NicDeviceSpecList struct { + + // items + Items []*NicDeviceSpec `json:"Items"` +} + +// Validate validates this nic device spec list +func (m *NicDeviceSpecList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceSpecList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this nic device spec list based on the context it is used +func (m *NicDeviceSpecList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceSpecList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *NicDeviceSpecList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NicDeviceSpecList) UnmarshalBinary(b []byte) error { + var res NicDeviceSpecList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_stats.go b/tools/dpvs-agent/models/nic_device_stats.go new file mode 100644 index 000000000..27e518db6 --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_stats.go @@ -0,0 +1,342 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NicDeviceStats nic device stats +// +// swagger:model NicDeviceStats +type NicDeviceStats struct { + + // buf avail + BufAvail uint32 `json:"bufAvail,omitempty"` + + // buf inuse + BufInuse uint32 `json:"bufInuse,omitempty"` + + // error bytes q + ErrorBytesQ []NicDeviceQueueData `json:"errorBytesQ"` + + // id + ID uint16 `json:"id,omitempty"` + + // in bytes + InBytes uint64 `json:"inBytes,omitempty"` + + // in bytes q + InBytesQ []NicDeviceQueueData `json:"inBytesQ"` + + // in errors + InErrors uint64 `json:"inErrors,omitempty"` + + // in missed + InMissed uint64 `json:"inMissed,omitempty"` + + // in pkts + InPkts uint64 `json:"inPkts,omitempty"` + + // in pkts q + InPktsQ []NicDeviceQueueData `json:"inPktsQ"` + + // out bytes + OutBytes uint64 `json:"outBytes,omitempty"` + + // out bytes q + OutBytesQ []NicDeviceQueueData `json:"outBytesQ"` + + // out errors + OutErrors uint64 `json:"outErrors,omitempty"` + + // out pkts + OutPkts uint64 `json:"outPkts,omitempty"` + + // out pkts q + OutPktsQ []NicDeviceQueueData `json:"outPktsQ"` + + // rx no mbuf + RxNoMbuf uint64 `json:"rxNoMbuf,omitempty"` +} + +// Validate validates this nic device stats +func (m *NicDeviceStats) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateErrorBytesQ(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInBytesQ(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInPktsQ(formats); err != nil { + res = append(res, err) + } + + if err := m.validateOutBytesQ(formats); err != nil { + res = append(res, err) + } + + if err := m.validateOutPktsQ(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceStats) validateErrorBytesQ(formats strfmt.Registry) error { + if swag.IsZero(m.ErrorBytesQ) { // not required + return nil + } + + for i := 0; i < len(m.ErrorBytesQ); i++ { + + if err := m.ErrorBytesQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("errorBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("errorBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) validateInBytesQ(formats strfmt.Registry) error { + if swag.IsZero(m.InBytesQ) { // not required + return nil + } + + for i := 0; i < len(m.InBytesQ); i++ { + + if err := m.InBytesQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("inBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("inBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) validateInPktsQ(formats strfmt.Registry) error { + if swag.IsZero(m.InPktsQ) { // not required + return nil + } + + for i := 0; i < len(m.InPktsQ); i++ { + + if err := m.InPktsQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("inPktsQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("inPktsQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) validateOutBytesQ(formats strfmt.Registry) error { + if swag.IsZero(m.OutBytesQ) { // not required + return nil + } + + for i := 0; i < len(m.OutBytesQ); i++ { + + if err := m.OutBytesQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("outBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("outBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) validateOutPktsQ(formats strfmt.Registry) error { + if swag.IsZero(m.OutPktsQ) { // not required + return nil + } + + for i := 0; i < len(m.OutPktsQ); i++ { + + if err := m.OutPktsQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("outPktsQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("outPktsQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +// ContextValidate validate this nic device stats based on the context it is used +func (m *NicDeviceStats) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateErrorBytesQ(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateInBytesQ(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateInPktsQ(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateOutBytesQ(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateOutPktsQ(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceStats) contextValidateErrorBytesQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.ErrorBytesQ); i++ { + + if err := m.ErrorBytesQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("errorBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("errorBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) contextValidateInBytesQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.InBytesQ); i++ { + + if err := m.InBytesQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("inBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("inBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) contextValidateInPktsQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.InPktsQ); i++ { + + if err := m.InPktsQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("inPktsQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("inPktsQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) contextValidateOutBytesQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.OutBytesQ); i++ { + + if err := m.OutBytesQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("outBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("outBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) contextValidateOutPktsQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.OutPktsQ); i++ { + + if err := m.OutPktsQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("outPktsQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("outPktsQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *NicDeviceStats) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NicDeviceStats) UnmarshalBinary(b []byte) error { + var res NicDeviceStats + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/real_server_expand_list.go b/tools/dpvs-agent/models/real_server_expand_list.go new file mode 100644 index 000000000..4593c3b21 --- /dev/null +++ b/tools/dpvs-agent/models/real_server_expand_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// RealServerExpandList real server expand list +// +// swagger:model RealServerExpandList +type RealServerExpandList struct { + + // items + Items []*RealServerSpecExpand `json:"Items"` +} + +// Validate validates this real server expand list +func (m *RealServerExpandList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerExpandList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this real server expand list based on the context it is used +func (m *RealServerExpandList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerExpandList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *RealServerExpandList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RealServerExpandList) UnmarshalBinary(b []byte) error { + var res RealServerExpandList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/real_server_spec_expand.go b/tools/dpvs-agent/models/real_server_spec_expand.go new file mode 100644 index 000000000..ba2a517db --- /dev/null +++ b/tools/dpvs-agent/models/real_server_spec_expand.go @@ -0,0 +1,150 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// RealServerSpecExpand real server spec expand +// +// swagger:model RealServerSpecExpand +type RealServerSpecExpand struct { + + // spec + Spec *RealServerSpecTiny `json:"Spec,omitempty"` + + // stats + Stats *ServerStats `json:"Stats,omitempty"` +} + +// Validate validates this real server spec expand +func (m *RealServerSpecExpand) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateSpec(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStats(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerSpecExpand) validateSpec(formats strfmt.Registry) error { + if swag.IsZero(m.Spec) { // not required + return nil + } + + if m.Spec != nil { + if err := m.Spec.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Spec") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Spec") + } + return err + } + } + + return nil +} + +func (m *RealServerSpecExpand) validateStats(formats strfmt.Registry) error { + if swag.IsZero(m.Stats) { // not required + return nil + } + + if m.Stats != nil { + if err := m.Stats.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Stats") + } + return err + } + } + + return nil +} + +// ContextValidate validate this real server spec expand based on the context it is used +func (m *RealServerSpecExpand) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateSpec(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateStats(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerSpecExpand) contextValidateSpec(ctx context.Context, formats strfmt.Registry) error { + + if m.Spec != nil { + if err := m.Spec.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Spec") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Spec") + } + return err + } + } + + return nil +} + +func (m *RealServerSpecExpand) contextValidateStats(ctx context.Context, formats strfmt.Registry) error { + + if m.Stats != nil { + if err := m.Stats.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Stats") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *RealServerSpecExpand) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RealServerSpecExpand) UnmarshalBinary(b []byte) error { + var res RealServerSpecExpand + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/real_server_spec_tiny.go b/tools/dpvs-agent/models/real_server_spec_tiny.go new file mode 100644 index 000000000..592c97d95 --- /dev/null +++ b/tools/dpvs-agent/models/real_server_spec_tiny.go @@ -0,0 +1,129 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// RealServerSpecTiny real server spec tiny +// +// swagger:model RealServerSpecTiny +type RealServerSpecTiny struct { + + // inhibited + Inhibited *bool `json:"inhibited,omitempty"` + + // ip + IP string `json:"ip,omitempty"` + + // mode + // Enum: [FNAT SNAT DR TUNNEL NAT] + Mode string `json:"mode,omitempty"` + + // overloaded + Overloaded *bool `json:"overloaded,omitempty"` + + // port + Port uint16 `json:"port"` + + // weight + Weight uint16 `json:"weight"` +} + +// Validate validates this real server spec tiny +func (m *RealServerSpecTiny) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateMode(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var realServerSpecTinyTypeModePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["FNAT","SNAT","DR","TUNNEL","NAT"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + realServerSpecTinyTypeModePropEnum = append(realServerSpecTinyTypeModePropEnum, v) + } +} + +const ( + + // RealServerSpecTinyModeFNAT captures enum value "FNAT" + RealServerSpecTinyModeFNAT string = "FNAT" + + // RealServerSpecTinyModeSNAT captures enum value "SNAT" + RealServerSpecTinyModeSNAT string = "SNAT" + + // RealServerSpecTinyModeDR captures enum value "DR" + RealServerSpecTinyModeDR string = "DR" + + // RealServerSpecTinyModeTUNNEL captures enum value "TUNNEL" + RealServerSpecTinyModeTUNNEL string = "TUNNEL" + + // RealServerSpecTinyModeNAT captures enum value "NAT" + RealServerSpecTinyModeNAT string = "NAT" +) + +// prop value enum +func (m *RealServerSpecTiny) validateModeEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, realServerSpecTinyTypeModePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *RealServerSpecTiny) validateMode(formats strfmt.Registry) error { + if swag.IsZero(m.Mode) { // not required + return nil + } + + // value enum + if err := m.validateModeEnum("mode", "body", m.Mode); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this real server spec tiny based on context it is used +func (m *RealServerSpecTiny) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *RealServerSpecTiny) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RealServerSpecTiny) UnmarshalBinary(b []byte) error { + var res RealServerSpecTiny + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/real_server_tiny_list.go b/tools/dpvs-agent/models/real_server_tiny_list.go new file mode 100644 index 000000000..3d6780b77 --- /dev/null +++ b/tools/dpvs-agent/models/real_server_tiny_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// RealServerTinyList real server tiny list +// +// swagger:model RealServerTinyList +type RealServerTinyList struct { + + // items + Items []*RealServerSpecTiny `json:"Items"` +} + +// Validate validates this real server tiny list +func (m *RealServerTinyList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerTinyList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this real server tiny list based on the context it is used +func (m *RealServerTinyList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerTinyList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *RealServerTinyList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RealServerTinyList) UnmarshalBinary(b []byte) error { + var res RealServerTinyList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/route_spec.go b/tools/dpvs-agent/models/route_spec.go new file mode 100644 index 000000000..2a7b401b1 --- /dev/null +++ b/tools/dpvs-agent/models/route_spec.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// RouteSpec route spec +// +// swagger:model RouteSpec +type RouteSpec struct { + + // device + Device string `json:"device,omitempty"` + + // dst + Dst string `json:"dst,omitempty"` + + // gateway + Gateway string `json:"gateway,omitempty"` + + // metric + Metric uint32 `json:"metric,omitempty"` + + // mtu + Mtu uint32 `json:"mtu,omitempty"` + + // prefix src + PrefixSrc string `json:"prefixSrc,omitempty"` + + // scope + Scope string `json:"scope,omitempty"` + + // src + Src string `json:"src,omitempty"` +} + +// Validate validates this route spec +func (m *RouteSpec) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this route spec based on context it is used +func (m *RouteSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *RouteSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RouteSpec) UnmarshalBinary(b []byte) error { + var res RouteSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/server_stats.go b/tools/dpvs-agent/models/server_stats.go new file mode 100644 index 000000000..e2ba38b74 --- /dev/null +++ b/tools/dpvs-agent/models/server_stats.go @@ -0,0 +1,77 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// ServerStats server stats +// +// swagger:model ServerStats +type ServerStats struct { + + // conns + Conns uint64 `json:"Conns,omitempty"` + + // cps + Cps uint32 `json:"Cps,omitempty"` + + // in bps + InBps uint32 `json:"InBps,omitempty"` + + // in bytes + InBytes uint64 `json:"InBytes,omitempty"` + + // in pkts + InPkts uint64 `json:"InPkts,omitempty"` + + // in pps + InPps uint32 `json:"InPps,omitempty"` + + // out bps + OutBps uint32 `json:"OutBps,omitempty"` + + // out bytes + OutBytes uint64 `json:"OutBytes,omitempty"` + + // out pkts + OutPkts uint64 `json:"OutPkts,omitempty"` + + // out pps + OutPps uint32 `json:"OutPps,omitempty"` +} + +// Validate validates this server stats +func (m *ServerStats) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this server stats based on context it is used +func (m *ServerStats) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *ServerStats) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ServerStats) UnmarshalBinary(b []byte) error { + var res ServerStats + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/status.go b/tools/dpvs-agent/models/status.go new file mode 100644 index 000000000..4b4f3a97d --- /dev/null +++ b/tools/dpvs-agent/models/status.go @@ -0,0 +1,114 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// Status Status of an individual component +// +// swagger:model Status +type Status struct { + + // Human readable status/error/warning message + Msg string `json:"msg,omitempty"` + + // State the component is in + // Enum: [Ok Warning Failure Disabled] + State string `json:"state,omitempty"` +} + +// Validate validates this status +func (m *Status) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateState(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var statusTypeStatePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["Ok","Warning","Failure","Disabled"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + statusTypeStatePropEnum = append(statusTypeStatePropEnum, v) + } +} + +const ( + + // StatusStateOk captures enum value "Ok" + StatusStateOk string = "Ok" + + // StatusStateWarning captures enum value "Warning" + StatusStateWarning string = "Warning" + + // StatusStateFailure captures enum value "Failure" + StatusStateFailure string = "Failure" + + // StatusStateDisabled captures enum value "Disabled" + StatusStateDisabled string = "Disabled" +) + +// prop value enum +func (m *Status) validateStateEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, statusTypeStatePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *Status) validateState(formats strfmt.Registry) error { + if swag.IsZero(m.State) { // not required + return nil + } + + // value enum + if err := m.validateStateEnum("state", "body", m.State); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this status based on context it is used +func (m *Status) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *Status) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *Status) UnmarshalBinary(b []byte) error { + var res Status + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/virtual_server_list.go b/tools/dpvs-agent/models/virtual_server_list.go new file mode 100644 index 000000000..1880596b5 --- /dev/null +++ b/tools/dpvs-agent/models/virtual_server_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// VirtualServerList virtual server list +// +// swagger:model VirtualServerList +type VirtualServerList struct { + + // items + Items []*VirtualServerSpecExpand `json:"Items"` +} + +// Validate validates this virtual server list +func (m *VirtualServerList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this virtual server list based on the context it is used +func (m *VirtualServerList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *VirtualServerList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *VirtualServerList) UnmarshalBinary(b []byte) error { + var res VirtualServerList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/virtual_server_spec_expand.go b/tools/dpvs-agent/models/virtual_server_spec_expand.go new file mode 100644 index 000000000..dd887a72d --- /dev/null +++ b/tools/dpvs-agent/models/virtual_server_spec_expand.go @@ -0,0 +1,438 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// VirtualServerSpecExpand virtual server spec expand +// +// swagger:model VirtualServerSpecExpand +type VirtualServerSpecExpand struct { + + // addr + Addr string `json:"Addr,omitempty"` + + // af + Af uint32 `json:"Af,omitempty"` + + // bps + Bps uint32 `json:"Bps,omitempty"` + + // conn timeout + ConnTimeout uint32 `json:"ConnTimeout,omitempty"` + + // dest check + DestCheck []DestCheckSpec `json:"DestCheck"` + + // expire quiescent + // Enum: [true false] + ExpireQuiescent string `json:"ExpireQuiescent,omitempty"` + + // flags + Flags string `json:"Flags,omitempty"` + + // fwmark + Fwmark uint32 `json:"Fwmark,omitempty"` + + // limit proportion + LimitProportion uint32 `json:"LimitProportion,omitempty"` + + // match + Match *MatchSpec `json:"Match,omitempty"` + + // netmask + Netmask uint32 `json:"Netmask,omitempty"` + + // port + Port uint16 `json:"Port,omitempty"` + + // proto + Proto uint16 `json:"Proto,omitempty"` + + // r ss + RSs *RealServerExpandList `json:"RSs,omitempty"` + + // sched name + // Enum: [rr wrr wlc connhash] + SchedName string `json:"SchedName,omitempty"` + + // stats + Stats *ServerStats `json:"Stats,omitempty"` + + // sync proxy + // Enum: [true false] + SyncProxy string `json:"SyncProxy,omitempty"` + + // timeout + Timeout uint32 `json:"Timeout,omitempty"` +} + +// Validate validates this virtual server spec expand +func (m *VirtualServerSpecExpand) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateDestCheck(formats); err != nil { + res = append(res, err) + } + + if err := m.validateExpireQuiescent(formats); err != nil { + res = append(res, err) + } + + if err := m.validateMatch(formats); err != nil { + res = append(res, err) + } + + if err := m.validateRSs(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSchedName(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStats(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSyncProxy(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerSpecExpand) validateDestCheck(formats strfmt.Registry) error { + if swag.IsZero(m.DestCheck) { // not required + return nil + } + + for i := 0; i < len(m.DestCheck); i++ { + + if err := m.DestCheck[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("DestCheck" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("DestCheck" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +var virtualServerSpecExpandTypeExpireQuiescentPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["true","false"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecExpandTypeExpireQuiescentPropEnum = append(virtualServerSpecExpandTypeExpireQuiescentPropEnum, v) + } +} + +const ( + + // VirtualServerSpecExpandExpireQuiescentTrue captures enum value "true" + VirtualServerSpecExpandExpireQuiescentTrue string = "true" + + // VirtualServerSpecExpandExpireQuiescentFalse captures enum value "false" + VirtualServerSpecExpandExpireQuiescentFalse string = "false" +) + +// prop value enum +func (m *VirtualServerSpecExpand) validateExpireQuiescentEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeExpireQuiescentPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecExpand) validateExpireQuiescent(formats strfmt.Registry) error { + if swag.IsZero(m.ExpireQuiescent) { // not required + return nil + } + + // value enum + if err := m.validateExpireQuiescentEnum("ExpireQuiescent", "body", m.ExpireQuiescent); err != nil { + return err + } + + return nil +} + +func (m *VirtualServerSpecExpand) validateMatch(formats strfmt.Registry) error { + if swag.IsZero(m.Match) { // not required + return nil + } + + if m.Match != nil { + if err := m.Match.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Match") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Match") + } + return err + } + } + + return nil +} + +func (m *VirtualServerSpecExpand) validateRSs(formats strfmt.Registry) error { + if swag.IsZero(m.RSs) { // not required + return nil + } + + if m.RSs != nil { + if err := m.RSs.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("RSs") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("RSs") + } + return err + } + } + + return nil +} + +var virtualServerSpecExpandTypeSchedNamePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["rr","wrr","wlc","connhash"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecExpandTypeSchedNamePropEnum = append(virtualServerSpecExpandTypeSchedNamePropEnum, v) + } +} + +const ( + + // VirtualServerSpecExpandSchedNameRr captures enum value "rr" + VirtualServerSpecExpandSchedNameRr string = "rr" + + // VirtualServerSpecExpandSchedNameWrr captures enum value "wrr" + VirtualServerSpecExpandSchedNameWrr string = "wrr" + + // VirtualServerSpecExpandSchedNameWlc captures enum value "wlc" + VirtualServerSpecExpandSchedNameWlc string = "wlc" + + // VirtualServerSpecExpandSchedNameConnhash captures enum value "connhash" + VirtualServerSpecExpandSchedNameConnhash string = "connhash" +) + +// prop value enum +func (m *VirtualServerSpecExpand) validateSchedNameEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeSchedNamePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecExpand) validateSchedName(formats strfmt.Registry) error { + if swag.IsZero(m.SchedName) { // not required + return nil + } + + // value enum + if err := m.validateSchedNameEnum("SchedName", "body", m.SchedName); err != nil { + return err + } + + return nil +} + +func (m *VirtualServerSpecExpand) validateStats(formats strfmt.Registry) error { + if swag.IsZero(m.Stats) { // not required + return nil + } + + if m.Stats != nil { + if err := m.Stats.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Stats") + } + return err + } + } + + return nil +} + +var virtualServerSpecExpandTypeSyncProxyPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["true","false"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecExpandTypeSyncProxyPropEnum = append(virtualServerSpecExpandTypeSyncProxyPropEnum, v) + } +} + +const ( + + // VirtualServerSpecExpandSyncProxyTrue captures enum value "true" + VirtualServerSpecExpandSyncProxyTrue string = "true" + + // VirtualServerSpecExpandSyncProxyFalse captures enum value "false" + VirtualServerSpecExpandSyncProxyFalse string = "false" +) + +// prop value enum +func (m *VirtualServerSpecExpand) validateSyncProxyEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeSyncProxyPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecExpand) validateSyncProxy(formats strfmt.Registry) error { + if swag.IsZero(m.SyncProxy) { // not required + return nil + } + + // value enum + if err := m.validateSyncProxyEnum("SyncProxy", "body", m.SyncProxy); err != nil { + return err + } + + return nil +} + +// ContextValidate validate this virtual server spec expand based on the context it is used +func (m *VirtualServerSpecExpand) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateDestCheck(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateMatch(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateRSs(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateStats(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerSpecExpand) contextValidateDestCheck(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.DestCheck); i++ { + + if err := m.DestCheck[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("DestCheck" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("DestCheck" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *VirtualServerSpecExpand) contextValidateMatch(ctx context.Context, formats strfmt.Registry) error { + + if m.Match != nil { + if err := m.Match.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Match") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Match") + } + return err + } + } + + return nil +} + +func (m *VirtualServerSpecExpand) contextValidateRSs(ctx context.Context, formats strfmt.Registry) error { + + if m.RSs != nil { + if err := m.RSs.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("RSs") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("RSs") + } + return err + } + } + + return nil +} + +func (m *VirtualServerSpecExpand) contextValidateStats(ctx context.Context, formats strfmt.Registry) error { + + if m.Stats != nil { + if err := m.Stats.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Stats") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *VirtualServerSpecExpand) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *VirtualServerSpecExpand) UnmarshalBinary(b []byte) error { + var res VirtualServerSpecExpand + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/virtual_server_spec_tiny.go b/tools/dpvs-agent/models/virtual_server_spec_tiny.go new file mode 100644 index 000000000..3ebfd849c --- /dev/null +++ b/tools/dpvs-agent/models/virtual_server_spec_tiny.go @@ -0,0 +1,183 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// VirtualServerSpecTiny virtual server spec tiny +// +// swagger:model VirtualServerSpecTiny +type VirtualServerSpecTiny struct { + + // bps + Bps uint32 `json:"Bps,omitempty"` + + // conn timeout + ConnTimeout uint32 `json:"ConnTimeout,omitempty"` + + // expire quiescent + ExpireQuiescent *bool `json:"ExpireQuiescent,omitempty"` + + // fwmark + Fwmark uint32 `json:"Fwmark,omitempty"` + + // limit proportion + LimitProportion uint32 `json:"LimitProportion,omitempty"` + + // match + Match *MatchSpec `json:"Match,omitempty"` + + // sched name + // Enum: [rr wrr wlc connhash] + SchedName string `json:"SchedName,omitempty"` + + // sync proxy + SyncProxy *bool `json:"SyncProxy,omitempty"` + + // timeout + Timeout uint32 `json:"Timeout,omitempty"` +} + +// Validate validates this virtual server spec tiny +func (m *VirtualServerSpecTiny) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateMatch(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSchedName(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerSpecTiny) validateMatch(formats strfmt.Registry) error { + if swag.IsZero(m.Match) { // not required + return nil + } + + if m.Match != nil { + if err := m.Match.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Match") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Match") + } + return err + } + } + + return nil +} + +var virtualServerSpecTinyTypeSchedNamePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["rr","wrr","wlc","connhash"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecTinyTypeSchedNamePropEnum = append(virtualServerSpecTinyTypeSchedNamePropEnum, v) + } +} + +const ( + + // VirtualServerSpecTinySchedNameRr captures enum value "rr" + VirtualServerSpecTinySchedNameRr string = "rr" + + // VirtualServerSpecTinySchedNameWrr captures enum value "wrr" + VirtualServerSpecTinySchedNameWrr string = "wrr" + + // VirtualServerSpecTinySchedNameWlc captures enum value "wlc" + VirtualServerSpecTinySchedNameWlc string = "wlc" + + // VirtualServerSpecTinySchedNameConnhash captures enum value "connhash" + VirtualServerSpecTinySchedNameConnhash string = "connhash" +) + +// prop value enum +func (m *VirtualServerSpecTiny) validateSchedNameEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecTinyTypeSchedNamePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecTiny) validateSchedName(formats strfmt.Registry) error { + if swag.IsZero(m.SchedName) { // not required + return nil + } + + // value enum + if err := m.validateSchedNameEnum("SchedName", "body", m.SchedName); err != nil { + return err + } + + return nil +} + +// ContextValidate validate this virtual server spec tiny based on the context it is used +func (m *VirtualServerSpecTiny) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateMatch(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerSpecTiny) contextValidateMatch(ctx context.Context, formats strfmt.Registry) error { + + if m.Match != nil { + if err := m.Match.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Match") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Match") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *VirtualServerSpecTiny) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *VirtualServerSpecTiny) UnmarshalBinary(b []byte) error { + var res VirtualServerSpecTiny + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/vlan_spec.go b/tools/dpvs-agent/models/vlan_spec.go new file mode 100644 index 000000000..ef77bf716 --- /dev/null +++ b/tools/dpvs-agent/models/vlan_spec.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// VlanSpec vlan spec +// +// swagger:model VlanSpec +type VlanSpec struct { + + // device + Device string `json:"device,omitempty"` + + // id + ID string `json:"id,omitempty"` + + // name + Name string `json:"name,omitempty"` +} + +// Validate validates this vlan spec +func (m *VlanSpec) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this vlan spec based on context it is used +func (m *VlanSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *VlanSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *VlanSpec) UnmarshalBinary(b []byte) error { + var res VlanSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/pkg/ipc/pool/conn.go b/tools/dpvs-agent/pkg/ipc/pool/conn.go new file mode 100644 index 000000000..6f7034653 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/pool/conn.go @@ -0,0 +1,316 @@ +package pool + +import ( + "bufio" + "context" + "net" + "sync/atomic" + "time" + + "github.com/dpvs-agent/pkg/ipc/proto" +) + +type BadConnError struct { + wrapped error +} + +var _ error = (*BadConnError)(nil) + +func (e BadConnError) Error() string { + s := "dpvs: Conn is in a bad state" + if e.wrapped != nil { + s += ": " + e.wrapped.Error() + } + return s +} + +func (e BadConnError) Unwrap() error { + return e.wrapped +} + +//-------------------------------------- + +var noDeadline = time.Time{} + +type Conn struct { + usedAt int64 // atomic + netConn net.Conn + + rd *proto.Reader + bw *bufio.Writer + wr *proto.Writer + + Inited bool + pooled bool + createdAt time.Time +} + +func NewConn(netConn net.Conn) *Conn { + cn := &Conn{ + netConn: netConn, + createdAt: time.Now(), + } + cn.rd = proto.NewReader(netConn) + cn.bw = bufio.NewWriter(netConn) + cn.wr = proto.NewWriter(cn.bw) + cn.SetUsedAt(time.Now()) + return cn +} + +func (cn *Conn) UsedAt() time.Time { + unix := atomic.LoadInt64(&cn.usedAt) + return time.Unix(unix, 0) +} + +func (cn *Conn) SetUsedAt(tm time.Time) { + atomic.StoreInt64(&cn.usedAt, tm.Unix()) +} + +func (cn *Conn) SetNetConn(netConn net.Conn) { + cn.netConn = netConn + cn.rd.Reset(netConn) + cn.bw.Reset(netConn) +} + +/* +func (cn *Conn) Write(b []byte) (int, error) { + offset := 0 + left := len(b) + for left > 0 { + written, err := cn.write(b[offset:]) + if err != nil { + return offset, err + } + left -= written + offset += written + } + return offset, nil +} +*/ + +type ConnWriteIf interface { + Sizeof() uint64 +} + +func (cn *Conn) Write(o ConnWriteIf) error { + buf := Package(o) + _, err := cn.writeN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (cn *Conn) WriteN(b []byte, n int) (int, error) { + return cn.writeN(b, n) +} + +func (cn *Conn) writeN(b []byte, n int) (int, error) { + if n > 0 && n <= len(b) { + if err := cn.SetWriteBuffer(n); err != nil { + return 0, err + } + } + + return cn.write(b) +} + +/* +func (cn *Conn) Read(b []byte) (int, error) { + offset := 0 + left := len(b) + for left > 0 { + readed, err := cn.read(b[offset:]) + if err != nil { + return offset, err + } + offset += readed + left -= readed + } + return offset, nil +} +*/ + +type ConnReadIf interface { + Sizeof() uint64 + Dump([]byte) bool +} + +func (cn *Conn) Read(o ConnReadIf) error { + buf, err := cn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +func (cn *Conn) Release(n int) { + cn.ReadN(n) +} + +func (cn *Conn) ReadN(n int) ([]byte, error) { + return cn.readN(n) +} + +func (cn *Conn) readN(n int) ([]byte, error) { + if err := cn.SetReadBuffer(n); err != nil { + return nil, err + } + + b := make([]byte, n) + readed, err := cn.read(b) + if err != nil || readed != n { + return nil, err + } + return b, nil +} + +func (cn *Conn) write(b []byte) (int, error) { + return cn.netConn.Write(b) +} + +func (cn *Conn) read(b []byte) (int, error) { + return cn.netConn.Read(b) +} + +func (cn *Conn) SetWriteBuffer(bytes int) error { + conn := cn.netConn + if unix, ok := conn.(*net.UnixConn); ok { + return unix.SetWriteBuffer(bytes) + } + if tc, ok := conn.(*net.TCPConn); ok { + return tc.SetWriteBuffer(bytes) + } + if uc, ok := conn.(*net.UDPConn); ok { + return uc.SetWriteBuffer(bytes) + } + if ic, ok := conn.(*net.IPConn); ok { + return ic.SetWriteBuffer(bytes) + } + return nil +} + +func (cn *Conn) SetReadBuffer(bytes int) error { + conn := cn.netConn + if unix, ok := conn.(*net.UnixConn); ok { + return unix.SetReadBuffer(bytes) + } + if tc, ok := conn.(*net.TCPConn); ok { + return tc.SetReadBuffer(bytes) + } + if uc, ok := conn.(*net.UDPConn); ok { + return uc.SetReadBuffer(bytes) + } + if ic, ok := conn.(*net.IPConn); ok { + return ic.SetReadBuffer(bytes) + } + return nil +} + +func (cn *Conn) RemoteAddr() net.Addr { + if cn.netConn != nil { + return cn.netConn.RemoteAddr() + } + return nil +} + +func (cn *Conn) Close() error { + return cn.netConn.Close() +} + +func (cn *Conn) deadline(ctx context.Context, timeout time.Duration) time.Time { + tm := time.Now() + cn.SetUsedAt(tm) + + if timeout > 0 { + tm = tm.Add(timeout) + } + + if ctx != nil { + deadline, ok := ctx.Deadline() + if ok { + if timeout == 0 { + return deadline + } + if deadline.Before(tm) { + return deadline + } + return tm + } + } + + if timeout > 0 { + return tm + } + + return noDeadline +} + +func (cn *Conn) WithWriter(ctx context.Context, timeout time.Duration, fn func(wr *proto.Writer) error) error { + if err := cn.netConn.SetDeadline(cn.deadline(ctx, timeout)); err != nil { + return err + } + + if cn.bw.Buffered() > 0 { + cn.bw.Reset(cn.netConn) + } + + if err := fn(cn.wr); err != nil { + return err + } + + if err := cn.bw.Flush(); err != nil { + return err + } + + return nil + /* + return internal.WithSpan(ctx, "dpvs-agent.with_writer", func(ctx context.Context, span trace.Span) error { + if err := cn.netConn.SetWriteDeadline(cn.deadline(ctx, timeout)); err != nil { + return internal.RecordError(ctx, span, err) + } + + if cn.bw.Buffered() > 0 { + cn.bw.Reset(cn.netConn) + } + + if err := fn(cn.wr); err != nil { + return internal.RecordError(ctx, span, err) + } + + if err := cn.bw.Flush(); err != nil { + return internal.RecordError(ctx, span, err) + } + + internal.WritesCounter.Add(ctx, 1) + + return nil + }) + */ +} + +func (cn *Conn) WithReader(ctx context.Context, timeout time.Duration, fn func(rd *proto.Reader) error) error { + if err := cn.netConn.SetDeadline(cn.deadline(ctx, timeout)); err != nil { + return err + } + + if err := fn(cn.rd); err != nil { + return err + } + + return nil + /* + return internal.WithSpan(ctx, "dpvs-agent.with_reader", func(ctx context.Context, span trace.Span) error { + if err := cn.netConn.SetReadDeadline(cn.deadline(ctx, timeout)); err != nil { + return internal.RecordError(ctx, span, err) + } + if err := fn(cn.rd); err != nil { + return internal.RecordError(ctx, span, err) + } + return nil + }) + */ +} diff --git a/tools/dpvs-agent/pkg/ipc/pool/pool.go b/tools/dpvs-agent/pkg/ipc/pool/pool.go new file mode 100644 index 000000000..c88d9d82d --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/pool/pool.go @@ -0,0 +1,523 @@ +package pool + +import ( + "context" + "errors" + "net" + "sync" + "sync/atomic" + "time" +) + +var ( + ErrClosed = errors.New("client is closed") + ErrPoolTimeout = errors.New("connection pool timeout") +) + +var timers = sync.Pool{ + New: func() interface{} { + t := time.NewTimer(time.Hour) + t.Stop() + return t + }, +} + +// Stats contains pool state information and accumulated stats. +type Stats struct { + Hits uint32 // number of times free connection was found in the pool + Misses uint32 // number of times free connection was NOT found in the pool + Timeouts uint32 // number of times a wait timeout occurred + + TotalConns uint32 // number of total connections in the pool + IdleConns uint32 // number of idle connections in the pool + StaleConns uint32 // number of stale connections removed from the pool +} + +type Pooler interface { + NewConn(context.Context) (*Conn, error) + CloseConn(*Conn) error + + Get(context.Context) (*Conn, error) + Put(context.Context, *Conn) + Remove(context.Context, *Conn, error) + + Len() int + IdleLen() int + Stats() *Stats + + Close() error +} + +type Options struct { + Dialer func(context.Context) (net.Conn, error) + OnClose func(*Conn) error + + PoolSize int + MinIdleConns int + MaxConnAge time.Duration + PoolTimeout time.Duration + IdleTimeout time.Duration + IdleCheckFrequency time.Duration +} + +type lastDialErrorWrap struct { + err error +} + +type ConnPool struct { + opt *Options + + dialErrorsNum uint32 // atomic + + lastDialError atomic.Value + + queue chan struct{} + + connsMu sync.Mutex + conns []*Conn + idleConns []*Conn + poolSize int + idleConnsLen int + + stats Stats + + _closed uint32 // atomic + closedCh chan struct{} +} + +var _ Pooler = (*ConnPool)(nil) + +func NewConnPool(opt *Options) *ConnPool { + p := &ConnPool{ + opt: opt, + + queue: make(chan struct{}, opt.PoolSize), + conns: make([]*Conn, 0, opt.PoolSize), + idleConns: make([]*Conn, 0, opt.PoolSize), + closedCh: make(chan struct{}), + } + + p.connsMu.Lock() + p.checkMinIdleConns() + p.connsMu.Unlock() + + if opt.IdleTimeout > 0 && opt.IdleCheckFrequency > 0 { + go p.reaper(opt.IdleCheckFrequency) + } + + return p +} + +func (p *ConnPool) checkMinIdleConns() { + if p.opt.MinIdleConns == 0 { + return + } + for p.poolSize < p.opt.PoolSize && p.idleConnsLen < p.opt.MinIdleConns { + p.poolSize++ + p.idleConnsLen++ + go func() { + err := p.addIdleConn() + if err != nil { + p.connsMu.Lock() + p.poolSize-- + p.idleConnsLen-- + p.connsMu.Unlock() + } + }() + } +} + +func (p *ConnPool) addIdleConn() error { + cn, err := p.dialConn(context.TODO(), true) + if err != nil { + return err + } + + p.connsMu.Lock() + p.conns = append(p.conns, cn) + p.idleConns = append(p.idleConns, cn) + p.connsMu.Unlock() + return nil +} + +func (p *ConnPool) NewConn(ctx context.Context) (*Conn, error) { + return p.newConn(ctx, false) +} + +func (p *ConnPool) newConn(ctx context.Context, pooled bool) (*Conn, error) { + cn, err := p.dialConn(ctx, pooled) + if err != nil { + return nil, err + } + + p.connsMu.Lock() + p.conns = append(p.conns, cn) + if pooled { + // If pool is full remove the cn on next Put. + if p.poolSize >= p.opt.PoolSize { + cn.pooled = false + } else { + p.poolSize++ + } + } + p.connsMu.Unlock() + + return cn, nil +} + +func (p *ConnPool) dialConn(ctx context.Context, pooled bool) (*Conn, error) { + if p.closed() { + return nil, ErrClosed + } + + if atomic.LoadUint32(&p.dialErrorsNum) >= uint32(p.opt.PoolSize) { + return nil, p.getLastDialError() + } + + netConn, err := p.opt.Dialer(ctx) + if err != nil { + p.setLastDialError(err) + if atomic.AddUint32(&p.dialErrorsNum, 1) == uint32(p.opt.PoolSize) { + go p.tryDial() + } + return nil, err + } + + // internal.NewConnectionsCounter.Add(ctx, 1) + cn := NewConn(netConn) + cn.pooled = pooled + return cn, nil +} + +func (p *ConnPool) tryDial() { + for { + if p.closed() { + return + } + + conn, err := p.opt.Dialer(context.Background()) + if err != nil { + p.setLastDialError(err) + time.Sleep(time.Second) + continue + } + + atomic.StoreUint32(&p.dialErrorsNum, 0) + _ = conn.Close() + return + } +} + +func (p *ConnPool) setLastDialError(err error) { + p.lastDialError.Store(&lastDialErrorWrap{err: err}) +} + +func (p *ConnPool) getLastDialError() error { + err, _ := p.lastDialError.Load().(*lastDialErrorWrap) + if err != nil { + return err.err + } + return nil +} + +// Get returns existed connection from the pool or creates a new one. +func (p *ConnPool) Get(ctx context.Context) (*Conn, error) { + if p.closed() { + return nil, ErrClosed + } + + err := p.waitTurn(ctx) + if err != nil { + return nil, err + } + + for { + p.connsMu.Lock() + cn := p.popIdle() + p.connsMu.Unlock() + + if cn == nil { + break + } + + if p.isStaleConn(cn) { + _ = p.CloseConn(cn) + continue + } + + atomic.AddUint32(&p.stats.Hits, 1) + return cn, nil + } + + atomic.AddUint32(&p.stats.Misses, 1) + + newcn, err := p.newConn(ctx, true) + if err != nil { + p.freeTurn() + return nil, err + } + + return newcn, nil +} + +func (p *ConnPool) getTurn() { + p.queue <- struct{}{} +} + +func (p *ConnPool) waitTurn(ctx context.Context) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + select { + case p.queue <- struct{}{}: + return nil + default: + } + + timer := timers.Get().(*time.Timer) + timer.Reset(p.opt.PoolTimeout) + + select { + case <-ctx.Done(): + if !timer.Stop() { + <-timer.C + } + timers.Put(timer) + return ctx.Err() + case p.queue <- struct{}{}: + if !timer.Stop() { + <-timer.C + } + timers.Put(timer) + return nil + case <-timer.C: + timers.Put(timer) + atomic.AddUint32(&p.stats.Timeouts, 1) + return ErrPoolTimeout + } +} + +func (p *ConnPool) freeTurn() { + <-p.queue +} + +func (p *ConnPool) popIdle() *Conn { + if len(p.idleConns) == 0 { + return nil + } + + idx := len(p.idleConns) - 1 + cn := p.idleConns[idx] + p.idleConns = p.idleConns[:idx] + p.idleConnsLen-- + p.checkMinIdleConns() + return cn +} + +func (p *ConnPool) Put(ctx context.Context, cn *Conn) { + if cn.rd.Buffered() > 0 { + // internal.Logger.Printf(ctx, "Conn has unread data") + p.Remove(ctx, cn, BadConnError{}) + return + } + + if !cn.pooled { + p.Remove(ctx, cn, nil) + return + } + + p.connsMu.Lock() + p.idleConns = append(p.idleConns, cn) + p.idleConnsLen++ + p.connsMu.Unlock() + p.freeTurn() +} + +func (p *ConnPool) Remove(ctx context.Context, cn *Conn, reason error) { + p.removeConnWithLock(cn) + p.freeTurn() + _ = p.closeConn(cn) +} + +func (p *ConnPool) CloseConn(cn *Conn) error { + p.removeConnWithLock(cn) + return p.closeConn(cn) +} + +func (p *ConnPool) removeConnWithLock(cn *Conn) { + p.connsMu.Lock() + p.removeConn(cn) + p.connsMu.Unlock() +} + +func (p *ConnPool) removeConn(cn *Conn) { + for i, c := range p.conns { + if c == cn { + p.conns = append(p.conns[:i], p.conns[i+1:]...) + if cn.pooled { + p.poolSize-- + p.checkMinIdleConns() + } + return + } + } +} + +func (p *ConnPool) closeConn(cn *Conn) error { + if p.opt.OnClose != nil { + _ = p.opt.OnClose(cn) + } + return cn.Close() +} + +// Len returns total number of connections. +func (p *ConnPool) Len() int { + p.connsMu.Lock() + n := len(p.conns) + p.connsMu.Unlock() + return n +} + +// IdleLen returns number of idle connections. +func (p *ConnPool) IdleLen() int { + p.connsMu.Lock() + n := p.idleConnsLen + p.connsMu.Unlock() + return n +} + +func (p *ConnPool) Stats() *Stats { + idleLen := p.IdleLen() + return &Stats{ + Hits: atomic.LoadUint32(&p.stats.Hits), + Misses: atomic.LoadUint32(&p.stats.Misses), + Timeouts: atomic.LoadUint32(&p.stats.Timeouts), + + TotalConns: uint32(p.Len()), + IdleConns: uint32(idleLen), + StaleConns: atomic.LoadUint32(&p.stats.StaleConns), + } +} + +func (p *ConnPool) closed() bool { + return atomic.LoadUint32(&p._closed) == 1 +} + +func (p *ConnPool) Filter(fn func(*Conn) bool) error { + p.connsMu.Lock() + defer p.connsMu.Unlock() + + var firstErr error + for _, cn := range p.conns { + if fn(cn) { + if err := p.closeConn(cn); err != nil && firstErr == nil { + firstErr = err + } + } + } + return firstErr +} + +func (p *ConnPool) Close() error { + if !atomic.CompareAndSwapUint32(&p._closed, 0, 1) { + return ErrClosed + } + close(p.closedCh) + + var firstErr error + p.connsMu.Lock() + for _, cn := range p.conns { + if err := p.closeConn(cn); err != nil && firstErr == nil { + firstErr = err + } + } + p.conns = nil + p.poolSize = 0 + p.idleConns = nil + p.idleConnsLen = 0 + p.connsMu.Unlock() + + return firstErr +} + +func (p *ConnPool) reaper(frequency time.Duration) { + ticker := time.NewTicker(frequency) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + // It is possible that ticker and closedCh arrive together, + // and select pseudo-randomly pick ticker case, we double + // check here to prevent being executed after closed. + if p.closed() { + return + } + _, err := p.ReapStaleConns() + if err != nil { + // internal.Logger.Printf(context.Background(), "ReapStaleConns failed: %s", err) + continue + } + case <-p.closedCh: + return + } + } +} + +func (p *ConnPool) ReapStaleConns() (int, error) { + var n int + for { + p.getTurn() + + p.connsMu.Lock() + cn := p.reapStaleConn() + p.connsMu.Unlock() + + p.freeTurn() + + if cn != nil { + _ = p.closeConn(cn) + n++ + } else { + break + } + } + atomic.AddUint32(&p.stats.StaleConns, uint32(n)) + return n, nil +} + +func (p *ConnPool) reapStaleConn() *Conn { + if len(p.idleConns) == 0 { + return nil + } + + cn := p.idleConns[0] + if !p.isStaleConn(cn) { + return nil + } + + p.idleConns = append(p.idleConns[:0], p.idleConns[1:]...) + p.idleConnsLen-- + p.removeConn(cn) + + return cn +} + +func (p *ConnPool) isStaleConn(cn *Conn) bool { + if p.opt.IdleTimeout == 0 && p.opt.MaxConnAge == 0 { + return false + } + + now := time.Now() + if p.opt.IdleTimeout > 0 && now.Sub(cn.UsedAt()) >= p.opt.IdleTimeout { + return true + } + if p.opt.MaxConnAge > 0 && now.Sub(cn.createdAt) >= p.opt.MaxConnAge { + return true + } + + return false +} diff --git a/tools/dpvs-agent/pkg/ipc/pool/util.go b/tools/dpvs-agent/pkg/ipc/pool/util.go new file mode 100644 index 000000000..3bd67fbed --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/pool/util.go @@ -0,0 +1,12 @@ +package pool + +import ( + "bytes" + "encoding/binary" +) + +func Package(o ConnWriteIf) []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} diff --git a/tools/dpvs-agent/pkg/ipc/proto/reader.go b/tools/dpvs-agent/pkg/ipc/proto/reader.go new file mode 100644 index 000000000..b77dee8d1 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/proto/reader.go @@ -0,0 +1,335 @@ +package proto + +import ( + "bufio" + "fmt" + "io" +) + +const ( + ErrorReply = '-' + StatusReply = '+' + IntReply = ':' + StringReply = '$' + ArrayReply = '*' +) + +//------------------------------------------------------------------------------ + +const Nil = DpvsError("dpvs: nil") + +type DpvsError string + +func (e DpvsError) Error() string { return string(e) } + +func (DpvsError) DpvsError() {} + +//------------------------------------------------------------------------------ + +type MultiBulkParse func(*Reader, int64) (interface{}, error) + +type Reader struct { + rd *bufio.Reader + _buf []byte +} + +func NewReader(rd io.Reader) *Reader { + return &Reader{ + rd: bufio.NewReader(rd), + _buf: make([]byte, 64), + } +} + +func (r *Reader) Buffered() int { + return r.rd.Buffered() +} + +func (r *Reader) Peek(n int) ([]byte, error) { + return r.rd.Peek(n) +} + +func (r *Reader) Reset(rd io.Reader) { + r.rd.Reset(rd) +} + +func (r *Reader) buf(n int) []byte { + if n <= cap(r._buf) { + return r._buf[:n] + } + d := n - cap(r._buf) + r._buf = append(r._buf, make([]byte, d)...) + return r._buf +} + +func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) { + /* + line, err := r.ReadLine() + + if err != nil { + return nil, err + } + + switch line[0] { + case ErrorReply: + return nil, ParseErrorReply(line) + case StatusReply: + return string(line[1:]), nil + case IntReply: + return util.ParseInt(line[1:], 10, 64) + case StringReply: + return r.readStringReply(line) + case ArrayReply: + n, err := parseArrayLen(line) + if err != nil { + return nil, err + } + if m == nil { + err := fmt.Errorf("dpvs: got %.100q, but multi bulk parser is nil", line) + return nil, err + } + return m(r, n) + } + */ + return nil, fmt.Errorf("dpvs read failed") +} + +/* +func (r *Reader) ReadLine() ([]byte, error) { + line, err := r.readLine() + if err != nil { + return nil, err + } + if isNilReply(line) { + return nil, Nil + } + return line, nil +} + +// readLine that returns an error if: +// - there is a pending read error; +// - or line does not end with \r\n. +func (r *Reader) readLine() ([]byte, error) { + b, err := r.rd.ReadSlice('\n') + if err != nil { + if err != bufio.ErrBufferFull { + return nil, err + } + + full := make([]byte, len(b)) + copy(full, b) + + b, err = r.rd.ReadBytes('\n') + if err != nil { + return nil, err + } + + full = append(full, b...) + b = full + } + if len(b) <= 2 || b[len(b)-1] != '\n' || b[len(b)-2] != '\r' { + return nil, fmt.Errorf("dpvs: invalid reply: %q", b) + } + return b[:len(b)-2], nil +} + +func (r *Reader) ReadIntReply() (int64, error) { + line, err := r.ReadLine() + if err != nil { + return 0, err + } + switch line[0] { + case ErrorReply: + return 0, ParseErrorReply(line) + case IntReply: + return util.ParseInt(line[1:], 10, 64) + default: + return 0, fmt.Errorf("dpvs: can't parse int reply: %.100q", line) + } +} + +func (r *Reader) ReadString() (string, error) { + line, err := r.ReadLine() + if err != nil { + return "", err + } + switch line[0] { + case ErrorReply: + return "", ParseErrorReply(line) + case StringReply: + return r.readStringReply(line) + case StatusReply: + return string(line[1:]), nil + case IntReply: + return string(line[1:]), nil + default: + return "", fmt.Errorf("dpvs: can't parse reply=%.100q reading string", line) + } +} + +func (r *Reader) readStringReply(line []byte) (string, error) { + if isNilReply(line) { + return "", Nil + } + + replyLen, err := util.Atoi(line[1:]) + if err != nil { + return "", err + } + + b := make([]byte, replyLen+2) + _, err = io.ReadFull(r.rd, b) + if err != nil { + return "", err + } + + return util.BytesToString(b[:replyLen]), nil +} + +func (r *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) { + line, err := r.ReadLine() + if err != nil { + return nil, err + } + switch line[0] { + case ErrorReply: + return nil, ParseErrorReply(line) + case ArrayReply: + n, err := parseArrayLen(line) + if err != nil { + return nil, err + } + return m(r, n) + default: + return nil, fmt.Errorf("dpvs: can't parse array reply: %.100q", line) + } +} + +func (r *Reader) ReadArrayLen() (int, error) { + line, err := r.ReadLine() + if err != nil { + return 0, err + } + switch line[0] { + case ErrorReply: + return 0, ParseErrorReply(line) + case ArrayReply: + n, err := parseArrayLen(line) + if err != nil { + return 0, err + } + return int(n), nil + default: + return 0, fmt.Errorf("dpvs: can't parse array reply: %.100q", line) + } +} +func (r *Reader) ReadScanReply() ([]string, uint64, error) { + n, err := r.ReadArrayLen() + if err != nil { + return nil, 0, err + } + if n != 2 { + return nil, 0, fmt.Errorf("dpvs: got %d elements in scan reply, expected 2", n) + } + + cursor, err := r.ReadUint() + if err != nil { + return nil, 0, err + } + + n, err = r.ReadArrayLen() + if err != nil { + return nil, 0, err + } + + keys := make([]string, n) + + for i := 0; i < n; i++ { + key, err := r.ReadString() + if err != nil { + return nil, 0, err + } + keys[i] = key + } + + return keys, cursor, err +} +*/ +/* +func (r *Reader) ReadInt() (int64, error) { + b, err := r.readTmpBytesReply() + if err != nil { + return 0, err + } + return util.ParseInt(b, 10, 64) +} + +func (r *Reader) ReadUint() (uint64, error) { + b, err := r.readTmpBytesReply() + if err != nil { + return 0, err + } + return util.ParseUint(b, 10, 64) +} + +func (r *Reader) ReadFloatReply() (float64, error) { + b, err := r.readTmpBytesReply() + if err != nil { + return 0, err + } + return util.ParseFloat(b, 64) +} + +func (r *Reader) readTmpBytesReply() ([]byte, error) { + line, err := r.ReadLine() + if err != nil { + return nil, err + } + switch line[0] { + case ErrorReply: + return nil, ParseErrorReply(line) + case StringReply: + return r._readTmpBytesReply(line) + case StatusReply: + return line[1:], nil + default: + return nil, fmt.Errorf("dpvs: can't parse string reply: %.100q", line) + } +} + +func (r *Reader) _readTmpBytesReply(line []byte) ([]byte, error) { + if isNilReply(line) { + return nil, Nil + } + + replyLen, err := util.Atoi(line[1:]) + if err != nil { + return nil, err + } + + buf := r.buf(replyLen + 2) + _, err = io.ReadFull(r.rd, buf) + if err != nil { + return nil, err + } + + return buf[:replyLen], nil +} +*/ +/* +func isNilReply(b []byte) bool { + return len(b) == 3 && + (b[0] == StringReply || b[0] == ArrayReply) && + b[1] == '-' && b[2] == '1' +} + +func ParseErrorReply(line []byte) error { + return DpvsError(string(line[1:])) +} + +func parseArrayLen(line []byte) (int64, error) { + if isNilReply(line) { + return 0, Nil + } + return util.ParseInt(line[1:], 10, 64) +} +*/ diff --git a/tools/dpvs-agent/pkg/ipc/proto/writer.go b/tools/dpvs-agent/pkg/ipc/proto/writer.go new file mode 100644 index 000000000..a4aced90d --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/proto/writer.go @@ -0,0 +1,167 @@ +package proto + +import ( + "encoding" + "fmt" + "io" + "strconv" + "time" + "unsafe" +) + +// BytesToString converts byte slice to string. +func BytesToString(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} + +// StringToBytes converts string to byte slice. +func StringToBytes(s string) []byte { + return *(*[]byte)(unsafe.Pointer( + &struct { + string + Cap int + }{s, len(s)}, + )) +} + +type writer interface { + io.Writer + io.ByteWriter + // io.StringWriter + WriteString(s string) (n int, err error) +} + +type Writer struct { + writer + + lenBuf []byte + numBuf []byte +} + +func NewWriter(wr writer) *Writer { + return &Writer{ + writer: wr, + + lenBuf: make([]byte, 64), + numBuf: make([]byte, 64), + } +} + +func (w *Writer) WriteArgs(args []interface{}) error { + if err := w.WriteByte(ArrayReply); err != nil { + return err + } + + if err := w.writeLen(len(args)); err != nil { + return err + } + + for _, arg := range args { + if err := w.WriteArg(arg); err != nil { + return err + } + } + + return nil +} + +func (w *Writer) writeLen(n int) error { + w.lenBuf = strconv.AppendUint(w.lenBuf[:0], uint64(n), 10) + w.lenBuf = append(w.lenBuf, '\r', '\n') + _, err := w.Write(w.lenBuf) + return err +} + +func (w *Writer) WriteArg(v interface{}) error { + switch v := v.(type) { + case nil: + return w.string("") + case string: + return w.string(v) + case []byte: + return w.bytes(v) + case int: + return w.int(int64(v)) + case int8: + return w.int(int64(v)) + case int16: + return w.int(int64(v)) + case int32: + return w.int(int64(v)) + case int64: + return w.int(v) + case uint: + return w.uint(uint64(v)) + case uint8: + return w.uint(uint64(v)) + case uint16: + return w.uint(uint64(v)) + case uint32: + return w.uint(uint64(v)) + case uint64: + return w.uint(v) + case float32: + return w.float(float64(v)) + case float64: + return w.float(v) + case bool: + if v { + return w.int(1) + } + return w.int(0) + case time.Time: + w.numBuf = v.AppendFormat(w.numBuf[:0], time.RFC3339Nano) + return w.bytes(w.numBuf) + case encoding.BinaryMarshaler: + b, err := v.MarshalBinary() + if err != nil { + return err + } + return w.bytes(b) + default: + return fmt.Errorf( + "dpvs-agent: can't marshal %T (implement encoding.BinaryMarshaler)", v) + } +} + +func (w *Writer) bytes(b []byte) error { + if err := w.WriteByte(StringReply); err != nil { + return err + } + + if err := w.writeLen(len(b)); err != nil { + return err + } + + if _, err := w.Write(b); err != nil { + return err + } + + return w.crlf() +} + +func (w *Writer) string(s string) error { + return w.bytes(StringToBytes(s)) +} + +func (w *Writer) uint(n uint64) error { + w.numBuf = strconv.AppendUint(w.numBuf[:0], n, 10) + return w.bytes(w.numBuf) +} + +func (w *Writer) int(n int64) error { + w.numBuf = strconv.AppendInt(w.numBuf[:0], n, 10) + return w.bytes(w.numBuf) +} + +func (w *Writer) float(f float64) error { + w.numBuf = strconv.AppendFloat(w.numBuf[:0], f, 'f', -1, 64) + return w.bytes(w.numBuf) +} + +func (w *Writer) crlf() error { + if err := w.WriteByte('\r'); err != nil { + return err + } + return w.WriteByte('\n') +} diff --git a/tools/dpvs-agent/pkg/ipc/types/certificate.go b/tools/dpvs-agent/pkg/ipc/types/certificate.go new file mode 100644 index 000000000..b0b7b74a4 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/certificate.go @@ -0,0 +1,369 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type CertificateAuthoritySpec struct { + src [0x10]byte + dst [0x10]byte + af uint32 + fwmark uint32 + port uint16 + proto uint8 + padding uint8 +} + +type CertificateAuthorityFront struct { + count uint32 +} + +func NewCertificateAuthoritySpec() *CertificateAuthoritySpec { + return &CertificateAuthoritySpec{} +} + +func NewCertificateAuthorityFront() *CertificateAuthorityFront { + return &CertificateAuthorityFront{} +} + +func (o *CertificateAuthoritySpec) Copy(src *CertificateAuthoritySpec) bool { + o.af = src.af + o.fwmark = src.fwmark + o.port = src.port + o.proto = src.proto + copy(o.src[:], src.src[:]) + copy(o.dst[:], src.dst[:]) + return true +} + +func (o *CertificateAuthoritySpec) ParseVipPortProto(vipport string) error { + items := strings.Split(vipport, "-") + if len(items) != 3 { + return errors.New("invalid vip-port-proto string") + } + + proto := items[2] + + switch strings.ToLower(proto) { + case "udp": + o.proto = unix.IPPROTO_UDP + case "tcp": + fallthrough + default: + o.proto = unix.IPPROTO_TCP + } + + // port := items[1] + port, err := strconv.Atoi(items[1]) + if err != nil { + return err + } + o.SetPort(uint16(port)) + + vip := items[0] + if net.ParseIP(vip) == nil { + return errors.New(fmt.Sprintf("invalid ip addr: %s\n", vip)) + } + + o.SetDst(vip) + + return nil +} + +func (o *CertificateAuthorityFront) Copy(src *CertificateAuthorityFront) bool { + o.count = src.count + return true +} + +func (o *CertificateAuthoritySpec) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *CertificateAuthorityFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *CertificateAuthoritySpec) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *CertificateAuthoritySpec = *(**CertificateAuthoritySpec)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *CertificateAuthorityFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *CertificateAuthorityFront = *(**CertificateAuthorityFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *CertificateAuthoritySpec) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *CertificateAuthorityFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *CertificateAuthorityFront) SetCount(count uint32) { + o.count = count +} + +func (o *CertificateAuthorityFront) GetCount() uint32 { + return o.count +} + +func (o *CertificateAuthoritySpec) SetAf(af uint32) { + o.af = af +} + +func (o *CertificateAuthoritySpec) SetSrc(addr string) { + if strings.Contains(addr, ":") { + o.SetAf(unix.AF_INET6) + copy(o.src[:], net.ParseIP(addr)) + return + } + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.src[:], buf.Bytes()[12:]) +} + +func (o *CertificateAuthoritySpec) SetDst(addr string) { + if strings.Contains(addr, ":") { + o.SetAf(unix.AF_INET6) + copy(o.dst[:], net.ParseIP(addr)) + return + } + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.dst[:], buf.Bytes()[12:]) +} + +func (o *CertificateAuthoritySpec) SetFwmark(fwmark uint32) { + o.fwmark = fwmark +} + +func (o *CertificateAuthoritySpec) SetPort(port uint16) { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(port)) + o.port = binary.BigEndian.Uint16(buf.Bytes()) +} + +func (o *CertificateAuthoritySpec) SetProto(proto string) { + switch strings.ToLower(proto) { + case "udp": + o.proto = unix.IPPROTO_UDP + default: + o.proto = unix.IPPROTO_TCP + } +} + +func (o *CertificateAuthorityFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*CertificateAuthorityFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to CertificateAuthorityFront") + } + + fronts := make([]*CertificateAuthorityFront, cnt) + + for i := 0; i < int(cnt); i++ { + fronts[i] = NewCertificateAuthorityFront() + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *CertificateAuthoritySpec) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*CertificateAuthoritySpec, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to CertificateAuthoritySpec") + } + + calst := make([]*CertificateAuthoritySpec, cnt) + for i := 0; i < int(cnt); i++ { + calst[i] = NewCertificateAuthoritySpec() + + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + calst[i].Dump(buf) + } + + return calst, nil +} + +func (o *CertificateAuthoritySpec) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (o *CertificateAuthoritySpec) Add(cp *pool.ConnPool, blk bool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var ADD uint32 + SOCKOPT_STRING := "SOCKOPT_SET_BLKLST_ADD" + ADD = SOCKOPT_SET_BLKLST_ADD + if !blk { + SOCKOPT_STRING = "SOCKOPT_SET_WHTLST_ADD" + ADD = SOCKOPT_SET_WHTLST_ADD + } + + msg := NewSockMsg(SOCKOPT_VERSION, ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write proto header Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + err = o.write(conn, logger) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write specific auth user Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s reply msg Read Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + logger.Info(fmt.Sprintf("Sockopt %s Done:%s", SOCKOPT_STRING, errCode.String())) + return errCode +} + +func (o *CertificateAuthoritySpec) Del(cp *pool.ConnPool, blk bool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var DEL uint32 + SOCKOPT_STRING := "SOCKOPT_SET_BLKLST_DEL" + DEL = SOCKOPT_SET_BLKLST_DEL + if !blk { + SOCKOPT_STRING = "SOCKOPT_SET_WHTLST_DEL" + DEL = SOCKOPT_SET_WHTLST_DEL + } + + msg := NewSockMsg(SOCKOPT_VERSION, DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write proto header Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + err = o.write(conn, logger) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write specific auth user Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s reply msg Read Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + logger.Info(fmt.Sprintf("Sockopt %s Done:%s", SOCKOPT_STRING, errCode.String())) + return errCode +} + +func (o *CertificateAuthoritySpec) Get(cp *pool.ConnPool, blk bool, logger hclog.Logger) ([]*CertificateAuthoritySpec, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + var GET uint32 + SOCKOPT_STRING := "SOCKOPT_GET_BLKLST_GETALL" + GET = SOCKOPT_GET_BLKLST_GETALL + if !blk { + GET = SOCKOPT_GET_WHTLST_GETALL + SOCKOPT_STRING = "SOCKOPT_GET_WHTLST_GETALL" + } + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write proto header Error: %s", SOCKOPT_STRING, err.Error())) + return nil, err + } + + if err := o.write(conn, logger); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write specific auth user Error: %s", SOCKOPT_STRING, err.Error())) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s reply msg Read Error: %s", SOCKOPT_STRING, err.Error())) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + err = fmt.Errorf("Sockopt %s reply ErrorCode: %s", SOCKOPT_STRING, reply.GetErrStr()) + logger.Error(err.Error()) + return nil, err + } + + front := NewCertificateAuthorityFront() + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s read auth user table header Error: %s", SOCKOPT_STRING, err.Error())) + return nil, err + } + + return o.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} diff --git a/tools/dpvs-agent/pkg/ipc/types/const.go b/tools/dpvs-agent/pkg/ipc/types/const.go new file mode 100644 index 000000000..9cbc3d49a --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/const.go @@ -0,0 +1,334 @@ +package types + +import ( + "strings" +) + +type lcoreid_t uint8 +type SockoptType uint32 +type DpvsErrType int32 +type DpvsFwdMode uint32 + +const ( + DPVS_FWD_MASQ DpvsFwdMode = iota + DPVS_FWD_LOCALNODE + DPVS_FWD_MODE_TUNNEL + DPVS_FWD_MODE_DR + DPVS_FWD_MODE_BYPASS + DPVS_FWD_MODE_FNAT + DPVS_FWD_MODE_SNAT +) +const DPVS_FWD_MODE_NAT DpvsFwdMode = DPVS_FWD_MASQ + +const ( + DPVS_SVC_F_PERSISTENT = 0x1 << iota + DPVS_SVC_F_HASHED + DPVS_SVC_F_ONEPACKET + DPVS_SVC_F_SCHED1 + DPVS_SVC_F_SCHED2 + DPVS_SVC_F_SCHED3 +) + +const ( + DPVS_SVC_F_SIP_HASH uint32 = 0x100 << iota + DPVS_SVC_F_QID_HASH + DPVS_SVC_F_MATCH +) + +const ( + DPVS_DEST_HC_PASSIVE = 0x1 << iota + DPVS_DEST_HC_TCP + DPVS_DEST_HC_UDP + DPVS_DEST_HC_PING +) + +const ( + DPVS_DEST_F_AVAILABLE = 0x1 << iota + DPVS_DEST_F_OVERLOAD + DPVS_DEST_F_INHIBITED +) + +const ( + DPVS_CONN_F_MASQ = iota + DPVS_CONN_F_LOCALNODE + DPVS_CONN_F_TUNNEL + DPVS_CONN_F_DROUTE + DPVS_CONN_F_BYPASS + DPVS_CONN_F_FULLNAT + DPVS_CONN_F_SNAT + DPVS_CONN_F_FWD_MASK +) + +const ( + DPVS_CONN_F_SYNPROXY = 0x10 << iota + DPVS_CONN_F_EXPIRE_QUIESCENT + _ + _ + DPVS_CONN_F_HASHED + DPVS_CONN_F_INACTIVE + DPVS_CONN_F_TEMPLATE + DPVS_CONN_F_ONE_PACKET + DPVS_CONN_F_IN_TIMER + DPVS_CONN_F_REDIRECT_HASHED + DPVS_CONN_F_NOFASTXMIT +) + +func (e *DpvsFwdMode) String() string { + switch *e { + case DPVS_FWD_MASQ: // DPVS_FWD_MASQ == DPVS_FWD_MODE_NAT + return "MASQ" + case DPVS_FWD_LOCALNODE: + return "LOCALNODE" + case DPVS_FWD_MODE_DR: + return "DR" + case DPVS_FWD_MODE_TUNNEL: + return "TUNNLE" + case DPVS_FWD_MODE_BYPASS: + return "BYPASS" + case DPVS_FWD_MODE_SNAT: + return "SNAT" + case DPVS_FWD_MODE_FNAT: + return "FNAT" + } + return "UNKNOW" +} + +func (e *DpvsFwdMode) FromString(name string) { + switch strings.ToUpper(name) { + case "MASQ": + *e = DPVS_FWD_MASQ + case "LOCALNODE": + *e = DPVS_FWD_LOCALNODE + case "DR": + *e = DPVS_FWD_MODE_DR + case "TUNNLE": + *e = DPVS_FWD_MODE_TUNNEL + case "BYPASS": + *e = DPVS_FWD_MODE_BYPASS + case "SNAT": + *e = DPVS_FWD_MODE_SNAT + case "NAT": + *e = DPVS_FWD_MODE_NAT + case "FNAT": + *e = DPVS_FWD_MODE_FNAT + default: + *e = DPVS_FWD_MODE_FNAT + } +} + +const ( + EDPVS_INPROGRESS DpvsErrType = 2 - iota + EDPVS_KNICONTINUE + EDPVS_OK + EDPVS_INVAL + EDPVS_NOMEM + EDPVS_EXIST + EDPVS_NOTEXIST + EDPVS_INVPKT + EDPVS_DROP + EDPVS_NOPROT + EDPVS_NOROUTE + EDPVS_DEFRAG + EDPVS_FRAG + EDPVS_DPDKAPIFAIL + EDPVS_IDLE + EDPVS_BUSY + EDPVS_NOTSUPP + EDPVS_RESOURCE + EDPVS_OVERLOAD + EDPVS_NOSERV + EDPVS_DISABLED + EDPVS_NOROOM + EDPVS_NONEALCORE + EDPVS_CALLBACKFAIL + EDPVS_IO + EDPVS_MSG_FAIL + EDPVS_MSG_DROP + EDPVS_PKTSTOLEN + EDPVS_SYSCALL + EDPVS_NODEV +) + +var dpvsErrNames = [...]string{"EDPVS_INPROGRESS", "EDPVS_KNICONTINUE", "EDPVS_OK", "EDPVS_INVAL", "EDPVS_NOMEM", "EDPVS_EXIST", "EDPVS_NOTEXIST", "EDPVS_INVPKT", "EDPVS_DROP", "EDPVS_NOPROT", "EDPVS_NOROUTE", "EDPVS_DEFRAG", "EDPVS_FRAG", "EDPVS_DPDKAPIFAIL", "EDPVS_IDLE", "EDPVS_BUSY", "EDPVS_NOTSUPP", "EDPVS_RESOURCE", "EDPVS_OVERLOAD", "EDPVS_NOSERV", "EDPVS_DISABLED", "EDPVS_NOROOM", "EDPVS_NONEALCORE", "EDPVS_CALLBACKFAIL", "EDPVS_IO", "EDPVS_MSG_FAIL", "EDPVS_MSG_DROP", "EDPVS_PKTSTOLEN", "EDPVS_SYSCALL", "EDPVS_NODEV"} + +func (e *DpvsErrType) String() string { + return dpvsErrNames[EDPVS_INPROGRESS-*e] +} + +const ( + SOCKOPT_VERSION = 0x10000 +) + +const ( + SOCKOPT_GET SockoptType = iota + SOCKOPT_SET + SOCKOPT_TYPE_MAX +) + +const ( + SOCKOPT_SET_LADDR_ADD = iota + SOCKOPT_SET_LADDR_DEL + SOCKOPT_SET_LADDR_FLUSH + SOCKOPT_GET_LADDR_GETALL + SOCKOPT_GET_LADDR_MAX + + DPVSAGENT_VS_GET_LADDR + DPVSAGENT_VS_ADD_LADDR + DPVSAGENT_VS_DEL_LADDR + + DPVS_SO_SET_FLUSH + DPVS_SO_SET_ZERO + DPVS_SO_SET_ADD + DPVS_SO_SET_EDIT + DPVS_SO_SET_DEL + DPVS_SO_SET_ADDDEST + DPVS_SO_SET_EDITDEST + DPVS_SO_SET_DELDEST + DPVS_SO_SET_GRATARP + DPVS_SO_GET_VERSION + DPVS_SO_GET_INFO + DPVS_SO_GET_SERVICES + DPVS_SO_GET_SERVICE + DPVS_SO_GET_DESTS + DPVSAGENT_SO_GET_SERVICES + SOCKOPT_SVC_MAX + + DPVSAGENT_VS_GET_DESTS + DPVSAGENT_VS_ADD_DESTS + DPVSAGENT_VS_EDIT_DESTS + DPVSAGENT_VS_DEL_DESTS + + SOCKOPT_SET_ROUTE_ADD + SOCKOPT_SET_ROUTE_DEL + SOCKOPT_SET_ROUTE_SET + SOCKOPT_SET_ROUTE_FLUSH + SOCKOPT_GET_ROUTE_SHOW + + SOCKOPT_SET_ROUTE6_ADD_DEL + SOCKOPT_SET_ROUTE6_FLUSH + SOCKOPT_GET_ROUTE6_SHOW + + DPVSAGENT_ROUTE_GET + DPVSAGENT_ROUTE_ADD + DPVSAGENT_ROUTE_DEL + DPVSAGENT_ROUTE6_GET + DPVSAGENT_ROUTE6_ADD + DPVSAGENT_ROUTE6_DEL + + DPVSAGENT_IFADDR_GET_BASE + DPVSAGENT_IFADDR_GET_STATS + DPVSAGENT_IFADDR_GET_VERBOSE + DPVSAGENT_IFADDR_ADD + DPVSAGENT_IFADDR_DEL + + SOCKOPT_SET_IFADDR_ADD + SOCKOPT_SET_IFADDR_DEL + SOCKOPT_SET_IFADDR_SET + SOCKOPT_SET_IFADDR_FLUSH + SOCKOPT_GET_IFADDR_SHOW + + SOCKOPT_NETIF_SET_LCORE + SOCKOPT_NETIF_SET_PORT + SOCKOPT_NETIF_SET_BOND + SOCKOPT_NETIF_SET_MAX + SOCKOPT_NETIF_GET_LCORE_MASK + SOCKOPT_NETIF_GET_LCORE_BASIC + SOCKOPT_NETIF_GET_LCORE_STATS + SOCKOPT_NETIF_GET_PORT_LIST + SOCKOPT_NETIF_GET_PORT_BASIC + SOCKOPT_NETIF_GET_PORT_STATS + SOCKOPT_NETIF_GET_PORT_XSTATS + SOCKOPT_NETIF_GET_PORT_EXT_INFO + SOCKOPT_NETIF_GET_BOND_STATUS + SOCKOPT_NETIF_GET_MAX + + SOCKOPT_SET_NEIGH_ADD + SOCKOPT_SET_NEIGH_DEL + SOCKOPT_GET_NEIGH_SHOW + + SOCKOPT_SET_BLKLST_ADD + SOCKOPT_SET_BLKLST_DEL + SOCKOPT_SET_BLKLST_FLUSH + SOCKOPT_GET_BLKLST_GETALL + + SOCKOPT_SET_WHTLST_ADD + SOCKOPT_SET_WHTLST_DEL + SOCKOPT_SET_WHTLST_FLUSH + SOCKOPT_GET_WHTLST_GETALL + + SOCKOPT_SET_VLAN_ADD + SOCKOPT_SET_VLAN_DEL + SOCKOPT_GET_VLAN_SHOW + + SOCKOPT_TC_ADD + SOCKOPT_TC_DEL + SOCKOPT_TC_CHANGE + SOCKOPT_TC_REPLACE + SOCKOPT_TC_SHOW + + SOCKOPT_SET_CONN + SOCKOPT_GET_CONN_ALL + SOCKOPT_GET_CONN_SPECIFIED + + SOCKOPT_IP6_SET + SOCKOPT_IP6_STATS + + SOCKOPT_TUNNEL_ADD + SOCKOPT_TUNNEL_DEL + SOCKOPT_TUNNEL_CHANGE + SOCKOPT_TUNNEL_REPLACE + SOCKOPT_TUNNEL_SHOW + + SOCKOPT_SET_KNI_ADD + SOCKOPT_SET_KNI_DEL + SOCKOPT_SET_KNI_FLUSH + SOCKOPT_GET_KNI_LIST + + SOCKOPT_SET_IPSET + SOCKOPT_GET_IPSET_TEST + SOCKOPT_GET_IPSET_LIST + + SOCKOPT_SET_IFTRAF_ADD + SOCKOPT_SET_IFTRAF_DEL + SOCKOPT_GET_IFTRAF_SHOW +) + +const ( + NETIF_NIC_PROMISC_ON = 1 << iota + NETIF_NIC_PROMISC_OFF + NETIF_NIC_LINK_UP + NETIF_NIC_LINK_DOWN + NETIF_NIC_FWD2KNI_ON + NETIF_NIC_FWD2KNI_OFF + NETIF_NIC_TC_EGRESS_ON + NETIF_NIC_TC_EGRESS_OFF + NETIF_NIC_TC_INGRESS_ON + NETIF_NIC_TC_INGRESS_OFF +) + +const ( + RTF_UP = 1 << iota + RTF_GATEWAY + RTF_HOST + RTF_REINSTATE + RTF_DYNAMIC + RTF_MODIFIED + RTF_MTU + RTF_WINDOW + RTF_IRTT + RTF_REJECT + + RTF_FORWARD + RTF_LOCALIN + RTF_DEFAULT + RTF_KNI + RTF_OUTWALL +) + +const ( + IFA_SCOPE_GLOBAL uint8 = iota + IFA_SCOPE_SITE + IFA_SCOPE_LINK + IFA_SCOPE_HOST + IFA_SCOPE_NONE = 255 +) diff --git a/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go b/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go new file mode 100644 index 000000000..97c180ce7 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go @@ -0,0 +1,56 @@ +package types + +type dpvsMatch struct { + af uint32 + srange ipRange + drange ipRange + iIfName [0x10]byte + oIfName [0x10]byte +} + +func (m *dpvsMatch) Copy(src *dpvsMatch) bool { + if src == nil { + return false + } + + m.af = src.af + + copy(m.iIfName[:], src.iIfName[:]) + copy(m.oIfName[:], src.oIfName[:]) + + if !m.srange.Copy(&src.srange) { + return false + } + if !m.drange.Copy(&src.drange) { + return false + } + return true +} + +func (m *dpvsMatch) SetAf(af uint32) { + m.af = af +} + +func (m *dpvsMatch) SetSrange(r *ipRange) { + m.srange.Copy(r) +} + +func (m *dpvsMatch) SetDrange(r *ipRange) { + m.drange.Copy(r) +} + +func (m *dpvsMatch) SetIifName(name []byte) { + copy(m.iIfName[:], name) +} + +func (m *dpvsMatch) SetOifName(name []byte) { + copy(m.oIfName[:], name) +} + +func (m *dpvsMatch) GetIifName() string { + return TrimRightZeros(string(m.iIfName[:])) +} + +func (m *dpvsMatch) GetOifName() string { + return TrimRightZeros(string(m.oIfName[:])) +} diff --git a/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go b/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go new file mode 100644 index 000000000..dfd02c1e0 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go @@ -0,0 +1,114 @@ +package types + +type dpvsStats struct { + conns uint64 + inPkts uint64 + inBytes uint64 + outPkts uint64 + outBytes uint64 + + cps uint32 + inPps uint32 + inBps uint32 + outPps uint32 + outBps uint32 + nop uint32 +} + +func (s *dpvsStats) Copy(src *dpvsStats) bool { + if src == nil { + return false + } + s.conns = src.conns + s.inPkts = src.inPkts + s.inBytes = src.inBytes + s.outPkts = src.outPkts + s.outBytes = src.outBytes + + s.cps = src.cps + s.inPps = src.inPps + s.inBps = src.inBps + s.outPps = src.outPps + s.outBps = src.outBps + return true +} + +func (s *dpvsStats) SetConns(c uint64) { + s.conns = c +} + +func (s *dpvsStats) SetInPkts(p uint64) { + s.inPkts = p +} + +func (s *dpvsStats) SetInBytes(b uint64) { + s.inBytes = b +} + +func (s *dpvsStats) SetOutPkts(p uint64) { + s.outPkts = p +} + +func (s *dpvsStats) SetOutBytes(b uint64) { + s.outBytes = b +} + +func (s *dpvsStats) SetCps(c uint32) { + s.cps = c +} + +func (s *dpvsStats) SetInPps(p uint32) { + s.inPps = p +} + +func (s *dpvsStats) SetInBps(b uint32) { + s.inBps = b +} + +func (s *dpvsStats) SetOutPps(p uint32) { + s.outPps = p +} + +func (s *dpvsStats) SetOutBps(b uint32) { + s.outBps = b +} + +func (s *dpvsStats) GetConns() uint64 { + return s.conns +} + +func (s *dpvsStats) GetInPkts() uint64 { + return s.inPkts +} + +func (s *dpvsStats) GetInBytes() uint64 { + return s.inBytes +} + +func (s *dpvsStats) GetOutPkts() uint64 { + return s.outPkts +} + +func (s *dpvsStats) GetOutBytes() uint64 { + return s.outBytes +} + +func (s *dpvsStats) GetCps() uint32 { + return s.cps +} + +func (s *dpvsStats) GetInPps() uint32 { + return s.inPps +} + +func (s *dpvsStats) GetInBps() uint32 { + return s.inBps +} + +func (s *dpvsStats) GetOutPps() uint32 { + return s.outPps +} + +func (s *dpvsStats) GetOutBps() uint32 { + return s.outBps +} diff --git a/tools/dpvs-agent/pkg/ipc/types/getmodel.go b/tools/dpvs-agent/pkg/ipc/types/getmodel.go new file mode 100644 index 000000000..6196594b2 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/getmodel.go @@ -0,0 +1,169 @@ +package types + +import ( + "github.com/dpvs-agent/models" +) + +func (vs *VirtualServerSpec) GetModel() *models.VirtualServerSpecExpand { + modelVs := &models.VirtualServerSpecExpand{ + Addr: vs.GetAddr(), + Af: vs.GetAf(), + Bps: vs.GetBps(), + ConnTimeout: vs.GetConnTimeout(), + LimitProportion: vs.GetLimitProportion(), + Netmask: vs.GetNetMask(), + Port: vs.GetPort(), + Proto: vs.GetProto(), + Fwmark: vs.GetFwmark(), + SyncProxy: "false", + ExpireQuiescent: "false", + SchedName: vs.GetSchedName(), + Timeout: vs.GetTimeout(), + Match: vs.match.GetModel(), + Stats: vs.stats.GetModel(), + DestCheck: vs.GetDestCheck(), + } + + flags := "" + if (vs.GetFlags() & DPVS_CONN_F_SYNPROXY) != 0 { + modelVs.SyncProxy = "true" + flags += "SynProxy|" + } + + if (vs.GetFlags() & DPVS_CONN_F_EXPIRE_QUIESCENT) != 0 { + modelVs.ExpireQuiescent = "true" + flags += "ExpireQuiescent|" + } + + if (vs.GetFlags() & DPVS_SVC_F_QID_HASH) != 0 { + flags += "ConHashByQuicID|" + } + if (vs.GetFlags() & DPVS_SVC_F_SIP_HASH) != 0 { + flags += "ConHashBySrcIP|" + } + + modelVs.Flags = flags + + return modelVs +} + +func (ir *ipRange) GetModel() *models.AddrRange { + return &models.AddrRange{ + Start: ir.GetMinAddr(), + End: ir.GetMaxAddr(), + } +} + +func (dm *dpvsMatch) GetModel() *models.MatchSpec { + return &models.MatchSpec{ + Dest: dm.drange.GetModel(), + Src: dm.srange.GetModel(), + InIfName: dm.GetIifName(), + OutIfName: dm.GetOifName(), + } +} + +func (rs *RealServerSpec) GetModel() *models.RealServerSpecExpand { + overloaded := rs.GetOverloaded() + inhibited := rs.GetInhibited() + return &models.RealServerSpecExpand{ + Spec: &models.RealServerSpecTiny{ + IP: rs.GetAddr(), + Mode: rs.GetFwdModeString(), + Port: rs.GetPort(), + Weight: (uint16)(rs.GetWeight()), + Overloaded: &overloaded, + Inhibited: &inhibited, + }, + Stats: rs.stats.GetModel(), + } +} + +type ServerStats models.ServerStats + +func (dst *ServerStats) Increase(src *ServerStats) { + dst.Conns += src.Conns + dst.InPkts += src.InPkts + dst.InBytes += src.InBytes + dst.OutPkts += src.OutPkts + dst.OutBytes += src.OutBytes + + dst.Cps += src.Cps + dst.InBps += src.InBps + dst.InPps += src.InPps + dst.OutBps += src.OutBps + dst.OutPps += src.OutPps +} + +func (stats *dpvsStats) GetModel() *models.ServerStats { + return &models.ServerStats{ + Conns: stats.GetConns(), + InPkts: stats.GetInPkts(), + InBytes: stats.GetInBytes(), + OutPkts: stats.GetOutPkts(), + OutBytes: stats.GetOutBytes(), + + Cps: stats.GetCps(), + InBps: stats.GetInBps(), + InPps: stats.GetInPps(), + OutBps: stats.GetOutBps(), + OutPps: stats.GetOutPps(), + } +} + +func (nic *NetifNicQueue) GetModel() []models.NicDeviceQueueData { + nicDataQueue := make([]models.NicDeviceQueueData, len(nic.queue)) + for i, data := range nic.queue { + nicDataQueue[i] = (models.NicDeviceQueueData)(data) + } + return nicDataQueue +} + +func (stats *NetifNicStats) GetModel() *models.NicDeviceStats { + nicStats := &models.NicDeviceStats{ + BufAvail: stats.GetMBufAvail(), + BufInuse: stats.GetMBufInuse(), + ID: stats.GetID(), + InBytes: stats.GetInBytes(), + InErrors: stats.GetInErrors(), + InMissed: stats.GetInMissed(), + InPkts: stats.GetInPkts(), + OutBytes: stats.GetOutBytes(), + OutPkts: stats.GetOutPkts(), + OutErrors: stats.GetOutErrors(), + RxNoMbuf: stats.GetRxNoMbuf(), + InBytesQ: stats.inBytesQ.GetModel(), + InPktsQ: stats.inPktsQ.GetModel(), + OutBytesQ: stats.outBytesQ.GetModel(), + OutPktsQ: stats.outPktsQ.GetModel(), + ErrorBytesQ: stats.errorQ.GetModel(), + } + return nicStats +} + +func (detail *NetifNicDetail) GetModel() *models.NicDeviceDetail { + return &models.NicDeviceDetail{ + Flags: detail.GetFlags(), + ID: detail.GetID(), + MTU: detail.GetMTU(), + Addr: detail.GetAddr(), + Autoneg: detail.GetLinkAutoNeg(), + Duplex: detail.GetLinkDuplex(), + NRxQ: detail.GetRxQueueCount(), + NTxQ: detail.GetTxQueueCount(), + Name: detail.GetName(), + SocketID: detail.GetSocketID(), + Speed: detail.GetSpeed(), + Status: detail.GetStatus(), + } +} + +func (laddr *LocalAddrDetail) GetModel() *models.LocalAddressSpecExpand { + return &models.LocalAddressSpecExpand{ + Af: laddr.GetAf(), + Addr: laddr.GetAddr(), + Conns: laddr.GetConns(), + Device: laddr.GetIfName(), + PortConflict: laddr.GetPortConflict(), + } +} diff --git a/tools/dpvs-agent/pkg/ipc/types/inetaddr.go b/tools/dpvs-agent/pkg/ipc/types/inetaddr.go new file mode 100644 index 000000000..661c31f09 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/inetaddr.go @@ -0,0 +1,571 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type InetAddrFront struct { + count uint32 +} + +func NewInetAddrFront() *InetAddrFront { + return &InetAddrFront{} +} + +func (o *InetAddrFront) GetCount() uint32 { + return o.count +} + +func (o *InetAddrFront) SetCount(c uint32) { + o.count = c +} + +func (o *InetAddrFront) Copy(src *InetAddrFront) bool { + o.count = src.count + return true +} + +func (o *InetAddrFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *InetAddrFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *InetAddrFront = *(**InetAddrFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *InetAddrFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *InetAddrFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*InetAddrFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to InetAddrFront") + } + + fronts := make([]*InetAddrFront, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i] = NewInetAddrFront() + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *InetAddrFront) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type InetAddrStats struct { + addr [0x10]byte + used uint32 + free uint32 + miss uint32 +} + +func NewInetAddrStats() *InetAddrStats { + return &InetAddrStats{} +} + +func (o *InetAddrStats) GetUsed() uint32 { + return o.used +} + +func (o *InetAddrStats) GetFree() uint32 { + return o.free +} + +func (o *InetAddrStats) GetMiss() uint32 { + return o.miss +} + +func (o *InetAddrStats) Copy(src *InetAddrStats) bool { + o.used = src.used + o.free = src.free + o.miss = src.miss + copy(o.addr[:], src.addr[:]) + return true +} + +func (o *InetAddrStats) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *InetAddrStats) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *InetAddrStats = *(**InetAddrStats)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *InetAddrStats) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *InetAddrStats) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*InetAddrStats, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to InetAddrStats") + } + + stats := make([]*InetAddrStats, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + stats[i] = NewInetAddrStats() + stats[i].Dump(buf) + } + + return stats, nil +} + +func (o *InetAddrStats) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type InetAddrDetail struct { + af uint32 + validLft uint32 + preferedLft uint32 + flags uint32 + ifName [0x10]byte + bcast [0x10]byte + addr [0x10]byte + plen uint8 + scope uint8 + cid uint8 + nop uint8 +} + +func NewInetAddrDetail() *InetAddrDetail { + return &InetAddrDetail{} +} + +func (o *InetAddrDetail) Copy(src *InetAddrDetail) bool { + o.af = src.af + o.validLft = src.validLft + o.preferedLft = src.preferedLft + o.flags = src.flags + o.plen = src.plen + o.scope = src.scope + o.cid = src.cid + + copy(o.ifName[:], src.ifName[:]) + copy(o.addr[:], src.addr[:]) + copy(o.bcast[:], src.bcast[:]) + + return true +} + +func (o *InetAddrDetail) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *InetAddrDetail) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *InetAddrDetail = *(**InetAddrDetail)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *InetAddrDetail) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *InetAddrDetail) GetAddr() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.addr[0], o.addr[1], o.addr[2], o.addr[3]) + return addr.String() + } + + addr = net.IP{o.addr[0x0], o.addr[0x1], o.addr[0x2], o.addr[0x3], + o.addr[0x4], o.addr[0x5], o.addr[0x6], o.addr[0x7], + o.addr[0x8], o.addr[0x9], o.addr[0xa], o.addr[0xb], + o.addr[0xc], o.addr[0xd], o.addr[0xe], o.addr[0xf], + } + return addr.String() +} + +func (o *InetAddrDetail) GetIfName() string { + return TrimRightZeros(string(o.ifName[:])) +} + +func (o *InetAddrDetail) SetAf(af uint32) { + o.af = af +} + +func (o *InetAddrDetail) SetValidLft(lft string) error { + if strings.EqualFold(strings.ToLower(lft), "forever") { + o.validLft = 0 + } else { + i, err := strconv.Atoi(lft) + if err != nil { + return err + } + o.validLft = uint32(i) + } + return nil +} + +func (o *InetAddrDetail) SetPreferedLft(lft string) error { + if strings.EqualFold(strings.ToLower(lft), "forever") { + o.preferedLft = 0 + } else { + i, err := strconv.Atoi(lft) + if err != nil { + return err + } + o.preferedLft = uint32(i) + } + return nil +} + +func (o *InetAddrDetail) SetPlen(len uint8) { + o.plen = len +} + +const ( + IFA_F_SAPOOL uint32 = 0x10000 + IFA_F_OPS_VERBOSE uint32 = 0x0001 + IFA_F_OPS_STATS uint32 = 0x0002 +) + +func (o *InetAddrDetail) SetFlags(flags string) { + switch strings.ToLower(flags) { + case "verbose": + o.flags |= IFA_F_OPS_VERBOSE + case "stats": + o.flags |= IFA_F_OPS_STATS + case "sapool": + o.flags |= IFA_F_SAPOOL + } +} + +func (o *InetAddrDetail) SetScope(scope string) { + value, err := strconv.ParseUint(scope, 10, 8) + if err == nil { + o.scope = uint8(value) + return + } + + switch strings.ToLower(scope) { + case "host": + o.scope = IFA_SCOPE_HOST + case "link": + o.scope = IFA_SCOPE_LINK + case "global": + fallthrough + default: + o.scope = IFA_SCOPE_GLOBAL + // o.scope = 255 + } +} + +func (o *InetAddrDetail) SetCid(cid uint8) { + o.cid = cid +} + +func (o *InetAddrDetail) SetIfName(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *InetAddrDetail) setAddr(addr string) { + if strings.Contains(addr, ":") { + copy(o.addr[:], net.ParseIP(addr)) + o.af = unix.AF_INET6 + return + } + + o.af = unix.AF_INET + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.addr[:], buf.Bytes()[12:]) +} + +func (o *InetAddrDetail) SetAddr(addr string) { + var plen, ip string + + if strings.Index(addr, "/") != -1 { + plen = addr[strings.Index(addr, "/")+1:] + ip = addr[:strings.Index(addr, "/")] + } else { + ip = addr + plen = "32" + + if strings.Contains(ip, ":") { + plen = "128" + } + } + + o.setAddr(ip) + + value, err := strconv.ParseUint(plen, 10, 8) + if err == nil { + o.SetPlen(uint8(value)) + } +} + +func (o *InetAddrDetail) SetBCast(addr string) { + if len(addr) == 0 { + return + } + if strings.Contains(addr, ":") { + copy(o.bcast[:], net.ParseIP(addr)) + } else { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.bcast[:], buf.Bytes()[12:]) + } +} + +func (o *InetAddrDetail) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*InetAddrDetail, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to InetAddrDetail") + } + + details := make([]*InetAddrDetail, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + details[i] = NewInetAddrDetail() + details[i].Dump(buf) + } + + return details, nil +} + +func (o *InetAddrDetail) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +/**************** +****************/ +func (o *InetAddrDetail) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*InetAddrDetail, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_IFADDR_GET_BASE, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE Write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE Write specific inetaddr failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE reply msg Read failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE failed", "result", result) + err = fmt.Errorf("Sockopt DPVSAGENT_IFADDR_GET_BASE reply ErrorCode: %s", result) + return nil, err + } + + front := NewInetAddrFront() + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE read table header failed", "Error", err.Error()) + return nil, err + } + + return o.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +func (o *InetAddrDetail) Add(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + traceName := fmt.Sprintf("dpip addr add %s dev %s", o.GetAddr(), o.GetIfName()) + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_IFADDR_ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_ADD Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_ADD write inetaddr detail failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_ADD reply msg Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + addr := o.GetAddr() + logger.Info("Sockopt DPVSAGENT_IFADDR_ADD done", "addr", addr, "result", result) + return errCode +} + +func (o *InetAddrDetail) Del(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + traceName := fmt.Sprintf("dpip addr del %s dev %s", o.GetAddr(), o.GetIfName()) + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_IFADDR_DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_DEL Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_DEL write del inetaddr detail failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_DEL Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + addr := o.GetAddr() + logger.Info("Sockopt DPVSAGENT_IFADDR_DEL done", "addr", addr, "del", "result", result) + return errCode +} + +func (o *InetAddrStats) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*InetAddrStats, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_IFADDR_GET_STATS, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_STATS Write proto header failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_STATS reply msg Read failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST failed", "result", result) + err = fmt.Errorf("Sockopt SOCKOPT_GET_KNI_LIST failed. ErrorCode: %s", reply.GetErrStr()) + return nil, err + } + + front := NewInetAddrFront() + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST read table header failed", "Error", err.Error()) + return nil, err + } + + return o.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} diff --git a/tools/dpvs-agent/pkg/ipc/types/iprange.go b/tools/dpvs-agent/pkg/ipc/types/iprange.go new file mode 100644 index 000000000..d35182498 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/iprange.go @@ -0,0 +1,43 @@ +package types + +type ipRange struct { + minAddr [0x10]byte + maxAddr [0x10]byte + minPort uint16 + maxPort uint16 +} + +func (r *ipRange) Copy(src *ipRange) bool { + if src == nil { + return false + } + copy(r.minAddr[:], src.minAddr[:]) + copy(r.maxAddr[:], src.maxAddr[:]) + r.minPort = src.minPort + r.maxPort = src.maxPort + return true +} + +func (r *ipRange) SetMinAddr(addr []byte) { + copy(r.minAddr[:], addr) +} + +func (r *ipRange) SetMaxAddr(addr []byte) { + copy(r.maxAddr[:], addr) +} + +func (r *ipRange) GetMinAddr() string { + return TrimRightZeros(string(r.minAddr[:])) +} + +func (r *ipRange) GetMaxAddr() string { + return TrimRightZeros(string(r.maxAddr[:])) +} + +func (r *ipRange) SetMinPort(port uint16) { + r.minPort = port +} + +func (r *ipRange) SetMaxPort(port uint16) { + r.maxPort = port +} diff --git a/tools/dpvs-agent/pkg/ipc/types/kni.go b/tools/dpvs-agent/pkg/ipc/types/kni.go new file mode 100644 index 000000000..afa2d0cff --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/kni.go @@ -0,0 +1,314 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type KniAddrFlowFront struct { + count uint32 +} + +type KniAddrFlowEntry struct { + af uint32 + addr [0x10]byte +} + +type KniAddrFlowSpec struct { + flags uint32 + ifName [0x10]byte + entry KniAddrFlowEntry +} + +func NewKniAddrFlowFront() *KniAddrFlowFront { + return &KniAddrFlowFront{} +} + +func NewKniAddrFlowSpec() *KniAddrFlowSpec { + return &KniAddrFlowSpec{flags: 1} +} + +func NewKniAddrFlowEntry() *KniAddrFlowEntry { + return &KniAddrFlowEntry{} +} + +func (o *KniAddrFlowSpec) Copy(src *KniAddrFlowSpec) bool { + o.flags = src.flags + copy(o.ifName[:], src.ifName[:]) + return o.entry.Copy(&src.entry) +} + +func (o *KniAddrFlowEntry) Copy(src *KniAddrFlowEntry) bool { + o.af = src.af + copy(o.addr[:], src.addr[:]) + return true +} + +func (o *KniAddrFlowFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *KniAddrFlowSpec) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *KniAddrFlowEntry) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *KniAddrFlowFront) Copy(src *KniAddrFlowFront) bool { + o.count = src.count + return true +} + +func (o *KniAddrFlowFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *KniAddrFlowFront = *(**KniAddrFlowFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *KniAddrFlowSpec) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *KniAddrFlowSpec = *(**KniAddrFlowSpec)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *KniAddrFlowEntry) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *KniAddrFlowEntry = *(**KniAddrFlowEntry)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *KniAddrFlowFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *KniAddrFlowSpec) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *KniAddrFlowEntry) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *KniAddrFlowSpec) SetFlags(flags uint32) { + o.flags = 1 // must be 1 +} + +func (o *KniAddrFlowSpec) SetDevice(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *KniAddrFlowEntry) SetAf(af uint32) { + o.af = af +} + +func (o *KniAddrFlowEntry) SetAddr(addr string) { + if strings.Contains(addr, ":") { + o.SetAf(unix.AF_INET6) + copy(o.addr[:], net.ParseIP(addr)) + return + } + + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.addr[:], buf.Bytes()[12:]) +} + +func (o *KniAddrFlowFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*KniAddrFlowFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("buffer may not convert to KniAddrFlowFront") + } + + fronts := make([]*KniAddrFlowFront, cnt) + for i := 0; i < int(cnt); i++ { + fronts[i] = NewKniAddrFlowFront() + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *KniAddrFlowSpec) write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (o *KniAddrFlowEntry) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*KniAddrFlowEntry, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("buffer may not convert to KniAddrFlowEntry") + } + + entries := make([]*KniAddrFlowEntry, cnt) + for i := 0; i < int(cnt); i++ { + entries[i] = NewKniAddrFlowEntry() + err := conn.Read(entries[i]) + if err != nil { + continue + } + } + + logger.Info("Get Kni Addr success", "entries", entries) + return entries, nil +} + +func (o *KniAddrFlowSpec) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*KniAddrFlowEntry, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, SOCKOPT_GET_KNI_LIST, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST Write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := o.write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST write spec kni failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST Read reply failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST failed", "result", result) + err = fmt.Errorf("Sockopt SOCKOPT_GET_KNI_LIST reply ErrorCode: %s", reply.GetErrStr()) + return nil, err + } + + front := NewKniAddrFlowFront() + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST read table header failed", "Error", err.Error()) + return nil, err + } + + entry := NewKniAddrFlowEntry() + return entry.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +func (o *KniAddrFlowSpec) Add(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var ADD uint32 + ADD = SOCKOPT_SET_KNI_ADD + + msg := NewSockMsg(SOCKOPT_VERSION, ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_ADD Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + err = o.write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_ADD write spec kni failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_ADD Read reply failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + logger.Info("Sockopt SOCKOPT_SET_KNI_ADD Done:", errCode.String()) + return errCode +} + +func (o *KniAddrFlowSpec) Del(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_DEL Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var DEL uint32 + DEL = SOCKOPT_SET_KNI_DEL + + msg := NewSockMsg(SOCKOPT_VERSION, DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_DEL Write spec kni failed", "Error", err.Error()) + return EDPVS_IO + } + err = o.write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_DEL write spec kni failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_DEL Read reply failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("Sockopt SOCKOPT_SET_KNI_DEL Done", "result", result) + return errCode +} diff --git a/tools/dpvs-agent/pkg/ipc/types/laddr.go b/tools/dpvs-agent/pkg/ipc/types/laddr.go new file mode 100644 index 000000000..7e16f8763 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/laddr.go @@ -0,0 +1,492 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type LocalAddrFront struct { + af uint32 + port uint32 + proto uint32 + fwmark uint32 + cid uint32 + count uint32 + addr [0x10]byte + match dpvsMatch + nop uint32 +} + +func NewLocalAddrFront() *LocalAddrFront { + return &LocalAddrFront{} +} + +func (o *LocalAddrFront) ID() string { + proto := "tcp" + if o.proto == unix.IPPROTO_UDP { + proto = "udp" + } + return fmt.Sprintf("%s-%d-%s", o.GetAddr(), o.GetPort(), proto) +} + +func (o *LocalAddrFront) GetPort() uint32 { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(o.port)) + port := binary.BigEndian.Uint16(buf.Bytes()) + return uint32(port) +} + +func (o *LocalAddrFront) GetAddr() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.addr[0], o.addr[1], o.addr[2], o.addr[3]) + return addr.String() + } + + addr = net.IP{o.addr[0x0], o.addr[0x1], o.addr[0x2], o.addr[0x3], + o.addr[0x4], o.addr[0x5], o.addr[0x6], o.addr[0x7], + o.addr[0x8], o.addr[0x9], o.addr[0xa], o.addr[0xb], + o.addr[0xc], o.addr[0xd], o.addr[0xe], o.addr[0xf], + } + return addr.String() +} + +func (o *LocalAddrFront) GetAf() uint32 { + return o.af +} + +func (o *LocalAddrFront) SetAf(af uint32) { + o.af = af +} +func (o *LocalAddrFront) SetAfByAddr(addr string) { + i := strings.Index(addr, "/") + if i != -1 { + i = len(addr) + } + + if strings.Count(addr[:i], ".") == 3 { + o.af = unix.AF_INET + } + if strings.Count(addr[:i], ":") >= 2 { + o.af = unix.AF_INET6 + } +} +func (o *LocalAddrFront) SetPort(port uint32) { + o.port = port +} +func (o *LocalAddrFront) SetProto(proto uint32) { + o.proto = proto +} +func (o *LocalAddrFront) SetFwmark(fwmark uint32) { + o.fwmark = fwmark +} + +func (o *LocalAddrFront) ParseVipPortProto(vipport string) error { + vip := strings.Split(vipport, "-")[0] + port := strings.Split(vipport, "-")[1] + proto := strings.Split(vipport, "-")[2] + + switch strings.ToLower(proto) { + case "udp": + o.proto = unix.IPPROTO_UDP + default: + o.proto = unix.IPPROTO_TCP + } + + value, err := strconv.Atoi(port) + if err != nil { + return err + } + + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(value)) + + o.port = uint32(binary.BigEndian.Uint16(buf.Bytes())) + if strings.Contains(vipport, ":") { + o.af = unix.AF_INET6 + copy(o.addr[:], net.ParseIP(vip)) + } else { + o.af = unix.AF_INET + + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(vip)) + copy(o.addr[:], buf.Bytes()[12:]) + } + + return nil +} + +func (o *LocalAddrFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *LocalAddrFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *LocalAddrFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *LocalAddrFront = *(**LocalAddrFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *LocalAddrFront) Copy(src *LocalAddrFront) bool { + if src == nil { + return false + } + + o.af = src.af + o.port = src.port + o.proto = src.proto + o.fwmark = src.fwmark + o.cid = src.cid + o.count = src.count + + copy(o.addr[:], src.addr[:]) + + return o.match.Copy(&src.match) +} + +func (o *LocalAddrFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*LocalAddrFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("buffer may not convert to LocalAddrFront") + } + + fronts := make([]*LocalAddrFront, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i] = NewLocalAddrFront() + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *LocalAddrFront) write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type LocalAddrDetail struct { + af uint32 + conns uint32 + portConflict uint64 + addr [0x10]byte + ifName [unix.IFNAMSIZ]byte +} + +func NewLocalAddrDetail() *LocalAddrDetail { + return &LocalAddrDetail{} +} + +func (o *LocalAddrDetail) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *LocalAddrDetail) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *LocalAddrDetail) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *LocalAddrDetail = *(**LocalAddrDetail)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *LocalAddrDetail) SetAf(af uint32) { + o.af = af +} + +func (o *LocalAddrDetail) GetAf() uint32 { + return o.af +} + +func (o *LocalAddrDetail) GetConns() uint32 { + return o.conns +} + +func (o *LocalAddrDetail) GetPortConflict() uint64 { + return o.portConflict +} + +func (o *LocalAddrDetail) SetAfByAddr(addr string) { + i := strings.Index(addr, "/") + if i != -1 { + i = len(addr) + } + + if strings.Count(addr[:i], ":") >= 2 { + o.af = unix.AF_INET6 + } + if strings.Count(addr[:i], ".") == 3 { + o.af = unix.AF_INET + } +} + +func (o *LocalAddrDetail) GetAddr() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.addr[0], o.addr[1], o.addr[2], o.addr[3]) + return addr.String() + } + + addr = net.IP{o.addr[0x0], o.addr[0x1], o.addr[0x2], o.addr[0x3], + o.addr[0x4], o.addr[0x5], o.addr[0x6], o.addr[0x7], + o.addr[0x8], o.addr[0x9], o.addr[0xa], o.addr[0xb], + o.addr[0xc], o.addr[0xd], o.addr[0xe], o.addr[0xf], + } + return addr.String() +} + +func (o *LocalAddrDetail) SetAddr(addr string) { + if strings.Contains(addr, ":") { + copy(o.addr[:], net.ParseIP(addr)) + } else { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.addr[:], buf.Bytes()[12:]) + } +} + +func (o *LocalAddrDetail) GetIfName() string { + return TrimRightZeros(string(o.ifName[:])) +} + +func (o *LocalAddrDetail) SetIfName(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *LocalAddrDetail) Copy(src *LocalAddrDetail) bool { + if src == nil { + return false + } + + o.af = src.af + o.conns = src.conns + o.portConflict = src.portConflict + + copy(o.addr[:], src.addr[:]) + copy(o.ifName[:], src.ifName[:]) + + return true +} + +func (o *LocalAddrDetail) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*LocalAddrDetail, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("buffer may not convert to LocalAddrEntry") + } + + details := make([]*LocalAddrDetail, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + // logger.Info(fmt.Sprintf("fetch RAW local address from dpvs (%d): %x", o.Sizeof(), buf)) + details[i] = NewLocalAddrDetail() + details[i].Dump(buf) + } + + logger.Info("Get Local Addr Done", "details", details) + return details, nil +} + +func (o *LocalAddrDetail) write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +/**************** +****************/ +func (o *LocalAddrFront) Get(cp *pool.ConnPool, parentLogger hclog.Logger) ([]*LocalAddrDetail, error) { + logger := hclog.Default().Named(o.ID()) + if parentLogger != nil { + logger = parentLogger.Named(o.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_GET_LADDR, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := o.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR write laddr table header failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR Read sockmsg failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR failed", "result", result) + err = fmt.Errorf("Sockopt DPVSAGENT_VS_GET_LADDR reply ErrorCode: %s", result) + return nil, err + } + + _, err = o.read(conn, o.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR read table header failed", "Error", err.Error()) + return nil, err + } + + detail := NewLocalAddrDetail() + return detail.read(conn, uint64(reply.GetLen())-o.Sizeof(), logger) +} + +func (o *LocalAddrFront) Add(details []*LocalAddrDetail, cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(o.ID()) + if parentLogger != nil { + logger = parentLogger.Named(o.ID()) + } + + if len(details) == 0 { + logger.Info("There are No laddr to set, return immediately") + return EDPVS_OK + } + o.count = uint32(len(details)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_ADD_LADDR, SOCKOPT_SET, o.Sizeof()+uint64(len(details))*details[0].Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_LADDR write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := o.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_LADDR write laddr table header failed", "Error", err.Error()) + return EDPVS_IO + } + + for _, detail := range details { + if err := detail.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_LADDR write spec laddr failed", "Error", err.Error()) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_LADDR Read reply failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVSAGENT_VS_ADD_LADDR Done", "details", details, "result", result) + return errCode +} + +func (o *LocalAddrFront) Del(details []*LocalAddrDetail, cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(o.ID()) + if parentLogger != nil { + logger = parentLogger.Named(o.ID()) + } + + if len(details) == 0 { + logger.Info("There are No laddr to del, return immediately") + return EDPVS_OK + } + o.count = uint32(len(details)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_DEL_LADDR, SOCKOPT_SET, o.Sizeof()+uint64(len(details))*details[0].Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_LADDR Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := o.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_LADDR write laddr table header failed", "Error", err.Error()) + return EDPVS_IO + } + + for _, detail := range details { + if err := detail.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_LADDR write spec laddr failed", "Error", err.Error()) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_LADDR Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVSAGENT_VS_DEL_LADDR", "details", details, " Done", "result", result) + return errCode +} diff --git a/tools/dpvs-agent/pkg/ipc/types/method.go b/tools/dpvs-agent/pkg/ipc/types/method.go new file mode 100644 index 000000000..ab1254f4c --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/method.go @@ -0,0 +1 @@ +package types diff --git a/tools/dpvs-agent/pkg/ipc/types/netif.go b/tools/dpvs-agent/pkg/ipc/types/netif.go new file mode 100644 index 000000000..f403ebb03 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/netif.go @@ -0,0 +1,728 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + // "errors" + "fmt" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type NetifNicDesc struct { + name [0x20]byte + mac [0x12]byte + flags uint16 +} + +func NewNetifNicDesc() *NetifNicDesc { + return &NetifNicDesc{} +} + +func (o *NetifNicDesc) Copy(src *NetifNicDesc) bool { + o.flags = src.flags + copy(o.name[:], src.name[:]) + copy(o.mac[:], src.mac[:]) + return true +} + +func (o *NetifNicDesc) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicDesc) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicDesc = *(**NetifNicDesc)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicDesc) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *NetifNicDesc) SetName(device string) { + copy(o.name[:], device[:]) +} + +func (o *NetifNicDesc) SetMac(mac string) { + // not set in user plane +} + +func (o *NetifNicDesc) SetPromisc(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("promisc_on") + return true + case "off", "down", "false": + o.setFlags("promisc_off") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) SetLink(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("link_status_up") + return true + case "off", "down", "false": + o.setFlags("link_status_down") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) SetFwd2Kni(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("forward2kni_on") + return true + case "off", "down", "false": + o.setFlags("forward2kni_off") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) SetTcEgress(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("tc_egress_on") + return true + case "off", "down", "false": + o.setFlags("tc_egress_off") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) SetTcIngress(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("tc_ingress_on") + return true + case "off", "down", "false": + o.setFlags("tc_ingress_off") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) setFlags(flags string) { + bak := o.flags + + o.flags = o.flags ^ o.flags + + switch strings.ToLower(flags) { + case "promisc_on": + o.flags |= NETIF_NIC_PROMISC_ON + case "promisc_off": + o.flags |= NETIF_NIC_PROMISC_OFF + case "link_status_up": + o.flags |= NETIF_NIC_LINK_UP + case "link_status_down": + o.flags |= NETIF_NIC_LINK_DOWN + case "forward2kni_on": + o.flags |= NETIF_NIC_FWD2KNI_ON + case "forward2kni_off": + o.flags |= NETIF_NIC_FWD2KNI_OFF + case "tc_egress_on": + o.flags |= NETIF_NIC_TC_EGRESS_ON + case "tc_egress_off": + o.flags |= NETIF_NIC_TC_EGRESS_OFF + case "tc_ingress_on": + o.flags |= NETIF_NIC_TC_INGRESS_ON + case "tc_ingress_off": + o.flags |= NETIF_NIC_TC_INGRESS_OFF + default: + o.flags |= bak + } +} + +func (o *NetifNicDesc) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (o *NetifNicDesc) Set(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var SET uint32 + SET = SOCKOPT_NETIF_SET_PORT + + msg := NewSockMsg(SOCKOPT_VERSION, SET, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_SET_PORT Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_SET_PORT write specific port failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_SET_PORT reply msg Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("Sockopt SOCKOPT_NETIF_SET_PORT Done", "result", result) + return errCode +} + +type NetifNicEntryFront struct { + count uint16 + phyBase uint16 + phyEnd uint16 + bondBase uint16 + bondEnd uint16 +} + +func NewNetifNicEntryFront() *NetifNicEntryFront { + return &NetifNicEntryFront{} +} + +func (o *NetifNicEntryFront) Copy(src *NetifNicEntryFront) bool { + o.count = src.count + o.phyBase = src.phyBase + o.phyEnd = src.phyEnd + o.bondBase = src.bondBase + o.bondEnd = src.bondEnd + return true +} + +func (o *NetifNicEntryFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicEntryFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicEntryFront = *(**NetifNicEntryFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicEntryFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *NetifNicEntryFront) read(conn *pool.Conn, logger hclog.Logger) error { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +type NetifNicEntry struct { + id uint16 + name [0x10]byte +} + +func (o *NetifNicEntry) GetID() uint16 { + return o.id +} + +func (o *NetifNicEntry) GetName() string { + return TrimRightZeros(string(o.name[:])) +} + +func NewNetifNicEntry() *NetifNicEntry { + return &NetifNicEntry{} +} + +func (o *NetifNicEntry) Copy(src *NetifNicEntry) bool { + copy(o.name[:], src.name[:]) + o.id = src.id + return true +} + +func (o *NetifNicEntry) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicEntry) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicEntry = *(**NetifNicEntry)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicEntry) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *NetifNicEntry) read(conn *pool.Conn, logger hclog.Logger) error { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +type NetifNicEntries struct { + Front *NetifNicEntryFront + Entries []*NetifNicEntry +} + +func NewNetifNicEntries() *NetifNicEntries { + return &NetifNicEntries{Front: NewNetifNicEntryFront()} +} + +func (o *NetifNicDesc) GetPortList(cp *pool.ConnPool, logger hclog.Logger) (*NetifNicEntries, DpvsErrType) { + var GET uint32 + GET = SOCKOPT_NETIF_GET_PORT_LIST + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST Write proto header failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST write specific port failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST reply msg Read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if reply.GetErrCode() != EDPVS_OK { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST failed.", "reply", reply.GetErrStr()) + return nil, reply.GetErrCode() + } + + nic := NewNetifNicEntries() + + err = nic.Front.read(conn, logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST table header read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if nic.Front.count <= 0 { + return nic, EDPVS_OK + } + + entry := NewNetifNicEntry() + resLen := int(reply.GetLen()) - int(nic.Front.Sizeof()) + if resLen != int(entry.Sizeof())*int(nic.Front.count) { + conn.Release(resLen) + logger.Error(fmt.Sprintf("buffer may not convert to %d count NetifNicEntry", nic.Front.count)) + return nil, EDPVS_IO + } + + nic.Entries = make([]*NetifNicEntry, nic.Front.count) + + for i := 0; i < int(nic.Front.count); i++ { + nic.Entries[i] = NewNetifNicEntry() + nic.Entries[i].read(conn, logger) + } + return nic, EDPVS_OK +} + +type NetifNicDetail struct { + name [0x20]byte + addr [0x20]byte + status [0x10]byte + duplex [0x10]byte + autoneg [0x10]byte + speed uint32 + nrxq uint8 + ntxq uint8 + padding [0x3]uint8 + socketId uint8 + id uint16 + mtu uint16 + flags uint16 +} + +func NewNetifNicDetail() *NetifNicDetail { + return &NetifNicDetail{} +} + +func (o *NetifNicDetail) Copy(src *NetifNicDetail) bool { + o.speed = src.speed + o.nrxq = src.nrxq + o.ntxq = src.ntxq + o.socketId = src.socketId + o.id = src.id + o.mtu = src.mtu + o.flags = src.flags + copy(o.name[:], src.name[:]) + copy(o.addr[:], src.addr[:]) + copy(o.status[:], src.status[:]) + copy(o.duplex[:], src.duplex[:]) + copy(o.autoneg[:], src.autoneg[:]) + return true +} + +func (o *NetifNicDetail) GetSpeed() uint32 { + return o.speed +} + +func (o *NetifNicDetail) GetSocketID() uint8 { + return o.socketId +} + +func (o *NetifNicDetail) GetTxQueueCount() uint8 { + return o.ntxq +} + +func (o *NetifNicDetail) GetRxQueueCount() uint8 { + return o.nrxq +} + +func (o *NetifNicDetail) GetStatus() string { + return TrimRightZeros(string(o.status[:])) +} + +func (o *NetifNicDetail) GetName() string { + return TrimRightZeros(string(o.name[:])) +} + +func (o *NetifNicDetail) GetLinkDuplex() string { + return TrimRightZeros(string(o.duplex[:])) +} + +func (o *NetifNicDetail) GetLinkAutoNeg() string { + return TrimRightZeros(string(o.autoneg[:])) +} + +func (o *NetifNicDetail) GetAddr() string { + return TrimRightZeros(string(o.addr[:])) +} + +func (o *NetifNicDetail) GetMTU() uint16 { + return o.mtu +} + +func (o *NetifNicDetail) GetID() uint16 { + return o.id +} + +func (o *NetifNicDetail) GetFlags() uint16 { + return o.flags +} + +func (o *NetifNicDetail) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicDetail) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicDetail = *(**NetifNicDetail)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicDetail) read(conn *pool.Conn, logger hclog.Logger) error { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +func (o *NetifNicDesc) GetPortBasic(cp *pool.ConnPool, logger hclog.Logger) (*NetifNicDetail, DpvsErrType) { + var GET uint32 + GET = SOCKOPT_NETIF_GET_PORT_BASIC + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return nil, EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC Write proto header failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC write specific port failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC reply msg Read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if reply.GetErrCode() != EDPVS_OK { + logger.Error(fmt.Sprintf("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC reply ErrorCode: %s", reply.GetErrStr())) + return nil, reply.GetErrCode() + } + + detail := NewNetifNicDetail() + if err := detail.read(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC spec port read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + logger.Info("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC read Done") + return detail, EDPVS_OK +} + +type NetifNicQueue struct { + queue [0x10]uint64 +} + +func (o *NetifNicQueue) Copy(src *NetifNicQueue) bool { + if src == nil { + return false + } + + for i := 0; i < len(o.queue); i++ { + o.queue[i] = src.queue[i] + } + + return true +} + +type NetifNicStats struct { + mBufAvail uint32 + mBufInuse uint32 + inPkts uint64 + outPkts uint64 + inBytes uint64 + outBytes uint64 + inMissed uint64 + inErrors uint64 + outErrors uint64 + rxNoMbuf uint64 + inPktsQ NetifNicQueue + outPktsQ NetifNicQueue + inBytesQ NetifNicQueue + outBytesQ NetifNicQueue + errorQ NetifNicQueue + padding [0x3]uint16 + id uint16 +} + +func NewNetifNicStats() *NetifNicStats { + return &NetifNicStats{} +} + +func (o *NetifNicStats) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicStats) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicStats = *(**NetifNicStats)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicStats) Copy(src *NetifNicStats) bool { + o.id = src.id + o.mBufAvail = src.mBufAvail + o.mBufInuse = src.mBufInuse + o.inPkts = src.inPkts + o.outPkts = src.outPkts + o.inBytes = src.inBytes + o.outBytes = src.outBytes + o.inMissed = src.inMissed + o.inErrors = src.inErrors + o.outErrors = src.outErrors + o.rxNoMbuf = src.rxNoMbuf + o.inPktsQ.Copy(&src.inPktsQ) + o.outPktsQ.Copy(&src.outPktsQ) + o.inBytesQ.Copy(&src.inBytesQ) + o.outBytesQ.Copy(&src.outBytesQ) + o.errorQ.Copy(&src.errorQ) + return true +} + +func (o *NetifNicStats) GetID() uint16 { + return o.id +} + +func (o *NetifNicStats) GetRxNoMbuf() uint64 { + return o.rxNoMbuf +} + +func (o *NetifNicStats) GetOutErrors() uint64 { + return o.outErrors +} + +func (o *NetifNicStats) GetInErrors() uint64 { + return o.inErrors +} + +func (o *NetifNicStats) GetInMissed() uint64 { + return o.inMissed +} + +func (o *NetifNicStats) GetOutBytes() uint64 { + return o.outBytes +} + +func (o *NetifNicStats) GetInBytes() uint64 { + return o.inBytes +} + +func (o *NetifNicStats) GetOutPkts() uint64 { + return o.outPkts +} + +func (o *NetifNicStats) GetInPkts() uint64 { + return o.inPkts +} + +func (o *NetifNicStats) GetMBufInuse() uint32 { + return o.mBufInuse +} + +func (o *NetifNicStats) GetMBufAvail() uint32 { + return o.mBufAvail +} + +func (o *NetifNicStats) read(conn *pool.Conn, logger hclog.Logger) error { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +func (o *NetifNicDesc) GetPortStats(cp *pool.ConnPool, logger hclog.Logger) (*NetifNicStats, DpvsErrType) { + var GET uint32 + GET = SOCKOPT_NETIF_GET_PORT_STATS + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_STATS Write proto header failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_STATS Write specific port failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_STATS reply msg Read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + stats := NewNetifNicStats() + if err := stats.read(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_STATS read port stats failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + logger.Info("Sockopt SOCKOPT_NETIF_GET_PORT_STATS read Done") + return stats, EDPVS_OK +} + +/* +func (o *NetifNicDesc) GetPortExtra(cp *pool.ConnPool) DpvsErrType { + var GET uint32 + GET = SOCKOPT_NETIF_GET_PORT_EXT_INFO +} +*/ diff --git a/tools/dpvs-agent/pkg/ipc/types/realserver.go b/tools/dpvs-agent/pkg/ipc/types/realserver.go new file mode 100644 index 000000000..bd56a7eb6 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/realserver.go @@ -0,0 +1,633 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type RealServerSpec struct { + af uint32 + port uint16 + proto uint16 + weight uint32 + addr [0x10]byte + connFlags uint16 + flags uint16 + fwdmode DpvsFwdMode + maxConn uint32 + minConn uint32 + actConns uint32 + inActConns uint32 + presistConns uint32 + stats dpvsStats +} + +func NewRealServerSpec() *RealServerSpec { + return &RealServerSpec{} +} + +func (rs *RealServerSpec) SetAf(af uint32) { + rs.af = af +} + +func (rs *RealServerSpec) SetProto(proto uint16) { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(proto)) + rs.proto = binary.BigEndian.Uint16(buf.Bytes()) +} + +func (rs *RealServerSpec) SetPort(port uint16) { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(port)) + rs.port = binary.BigEndian.Uint16(buf.Bytes()) +} + +func (rs *RealServerSpec) SetWeight(weight uint32) { + rs.weight = weight +} + +func (rs *RealServerSpec) GetWeight() uint32 { + return rs.weight +} + +func (rs *RealServerSpec) SetAddr(addr string) { + if strings.Contains(addr, ":") { + rs.af = unix.AF_INET6 + copy(rs.addr[:], net.ParseIP(addr)) + } else { + rs.af = unix.AF_INET + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(rs.addr[:], buf.Bytes()[12:]) + } +} + +func (rs *RealServerSpec) SetFlags(flags uint16) { + rs.flags = flags +} + +func (rs *RealServerSpec) setConnFlags(connFlags uint16) { + rs.connFlags = connFlags +} + +func (rs *RealServerSpec) SetFwdMode(fwdmode DpvsFwdMode) { + rs.setConnFlags(uint16(fwdmode) & DPVS_CONN_F_FWD_MASK) + rs.fwdmode = fwdmode +} + +func (rs *RealServerSpec) SetMaxConn(conns uint32) { + rs.maxConn = conns +} + +func (rs *RealServerSpec) SetMinConn(conns uint32) { + rs.minConn = conns +} + +func (rs *RealServerSpec) SetPresistConns(conns uint32) { + rs.presistConns = conns +} + +func (rs *RealServerSpec) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*rs)) +} + +func (rs *RealServerSpec) Copy(src *RealServerSpec) bool { + if src == nil { + return false + } + + copy(rs.addr[:], src.addr[:]) + + rs.af = src.af + rs.proto = src.proto + rs.port = src.port + rs.weight = src.weight + rs.flags = src.flags + rs.connFlags = src.connFlags + rs.fwdmode = src.fwdmode + rs.maxConn = src.maxConn + rs.minConn = src.minConn + rs.actConns = src.actConns + rs.inActConns = src.inActConns + rs.presistConns = src.presistConns + + return rs.stats.Copy(&src.stats) +} + +func (rs *RealServerSpec) Dump(buf []byte) bool { + if len(buf) != int(rs.Sizeof()) { + return false + } + + var tmp *RealServerSpec = *(**RealServerSpec)(unsafe.Pointer(&buf)) + + return rs.Copy(tmp) +} + +func (rs *RealServerSpec) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, rs) + return buf.Bytes() +} + +func (rs *RealServerSpec) write(conn *pool.Conn) error { + buf := rs.Package() + _, err := conn.WriteN(buf, int(rs.Sizeof())) + if err != nil { + // return errors.New("real server desc write failure(", written, "/", len(buf), ")") + return err + } + return nil +} + +func (rs *RealServerSpec) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*RealServerSpec, error) { + res := len % rs.Sizeof() + cnt := len / rs.Sizeof() + if res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to RealServerSpec") + } + + rss := make([]*RealServerSpec, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(rs.Sizeof())) + if err != nil { + continue + } + + rss[i] = NewRealServerSpec() + rss[i].Dump(buf) + spec := *rss[i] + logger.Info("get real server success", "spec", spec) + } + + return rss, nil +} + +func (rs *RealServerSpec) GetAddr() string { + if rs.af == unix.AF_INET { + addr := net.IPv4(rs.addr[0], rs.addr[1], rs.addr[2], rs.addr[3]) + return addr.String() + } + return "" +} + +func (rs *RealServerSpec) GetPort() uint16 { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(rs.port)) + return binary.BigEndian.Uint16(buf.Bytes()) +} + +func (rs *RealServerSpec) GetConnFlags() uint16 { + return rs.connFlags +} + +func (rs *RealServerSpec) GetOverloaded() bool { + return rs.flags&DPVS_DEST_F_OVERLOAD != 0 +} + +func (rs *RealServerSpec) SetOverloaded(overloaded *bool) { + if overloaded == nil { + return + } + if *overloaded { + rs.flags |= DPVS_DEST_F_OVERLOAD + } else { + rs.flags &= ^uint16(DPVS_DEST_F_OVERLOAD) + } +} + +func (rs *RealServerSpec) GetInhibited() bool { + return rs.flags&DPVS_DEST_F_INHIBITED != 0 +} + +func (rs *RealServerSpec) SetInhibited(inhibited *bool) { + if inhibited == nil { + return + } + if *inhibited { + rs.flags |= DPVS_DEST_F_INHIBITED + } else { + rs.flags &= ^uint16(DPVS_DEST_F_INHIBITED) + } +} + +func (rs *RealServerSpec) GetFwdModeString() string { + return rs.fwdmode.String() +} + +func (rs *RealServerSpec) ID() string { + return fmt.Sprintf("%s:%d", rs.GetAddr(), rs.port) +} + +func (rs *RealServerSpec) Format(kind string) string { + /* + -> RIP:RPORT\t\t\tFNAT\tWeight\tActive\tInactive + */ + return fmt.Sprintf(" -> %s:%d\t\t\t%s\t%d\t%d\t%d", rs.GetAddr(), rs.GetPort(), rs.GetFwdModeString(), rs.weight, rs.actConns, rs.inActConns) +} + +type RealServerFront struct { + af uint32 + proto uint16 + port uint16 + fwmark uint32 + addr [0x10]byte + numDests uint32 + match dpvsMatch + cid uint32 + index uint32 +} + +func NewRealServerFront() *RealServerFront { + return &RealServerFront{} +} + +func (rs *RealServerFront) SetNumDests(n uint32) { + rs.numDests = n +} + +func (rs *RealServerFront) ID() string { + proto := "tcp" + if rs.proto == unix.IPPROTO_UDP { + proto = "udp" + } + return fmt.Sprintf("%s-%d-%s", rs.GetAddr(), rs.GetPort(), proto) +} + +func (rs *RealServerFront) GetAddr() string { + var addr net.IP + + if rs.af == unix.AF_INET { + addr = net.IPv4(rs.addr[0], rs.addr[1], rs.addr[2], rs.addr[3]) + return addr.String() + } + + addr = net.IP{rs.addr[0x0], rs.addr[0x1], rs.addr[0x2], rs.addr[0x3], + rs.addr[0x4], rs.addr[0x5], rs.addr[0x6], rs.addr[0x7], + rs.addr[0x8], rs.addr[0x9], rs.addr[0xa], rs.addr[0xb], + rs.addr[0xc], rs.addr[0xd], rs.addr[0xe], rs.addr[0xf], + } + return addr.String() +} + +func (rs *RealServerFront) GetAf() uint32 { + return rs.af +} + +func (rs *RealServerFront) GetPort() uint16 { + return rs.port +} + +func (rs *RealServerFront) GetProto() uint16 { + return rs.proto +} + +func (rs *RealServerFront) Dump(buf []byte) bool { + if len(buf) != int(rs.Sizeof()) { + return false + } + + var tmp *RealServerFront = *(**RealServerFront)(unsafe.Pointer(&buf)) + + return rs.Copy(tmp) +} + +func (rs *RealServerFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, rs) + return buf.Bytes() +} + +func (rs *RealServerFront) write(conn *pool.Conn) error { + buf := rs.Package() + _, err := conn.WriteN(buf, int(rs.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (rs *RealServerFront) read(conn *pool.Conn, logger hclog.Logger) error { + conn.SetReadBuffer(int(rs.Sizeof())) + buf, err := conn.ReadN(int(rs.Sizeof())) + if err != nil { + return err + } + + if !rs.Dump(buf) { + return errors.New("Dump RealServerFront failed") + } + + return nil +} + +func (rs *RealServerFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*rs)) +} + +func (o *RealServerFront) ParseVipPortProto(vipport string) error { + vip := strings.Split(vipport, "-")[0] + port := strings.Split(vipport, "-")[1] + proto := strings.Split(vipport, "-")[2] + + switch strings.ToLower(proto) { + case "tcp": + o.proto = unix.IPPROTO_TCP + case "udp": + o.proto = unix.IPPROTO_UDP + default: + } + + value, err := strconv.Atoi(port) + if err != nil { + return err + } + + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(value)) + + o.port = binary.BigEndian.Uint16(buf.Bytes()) + if strings.Contains(vipport, ":") { + o.af = unix.AF_INET6 + copy(o.addr[:], net.ParseIP(vip)) + } else { + o.af = unix.AF_INET + + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(vip)) + copy(o.addr[:], buf.Bytes()[12:]) + } + + return nil +} + +func (rs *RealServerFront) Copy(src *RealServerFront) bool { + if src == nil { + return false + } + + copy(rs.addr[:], src.addr[:]) + + rs.af = src.af + rs.proto = src.proto + rs.port = src.port + rs.fwmark = src.fwmark + rs.numDests = src.numDests + rs.cid = src.cid + + return rs.match.Copy(&src.match) +} + +/***************** +******************/ + +func (front *RealServerFront) Get(cp *pool.ConnPool, parentLogger hclog.Logger) ([]*RealServerSpec, error) { + logger := hclog.Default().Named(front.ID()) + if parentLogger != nil { + logger = parentLogger.Named(front.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_GET_DESTS, SOCKOPT_GET, front.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_DESTs write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := front.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_DESTs write body failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_DESTs Read sockmsg failed", "Error", err.Error()) + return nil, err + } + + if err := front.read(conn, logger); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_DESTs read table header failed", "Error", err.Error()) + return nil, err + } + + rs := NewRealServerSpec() + + return rs.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +// put +func (front *RealServerFront) Edit(existOnly bool, rss []*RealServerSpec, cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(front.ID()) + if parentLogger != nil { + logger = parentLogger.Named(front.ID()) + } + + if len(rss) == 0 { + return EDPVS_OK + } + + sEdit := "DPVSAGENT_VS_EDIT_DESTS" + var EDIT uint32 = DPVSAGENT_VS_EDIT_DESTS + + if !existOnly { + EDIT = DPVSAGENT_VS_ADD_DESTS + sEdit = "DPVSAGENT_VS_ADD_DESTS" + } + + front.numDests = uint32(len(rss)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, EDIT, SOCKOPT_SET, front.Sizeof()+rss[0].Sizeof()*uint64(len(rss))) + + if err := msg.Write(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write proto header failed Error=%s", sEdit, err.Error())) + return EDPVS_IO + } + + if err := front.write(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write rss table header failed Error=%s", sEdit, err.Error())) + return EDPVS_IO + } + + for _, rs := range rss { + if err := rs.write(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write rs %v header failed Error=%s", sEdit, *rs, err.Error())) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + + if err := reply.Read(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Read sockmsg failed Error=%s", sEdit, err.Error())) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + logger.Info(fmt.Sprintf("%s %v Done result=%s", sEdit, rss, errCode.String())) + return errCode +} + +func (front *RealServerFront) add(rss []*RealServerSpec, cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + if len(rss) == 0 { + return EDPVS_OK + } + + front.numDests = uint32(len(rss)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_ADD_DESTS, SOCKOPT_SET, front.Sizeof()+rss[0].Sizeof()*uint64(len(rss))) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_DESTs write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := front.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_DESTs write rss table header failed", "Error", err.Error()) + return EDPVS_IO + } + + for _, rs := range rss { + if err := rs.write(conn); err != nil { + // backend error + logger.Error("Sockopt DPVSAGENT_VS_ADD_DESTs write spec rs failed", "Error", err.Error()) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_DESTs Read sockmsg failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVSAGENT_VS_ADD_DESTs Done", "result", result) + return errCode +} + +func (front *RealServerFront) Del(rss []*RealServerSpec, cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + if len(rss) == 0 { + logger.Info("No Real server need delete, return immediately") + return EDPVS_OK + } + + front.numDests = uint32(len(rss)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_DEL_DESTS, SOCKOPT_SET, front.Sizeof()+rss[0].Sizeof()*uint64(len(rss))) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_DESTs write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := front.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_DESTs write rss table header failed", "Error", err.Error()) + return EDPVS_IO + } + + for _, rs := range rss { + if err := rs.write(conn); err != nil { + // backend error + logger.Error("Sockopt DPVSAGENT_VS_DEL_DESTs write spec rs failed", "Error", err.Error()) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_DESTs Read sockmsg failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVSAGENT_VS_ADD_DESTs Done", "result", result) + return errCode +} + +// post +func (front *RealServerFront) Update(rss []*RealServerSpec, cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(front.ID()) + if parentLogger != nil { + logger = parentLogger.Named(front.ID()) + } + + if len(rss) == 0 { + logger.Warn("Remove all RS ! ! !") + } + + running, err := front.Get(cp, logger) + if err != nil { + logger.Error("Get realserver failed", "Error", err.Error()) + return EDPVS_IO + } + + reserved := make(map[string]*RealServerSpec) + for _, rs := range rss { + reserved[rs.ID()] = rs + } + + unreserved := make([]*RealServerSpec, 0) + for _, expire := range running { + if _, ok := reserved[expire.ID()]; !ok { + unreserved = append(unreserved, expire) + } + } + logger.Info("reserved", reserved, "unreserved", unreserved) + + status := front.add(rss, cp, logger) + if status != EDPVS_OK { + return status + } + + errCode := front.Del(unreserved, cp, logger) + result := errCode.String() + logger.Info("Set", "rss", rss, "Done", "result", result) + return errCode +} diff --git a/tools/dpvs-agent/pkg/ipc/types/route.go b/tools/dpvs-agent/pkg/ipc/types/route.go new file mode 100644 index 000000000..e428ff621 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/route.go @@ -0,0 +1,470 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type RouteAddr struct { + addr [0x10]byte + plen uint32 // prefix len +} + +func (o *RouteAddr) Copy(src *RouteAddr) bool { + o.plen = src.plen + copy(o.addr[:], src.addr[:]) + return true +} + +type RouteDetail struct { + af uint32 + mtu uint32 + flags uint32 + metric uint32 + dst RouteAddr + src RouteAddr + gateway RouteAddr + prefSrc RouteAddr + ifName [0x10]byte +} + +func NewRouteDetail() *RouteDetail { + return &RouteDetail{} +} + +func (o *RouteDetail) GetIfName() string { + return TrimRightZeros(string(o.ifName[:])) +} + +func (o *RouteDetail) GetSrc() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.src.addr[0], o.src.addr[1], o.src.addr[2], o.src.addr[3]) + return addr.String() + } + + addr = net.IP{o.src.addr[0x0], o.src.addr[0x1], o.src.addr[0x2], o.src.addr[0x3], + o.src.addr[0x4], o.src.addr[0x5], o.src.addr[0x6], o.src.addr[0x7], + o.src.addr[0x8], o.src.addr[0x9], o.src.addr[0xa], o.src.addr[0xb], + o.src.addr[0xc], o.src.addr[0xd], o.src.addr[0xe], o.src.addr[0xf], + } + return addr.String() +} + +func (o *RouteDetail) GetDst() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.dst.addr[0], o.dst.addr[1], o.dst.addr[2], o.dst.addr[3]) + return addr.String() + } + + addr = net.IP{o.dst.addr[0x0], o.dst.addr[0x1], o.dst.addr[0x2], o.dst.addr[0x3], + o.dst.addr[0x4], o.dst.addr[0x5], o.dst.addr[0x6], o.dst.addr[0x7], + o.dst.addr[0x8], o.dst.addr[0x9], o.dst.addr[0xa], o.dst.addr[0xb], + o.dst.addr[0xc], o.dst.addr[0xd], o.dst.addr[0xe], o.dst.addr[0xf], + } + return addr.String() +} + +func (o *RouteDetail) Copy(src *RouteDetail) bool { + o.af = src.af + o.mtu = src.mtu + o.flags = src.flags + o.metric = src.metric + o.dst.Copy(&src.dst) + o.src.Copy(&src.src) + o.gateway.Copy(&src.gateway) + o.prefSrc.Copy(&src.prefSrc) + copy(o.ifName[:], src.ifName[:]) + return true +} + +func (o *RouteDetail) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *RouteDetail) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *RouteDetail = *(**RouteDetail)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *RouteDetail) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *RouteDetail) SetAf(af uint32) { + o.af = af +} + +func (o *RouteDetail) SetMtu(mtu uint32) { + o.mtu = mtu +} + +func (o *RouteDetail) SetFlags(flags uint32) { + // FIXME o.flags ^= o.flags first ??? + o.flags |= flags +} + +func (o *RouteDetail) SetMetric(metric uint32) { + o.metric = metric +} + +func (o *RouteDetail) SetScope(scope string) { + switch strings.ToLower(scope) { + case "host": + o.SetFlags(RTF_LOCALIN) + case "kni_host": + o.SetFlags(RTF_KNI) + default: + /*case "global":*/ + /*case "link":*/ + o.SetFlags(RTF_FORWARD) + } +} + +func (o *RouteDetail) SetDst(dst string) { + addr := dst + plen := "32" + if strings.Index(dst, "/") != -1 { + addr = dst[:strings.Index(dst, "/")] + plen = dst[strings.Index(dst, "/")+1:] + } + + if strings.Contains(addr, ":") { + o.SetAf(unix.AF_INET6) + copy(o.dst.addr[:], net.ParseIP(addr)) + } else { + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.dst.addr[:], buf.Bytes()[12:]) + } + + mask, err := strconv.Atoi(plen) + if err != nil { + o.dst.plen = 32 + } + o.dst.plen = uint32(mask) +} + +func (o *RouteDetail) SetSrc(src string) bool { + if len(src) == 0 { + return false + } + + if strings.Contains(src, ":") { + o.SetAf(unix.AF_INET6) + copy(o.src.addr[:], net.ParseIP(src)) + } else { + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(src)) + copy(o.src.addr[:], buf.Bytes()[12:]) + } + + return true +} + +func (o *RouteDetail) SetGateway(gw string) bool { + if len(gw) == 0 { + return false + } + + if strings.Contains(gw, ":") { + o.SetAf(unix.AF_INET6) + copy(o.gateway.addr[:], net.ParseIP(gw)) + } else { + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(gw)) + copy(o.gateway.addr[:], buf.Bytes()[12:]) + } + return true +} + +func (o *RouteDetail) SetPrefSrc(pref string) { + if len(pref) == 0 { + return + } + + if strings.Contains(pref, ":") { + o.SetAf(unix.AF_INET6) + copy(o.prefSrc.addr[:], net.ParseIP(pref)) + } else { + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(pref)) + copy(o.prefSrc.addr[:], buf.Bytes()[12:]) + } +} + +func (o *RouteDetail) SetDevice(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *RouteDetail) Read(conn *pool.Conn, len uint64) ([]*RouteDetail, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to RouteDetail") + } + + details := make([]*RouteDetail, cnt) + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + details[i] = NewRouteDetail() + details[i].Dump(buf) + } + + return details, nil +} + +func (o *RouteDetail) Write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type RouteFront struct { + count uint32 +} + +func NewRouteFront() *RouteFront { + return &RouteFront{} +} + +func (o *RouteFront) Copy(src *RouteFront) bool { + o.count = src.count + return true +} + +func (o *RouteFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *RouteFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *RouteFront = *(**RouteFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *RouteFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *RouteFront) SetCount(c uint32) { + o.count = c +} + +func (o *RouteFront) GetCount() uint32 { + return o.count +} + +func (o *RouteFront) Read(conn *pool.Conn, len uint64) ([]*RouteFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to RouteFront") + } + + fronts := make([]*RouteFront, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i] = NewRouteFront() + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *RouteFront) Write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +/**************** +****************/ +func (o *RouteDetail) Get(cp *pool.ConnPool, parentLogger hclog.Logger) ([]*RouteDetail, error) { + traceName := o.GetIfName() + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + var GET uint32 + GET = DPVSAGENT_ROUTE_GET + if o.af == unix.AF_INET6 { + GET = DPVSAGENT_ROUTE6_GET + } + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt ", GET, "Write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := o.Write(conn); err != nil { + logger.Error("Sockopt ", GET, "Write proto body failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt ", GET, "Read proto header failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt ", GET, " failed", "result", result) + err := fmt.Errorf("Sockopt %s reply ErrorCode: %s", GET, result) + return nil, err + } + + front := NewRouteFront() + _, err = front.Read(conn, front.Sizeof()) + if err != nil { + logger.Error("Sockopt ", GET, "read list header failed", "Error", err.Error()) + return nil, err + } + + return o.Read(conn, uint64(reply.GetLen())-front.Sizeof()) +} + +func (o *RouteDetail) Add(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + traceName := fmt.Sprintf("add %s via %s dev %s", o.GetSrc(), o.GetDst(), o.GetIfName()) + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var ADD uint32 + ADD = DPVSAGENT_ROUTE_ADD + if o.af == unix.AF_INET6 { + ADD = DPVSAGENT_ROUTE6_ADD + } + + msg := NewSockMsg(SOCKOPT_VERSION, ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt ", ADD, "Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + err = o.Write(conn) + if err != nil { + logger.Error("Sockopt ", ADD, "Write proto body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt ", ADD, "reply failed", "Error", err.Error()) + return EDPVS_IO + } + + return reply.GetErrCode() +} + +func (o *RouteDetail) Del(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + traceName := fmt.Sprintf("del %s via %s dev %s", o.GetSrc(), o.GetDst(), o.GetIfName()) + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var DEL uint32 + DEL = DPVSAGENT_ROUTE_DEL + if o.af == unix.AF_INET6 { + DEL = DPVSAGENT_ROUTE6_DEL + } + + msg := NewSockMsg(SOCKOPT_VERSION, DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt ", DEL, "Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = o.Write(conn) + if err != nil { + logger.Error("Sockopt ", DEL, "Write proto body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt ", DEL, "reply failed", "Error", err.Error()) + return EDPVS_IO + } + + return reply.GetErrCode() +} diff --git a/tools/dpvs-agent/pkg/ipc/types/sockmsg.go b/tools/dpvs-agent/pkg/ipc/types/sockmsg.go new file mode 100644 index 000000000..3db2543e5 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/sockmsg.go @@ -0,0 +1,132 @@ +package types + +import ( + "bytes" + "encoding/binary" + "errors" + "unsafe" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type SockMsg struct { + version uint32 + id uint32 + sockopt SockoptType + nop uint32 + len uint64 +} + +type ReplySockMsg struct { + version uint32 + id uint32 + sockopt SockoptType + errCode DpvsErrType + errStr [0x40]byte + len uint32 + nop uint32 +} + +func NewSockMsg(version, id uint32, sockopt SockoptType, len uint64) *SockMsg { + return &SockMsg{version: version, id: id, sockopt: sockopt, len: len} +} + +func (msg *SockMsg) GetLen() uint64 { + return msg.len +} + +func NewReplySockMsg() *ReplySockMsg { + return &ReplySockMsg{} +} + +func (msg *ReplySockMsg) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*msg)) +} + +func (msg *ReplySockMsg) Dump(buf []byte) bool { + if len(buf) != int(msg.Sizeof()) { + return false + } + + var tmp *ReplySockMsg = *(**ReplySockMsg)(unsafe.Pointer(&buf)) + msg.version = tmp.version + msg.id = tmp.id + msg.sockopt = tmp.sockopt + msg.errCode = tmp.errCode + msg.len = tmp.len + copy(msg.errStr[:], tmp.errStr[:]) + msg.ZeroPadding() + + return true +} + +func (msg *ReplySockMsg) SetVersion(version uint32) { + msg.version = version +} + +func (msg *ReplySockMsg) SetID(id uint32) { + msg.id = id +} + +func (msg *ReplySockMsg) SetSockopt(opt SockoptType) { + msg.sockopt = opt +} + +func (msg *ReplySockMsg) SetErrCode(code DpvsErrType) { + msg.errCode = code +} + +func (msg *ReplySockMsg) SetErrStr(err []byte) { + copy(msg.errStr[:], err) +} + +func (msg *ReplySockMsg) SetLen(len uint32) { + msg.len = len +} + +func (msg *ReplySockMsg) ZeroPadding() { + msg.nop = 0 +} + +func (msg *ReplySockMsg) GetErrCode() DpvsErrType { + return msg.errCode +} + +func (msg *ReplySockMsg) GetErrStr() string { + return TrimRightZeros(string(msg.errStr[:])) +} + +func (msg *ReplySockMsg) GetLen() uint32 { + return msg.len +} + +func (msg *SockMsg) Package() []byte { + hdr := new(bytes.Buffer) + binary.Write(hdr, binary.LittleEndian, msg) + return hdr.Bytes() +} + +func (msg *SockMsg) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*msg)) +} + +func (msg *SockMsg) Write(conn *pool.Conn) error { + buf := msg.Package() + _, err := conn.WriteN(buf, len(buf)) + if err != nil { + return err + } + return nil +} + +func (msg *ReplySockMsg) Read(conn *pool.Conn) error { + buf, err := conn.ReadN(int(msg.Sizeof())) + if err != nil { + return err + } + + if !msg.Dump(buf) { + return errors.New("dump reply msg failed") + } + return nil +} diff --git a/tools/dpvs-agent/pkg/ipc/types/utility.go b/tools/dpvs-agent/pkg/ipc/types/utility.go new file mode 100644 index 000000000..d887d9a19 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/utility.go @@ -0,0 +1,11 @@ +package types + +import "strings" + +func TrimRightZeros(s string) string { + idx := strings.IndexByte(s, 0) + if idx >= 0 { + return s[:idx] + } + return s +} diff --git a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go new file mode 100644 index 000000000..bb7cc409d --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go @@ -0,0 +1,693 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type VirtualServerFront struct { + cid uint8 + index uint8 + count uint16 + padding uint32 +} + +func NewVirtualServerFront() *VirtualServerFront { + return &VirtualServerFront{} +} + +func (o *VirtualServerFront) Copy(src *VirtualServerFront) bool { + if src == nil { + return false + } + + o.cid = src.cid + o.index = src.index + o.count = src.count + + return true +} + +func (o *VirtualServerFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *VirtualServerFront = *(**VirtualServerFront)(unsafe.Pointer(&buf)) + return o.Copy(tmp) +} + +func (o *VirtualServerFront) SetCid(cid uint8) { + o.cid = cid +} + +func (o *VirtualServerFront) SetIndex(index uint8) { + o.index = index +} + +func (o *VirtualServerFront) SetCount(count uint16) { + o.count = count +} + +func (o *VirtualServerFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *VirtualServerFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *VirtualServerFront) read(conn *pool.Conn, logger hclog.Logger) error { + conn.SetReadBuffer(int(o.Sizeof())) + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + if !o.Dump(buf) { + return errors.New("dump reply virtual server front failed") + } + logger.Info("Get Virtual Server Count success", "count", o.count) + + return nil +} +func (o *VirtualServerFront) Write(conn *pool.Conn) error { + buf := o.Package() + + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + + return nil +} + +type dpvsDestCheck struct { + types uint8 + padding [7]byte +} + +type VirtualServerSpec struct { + af uint32 + proto uint16 + port uint16 + fwmark uint32 + flags uint32 + timeout uint32 + connTimeout uint32 + netmask uint32 + bps uint32 + limitProportion uint32 + addr [0x10]byte + schedName [0x10]byte + match dpvsMatch + numDests uint32 + numLaddrs uint32 + cid uint64 + stats dpvsStats + hc dpvsDestCheck +} + +func NewVirtualServerSpec() *VirtualServerSpec { + return &VirtualServerSpec{} +} + +func (vs *VirtualServerSpec) Convert2NewRsFront() *RealServerFront { + front := NewRealServerFront() + + front.af = vs.af + front.port = vs.port + front.proto = vs.proto + front.fwmark = vs.fwmark + front.numDests = vs.numDests + front.cid = uint32(vs.cid) + + front.match.Copy(&vs.match) + copy(front.addr[:], vs.addr[:]) + + return front +} + +func (vs *VirtualServerSpec) Copy(src *VirtualServerSpec) bool { + if src == nil { + return false + } + + vs.af = src.af + vs.proto = src.proto + vs.port = src.port + vs.fwmark = src.fwmark + vs.flags = src.flags + vs.timeout = src.timeout + vs.connTimeout = src.connTimeout + vs.netmask = src.netmask + vs.bps = src.bps + vs.limitProportion = src.limitProportion + vs.numDests = src.numDests + vs.numLaddrs = src.numLaddrs + vs.cid = src.cid + vs.hc = src.hc + + copy(vs.addr[:], src.addr[:]) + copy(vs.schedName[:], src.schedName[:]) + + if !vs.match.Copy(&src.match) { + return false + } + if !vs.stats.Copy(&src.stats) { + return false + } + return true +} + +func (vs *VirtualServerSpec) ID() string { + proto := "tcp" + if vs.proto == unix.IPPROTO_UDP { + proto = "udp" + } + return fmt.Sprintf("%s-%d-%s", vs.GetAddr(), vs.GetPort(), proto) +} + +func (vs *VirtualServerSpec) Format(kind string) string { + /* + TCP VIP:PORT sched + -> RIP:RPORT Fnat weight actConn inActConn + -> RIP:RPORT Fnat weight actConn inActConn + ... + */ + + var vipport string + vip := vs.GetAddr() + if vip == "" { + return "" + } + port := vs.GetPort() + + vipport = fmt.Sprintf("%s:%d", vip, port) + if vs.proto == unix.IPPROTO_TCP { + vsHeader := fmt.Sprintf("TCP %s %s\r\n", vipport, string(vs.schedName[:])) + return vsHeader + } + + return "" +} + +func (vs *VirtualServerSpec) Dump(buf []byte) bool { + if len(buf) != int(vs.Sizeof()) { + return false + } + + var tmp *VirtualServerSpec = *(**VirtualServerSpec)(unsafe.Pointer(&buf)) + + return vs.Copy(tmp) +} + +func (vs *VirtualServerSpec) SetAf(af uint32) { + vs.af = af +} +func (vs *VirtualServerSpec) GetAf() uint32 { + return vs.af +} + +func (vs *VirtualServerSpec) SetProto(proto uint16) { + vs.proto = proto +} + +func (vs *VirtualServerSpec) SetPort(port uint16) { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(port)) + vs.port = binary.BigEndian.Uint16(buf.Bytes()) +} + +func (vs *VirtualServerSpec) GetPort() uint16 { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(vs.port)) + return binary.BigEndian.Uint16(buf.Bytes()) +} + +func (vs *VirtualServerSpec) GetProto() uint16 { + return vs.proto +} + +func (vs *VirtualServerSpec) SetFwmark(fwmark uint32) { + vs.fwmark = fwmark +} +func (vs *VirtualServerSpec) GetFwmark() uint32 { + return vs.fwmark +} + +func (vs *VirtualServerSpec) SetFlagsSyncProxy() { + vs.setFlags(DPVS_CONN_F_SYNPROXY) +} + +func (vs *VirtualServerSpec) SetFlagsExpireQuiescent() { + vs.setFlags(DPVS_CONN_F_EXPIRE_QUIESCENT) +} + +func (vs *VirtualServerSpec) SetFlagsPersistent() { + vs.setFlags(DPVS_SVC_F_PERSISTENT) +} + +func (vs *VirtualServerSpec) SetFlagsHashSrcIP() { + vs.flags &= (uint32)(^DPVS_SVC_F_QID_HASH) + vs.flags &= (uint32)(^DPVS_SVC_F_SIP_HASH) + + vs.setFlags(DPVS_SVC_F_SIP_HASH) +} + +func (vs *VirtualServerSpec) SetFlagsHashQuicID() { + vs.flags &= (uint32)(^DPVS_SVC_F_QID_HASH) + vs.flags &= (uint32)(^DPVS_SVC_F_SIP_HASH) + + vs.setFlags(DPVS_SVC_F_QID_HASH) +} + +func (vs *VirtualServerSpec) setFlags(flags uint32) { + vs.flags |= flags +} + +func (vs *VirtualServerSpec) GetFlags() uint32 { + return vs.flags +} + +func (vs *VirtualServerSpec) SetTimeout(t uint32) { + vs.timeout = t +} +func (vs *VirtualServerSpec) GetTimeout() uint32 { + return vs.timeout +} + +func (vs *VirtualServerSpec) SetConnTimeout(ct uint32) { + vs.connTimeout = ct +} + +func (vs *VirtualServerSpec) GetConnTimeout() uint32 { + return vs.connTimeout +} + +func (vs *VirtualServerSpec) SetNetMask(mask uint32) { + vs.netmask = mask +} + +func (vs *VirtualServerSpec) GetNetMask() uint32 { + return vs.netmask +} + +func (vs *VirtualServerSpec) SetBps(bps uint32) { + vs.bps = bps +} + +func (vs *VirtualServerSpec) GetBps() uint32 { + return vs.bps +} + +func (vs *VirtualServerSpec) SetLimitProportion(limit uint32) { + vs.limitProportion = limit +} + +func (vs *VirtualServerSpec) GetLimitProportion() uint32 { + return vs.limitProportion +} + +func (vs *VirtualServerSpec) SetNumDests(num uint32) { + vs.numDests = num +} + +func (vs *VirtualServerSpec) GetNumDests() uint32 { + return vs.numDests +} + +func (vs *VirtualServerSpec) SetNumLaddrs(num uint32) { + vs.numLaddrs = num +} + +func (vs *VirtualServerSpec) SetCid(cid uint64) { + vs.cid = cid +} + +func (vs *VirtualServerSpec) setNetmask(mask uint32) { + vs.netmask = mask +} + +func (vs *VirtualServerSpec) SetAddr(addr string) { + if strings.Contains(addr, ":") { + copy(vs.addr[:], net.ParseIP(addr)) + vs.af = unix.AF_INET6 + vs.setNetmask(128) + return + } + + vs.af = unix.AF_INET + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(vs.addr[:], buf.Bytes()[12:]) + vs.setNetmask(0xFFFFFFFF) +} + +func (vs *VirtualServerSpec) GetAddr() string { + var addr net.IP + + if vs.af == unix.AF_INET { + addr = net.IPv4(vs.addr[0], vs.addr[1], vs.addr[2], vs.addr[3]) + return addr.String() + } + + addr = net.IP{vs.addr[0x0], vs.addr[0x1], vs.addr[0x2], vs.addr[0x3], + vs.addr[0x4], vs.addr[0x5], vs.addr[0x6], vs.addr[0x7], + vs.addr[0x8], vs.addr[0x9], vs.addr[0xa], vs.addr[0xb], + vs.addr[0xc], vs.addr[0xd], vs.addr[0xe], vs.addr[0xf], + } + return addr.String() +} + +func (vs *VirtualServerSpec) GetSchedName() string { + return TrimRightZeros(string(vs.schedName[:])) +} + +func (vs *VirtualServerSpec) GetDestCheck() []models.DestCheckSpec { + var res []models.DestCheckSpec + if vs.hc.types&DPVS_DEST_HC_PASSIVE != 0 { + res = append(res, models.DestCheckSpecPassive) + } + if vs.hc.types&DPVS_DEST_HC_TCP != 0 { + res = append(res, models.DestCheckSpecTCP) + } + if vs.hc.types&DPVS_DEST_HC_UDP != 0 { + res = append(res, models.DestCheckSpecUDP) + } + if vs.hc.types&DPVS_DEST_HC_PING != 0 { + res = append(res, models.DestCheckSpecPing) + } + return res +} + +func (vs *VirtualServerSpec) SetSchedName(name string) { + sched := strings.ToLower(name) + + switch strings.ToLower(name) { + case "rr": + case "wlc": + case "conhash": + case "fo": + case "mh": + default: + sched = "wrr" + } + copy(vs.schedName[:], []byte(sched)) +} + +func (vs *VirtualServerSpec) SetMatch(m *dpvsMatch) { + vs.match.Copy(m) +} + +func (vs *VirtualServerSpec) SetStats(s *dpvsStats) { + vs.stats.Copy(s) +} + +func (vs *VirtualServerSpec) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*vs)) +} + +func (vs *VirtualServerSpec) ParseVipPortProto(vipport string) error { + items := strings.Split(vipport, "-") + if len(items) != 3 { + return errors.New("invalid vip-port-proto string") + } + + proto := items[2] + + switch strings.ToLower(proto) { + case "udp": + vs.proto = unix.IPPROTO_UDP + case "tcp": + fallthrough + default: + vs.proto = unix.IPPROTO_TCP + } + + // port := items[1] + port, err := strconv.Atoi(items[1]) + if err != nil { + return err + } + vs.SetPort(uint16(port)) + + vip := items[0] + if net.ParseIP(vip) == nil { + return errors.New(fmt.Sprintf("invalid ip addr: %s\n", vip)) + } + vs.SetAddr(vip) + + return nil +} + +func (vs *VirtualServerSpec) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*VirtualServerSpec, error) { + res := len % vs.Sizeof() + cnt := len / vs.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + err := errors.New("the buffer may not convert to VirtualServerSpec") + logger.Error("Read failed", "Error", err.Error()) + return nil, err + } + + vss := make([]*VirtualServerSpec, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(vs.Sizeof())) + if err != nil { + logger.Error("Read VirtualServerSpec() failed", "Error", err.Error()) + return nil, err + } + + vss[i] = NewVirtualServerSpec() + if !vss[i].Dump(buf) { + logger.Error("Dump byte as VirtualServerSpec failed") + return nil, errors.New("dump reply virtual server failed") + } + spec := *vss[i] + logger.Info("get virtual server success", "spec", spec) + } + + return vss, nil +} + +func (vs *VirtualServerSpec) Write(conn *pool.Conn) error { + buf := vs.Package() + + _, err := conn.WriteN(buf, int(vs.Sizeof())) + if err != nil { + return err + } + + return nil +} + +func (vs *VirtualServerSpec) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, vs) + return buf.Bytes() +} + +/***************** +******************/ + +func (front *VirtualServerFront) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*VirtualServerSpec, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_SO_GET_SERVICES, SOCKOPT_GET, front.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_SO_GET_SERVICEs Write proto header failed", "Error", err.Error()) + return nil, err + } + + err = front.Write(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_SO_GET_SERVICEs Write proto bodyfailed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_SO_GET_SERVICEs Read proto header failed", "Error", err.Error()) + return nil, err + } + + if err := front.read(conn, logger); err != nil { + logger.Error("Sockopt DPVSAGENT_SO_GET_SERVICEs Read vss table header failed", "Error", err.Error()) + return nil, err + } + + vs := NewVirtualServerSpec() + return vs.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +func (vs *VirtualServerSpec) Get(cp *pool.ConnPool, parentLogger hclog.Logger) ([]*VirtualServerSpec, error) { + logger := hclog.Default().Named(vs.ID()) + if parentLogger != nil { + logger = parentLogger.Named(vs.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + msg := NewSockMsg(SOCKOPT_VERSION, DPVS_SO_GET_SERVICE, SOCKOPT_GET, vs.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_GET_SERVICE Write proto header failed", "Error", err.Error()) + return nil, err + } + + err = vs.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_GET_SERVICE Write proto body failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVS_SO_GET_SERVICE Read failed", "Error", err.Error()) + return nil, err + } + + return vs.read(conn, uint64(reply.GetLen()), logger) +} + +func (vs *VirtualServerSpec) Update(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(vs.ID()) + if parentLogger != nil { + logger = parentLogger.Named(vs.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVS_SO_SET_EDIT, SOCKOPT_SET, vs.Sizeof()) + + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_EDIT Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = vs.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_EDIT Write proto body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_EDIT Read failed", "Error", err.Error()) + return EDPVS_IO + } + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVS_SO_SET_EDIT Done", "result", result) + return errCode +} + +func (vs *VirtualServerSpec) Add(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(vs.ID()) + if parentLogger != nil { + logger = parentLogger.Named(vs.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVS_SO_SET_ADD, SOCKOPT_SET, vs.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_ADD Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = vs.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_ADD Write proto body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_ADD Read failed", "Error", err.Error()) + return EDPVS_IO + } + errCode := reply.GetErrCode() + result := errCode.String() + + logger.Info("DPVS_SO_SET_ADD Done", "result", result) + return errCode +} + +func (vs *VirtualServerSpec) Del(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVS_SO_SET_DEL, SOCKOPT_SET, vs.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVS_SO_SET_DEL write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := vs.Write(conn); err != nil { + logger.Error("Sockopt DPVS_SO_SET_DEL Write body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVS_SO_SET_DEL Read reply failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + + logger.Info("DPVS_SO_SET_DEL Done", "result", result) + return errCode +} diff --git a/tools/dpvs-agent/pkg/ipc/types/vlan.go b/tools/dpvs-agent/pkg/ipc/types/vlan.go new file mode 100644 index 000000000..ece83c0ef --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/vlan.go @@ -0,0 +1,312 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type VlanFront struct { + count uint32 +} + +func NewVlanFront() *VlanFront { + return &VlanFront{} +} + +func (o *VlanFront) GetCount() uint32 { + return o.count +} + +func (o *VlanFront) SetCount(c uint32) { + o.count = c +} + +func (o *VlanFront) Copy(src *VlanFront) bool { + o.count = src.count + return true +} + +func (o *VlanFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *VlanFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *VlanFront = *(**VlanFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *VlanFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *VlanFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*VlanFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to VlanFront") + } + + fronts := make([]*VlanFront, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i] = NewVlanFront() + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *VlanFront) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type VlanDevice struct { + realDev [0x10]byte + ifName [0x10]byte + proto uint16 + id uint16 +} + +func NewVlanDevice() *VlanDevice { + return &VlanDevice{proto: unix.ETH_P_8021Q} +} + +func (o *VlanDevice) Copy(src *VlanDevice) bool { + copy(o.realDev[:], src.realDev[:]) + copy(o.ifName[:], src.ifName[:]) + o.proto = src.proto + o.id = src.id + return true +} + +func (o *VlanDevice) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *VlanDevice) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *VlanDevice = *(**VlanDevice)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *VlanDevice) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *VlanDevice) SetRealDev(name string) { + copy(o.realDev[:], name[:]) +} + +func (o *VlanDevice) SetId(id uint16) { + o.id = id +} + +func (o *VlanDevice) SetIfName(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *VlanDevice) SetProto(proto string) { + p := strings.ToLower(proto) + switch p { + case "vlan": + fallthrough + case "802.1q": + o.proto = unix.ETH_P_8021Q + case "qinq": + fallthrough + case "802.1ad": + o.proto = unix.ETH_P_8021AD + default: + } +} + +func (o *VlanDevice) ValidProto(proto string) bool { + // p := strings.ToLower(proto) + switch strings.ToLower(proto) { + case "vlan": + return true + case "802.1q": + return true + case "qinq": + return true + case "802.1ad": + return true + default: + return false + } + return false +} + +func (o *VlanDevice) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*VlanDevice, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to VlanDevice") + } + + devices := make([]*VlanDevice, cnt) + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + devices[i] = NewVlanDevice() + devices[i].Dump(buf) + } + + return devices, nil +} + +func (o *VlanDevice) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +/**************** +****************/ +func (o *VlanDevice) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*VlanDevice, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, SOCKOPT_GET_VLAN_SHOW, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_VLAN_SHOW Write proto header Error:", err.Error()) + return nil, err + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_GET_VLAN_SHOW write specific vlan Error:", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_VLAN_SHOW reply msg Read failed:", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + err = fmt.Errorf("Sockopt SOCKOPT_GET_VLAN_SHOW reply ErrorCode: %s", reply.GetErrStr()) + logger.Error(err.Error()) + return nil, err + } + + front := VlanFront{} + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_GET_VLAN_SHOW read table header failed:", err.Error()) + return nil, err + } + + return o.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +func (o *VlanDevice) Add(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, SOCKOPT_SET_VLAN_ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_ADD Write proto header Error failed", "Error", err.Error()) + return EDPVS_IO + } + + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_ADD write specific vlan Error failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_ADD reply msg Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("Sockopt SOCKOPT_SET_VLAN_ADD Done", "result", result) + return errCode +} + +func (o *VlanDevice) Del(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, SOCKOPT_SET_VLAN_DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_DEL Write proto header Error:", err.Error()) + return EDPVS_IO + } + + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_DEL write specific vlan Error:", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_DEL reply msg Read failed:", err.Error()) + return EDPVS_IO + } + + return reply.GetErrCode() +} diff --git a/tools/dpvs-agent/restapi/configure_dpvs_agent.go b/tools/dpvs-agent/restapi/configure_dpvs_agent.go new file mode 100644 index 000000000..f37abf18a --- /dev/null +++ b/tools/dpvs-agent/restapi/configure_dpvs_agent.go @@ -0,0 +1,172 @@ +// This file is safe to edit. Once it exists it will not be overwritten + +package restapi + +import ( + "crypto/tls" + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + + "github.com/dpvs-agent/restapi/operations" + "github.com/dpvs-agent/restapi/operations/device" + "github.com/dpvs-agent/restapi/operations/virtualserver" +) + +//go:generate swagger generate server --target ../../dpvs-agent --name DpvsAgent --spec ../dpvs-agent-api.yaml --principal interface{} + +func configureFlags(api *operations.DpvsAgentAPI) { + // api.CommandLineOptionsGroups = []swag.CommandLineOptionsGroup{ ... } +} + +func configureAPI(api *operations.DpvsAgentAPI) http.Handler { + // configure the api here + api.ServeError = errors.ServeError + + // Set your custom logger if needed. Default one is log.Printf + // Expected interface func(string, ...interface{}) + // + // Example: + // api.Logger = log.Printf + + api.UseSwaggerUI() + // To continue using redoc as your UI, uncomment the following line + // api.UseRedoc() + + api.JSONConsumer = runtime.JSONConsumer() + + api.JSONProducer = runtime.JSONProducer() + + if api.DeviceDeleteDeviceNameAddrHandler == nil { + api.DeviceDeleteDeviceNameAddrHandler = device.DeleteDeviceNameAddrHandlerFunc(func(params device.DeleteDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameAddr has not yet been implemented") + }) + } + if api.DeviceDeleteDeviceNameRouteHandler == nil { + api.DeviceDeleteDeviceNameRouteHandler = device.DeleteDeviceNameRouteHandlerFunc(func(params device.DeleteDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameRoute has not yet been implemented") + }) + } + if api.DeviceDeleteDeviceNameVlanHandler == nil { + api.DeviceDeleteDeviceNameVlanHandler = device.DeleteDeviceNameVlanHandlerFunc(func(params device.DeleteDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameVlan has not yet been implemented") + }) + } + if api.VirtualserverDeleteVsVipPortHandler == nil { + api.VirtualserverDeleteVsVipPortHandler = virtualserver.DeleteVsVipPortHandlerFunc(func(params virtualserver.DeleteVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPort has not yet been implemented") + }) + } + if api.VirtualserverDeleteVsVipPortLaddrHandler == nil { + api.VirtualserverDeleteVsVipPortLaddrHandler = virtualserver.DeleteVsVipPortLaddrHandlerFunc(func(params virtualserver.DeleteVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortLaddr has not yet been implemented") + }) + } + if api.VirtualserverDeleteVsVipPortRsHandler == nil { + api.VirtualserverDeleteVsVipPortRsHandler = virtualserver.DeleteVsVipPortRsHandlerFunc(func(params virtualserver.DeleteVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortRs has not yet been implemented") + }) + } + if api.DeviceGetDeviceHandler == nil { + api.DeviceGetDeviceHandler = device.GetDeviceHandlerFunc(func(params device.GetDeviceParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDevice has not yet been implemented") + }) + } + if api.DeviceGetDeviceNameAddrHandler == nil { + api.DeviceGetDeviceNameAddrHandler = device.GetDeviceNameAddrHandlerFunc(func(params device.GetDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameAddr has not yet been implemented") + }) + } + if api.DeviceGetDeviceNameRouteHandler == nil { + api.DeviceGetDeviceNameRouteHandler = device.GetDeviceNameRouteHandlerFunc(func(params device.GetDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameRoute has not yet been implemented") + }) + } + if api.DeviceGetDeviceNameVlanHandler == nil { + api.DeviceGetDeviceNameVlanHandler = device.GetDeviceNameVlanHandlerFunc(func(params device.GetDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameVlan has not yet been implemented") + }) + } + if api.VirtualserverGetVsHandler == nil { + api.VirtualserverGetVsHandler = virtualserver.GetVsHandlerFunc(func(params virtualserver.GetVsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVs has not yet been implemented") + }) + } + if api.VirtualserverGetVsVipPortHandler == nil { + api.VirtualserverGetVsVipPortHandler = virtualserver.GetVsVipPortHandlerFunc(func(params virtualserver.GetVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPort has not yet been implemented") + }) + } + if api.VirtualserverGetVsVipPortLaddrHandler == nil { + api.VirtualserverGetVsVipPortLaddrHandler = virtualserver.GetVsVipPortLaddrHandlerFunc(func(params virtualserver.GetVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortLaddr has not yet been implemented") + }) + } + if api.VirtualserverGetVsVipPortRsHandler == nil { + api.VirtualserverGetVsVipPortRsHandler = virtualserver.GetVsVipPortRsHandlerFunc(func(params virtualserver.GetVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortRs has not yet been implemented") + }) + } + if api.DevicePutDeviceNameAddrHandler == nil { + api.DevicePutDeviceNameAddrHandler = device.PutDeviceNameAddrHandlerFunc(func(params device.PutDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameAddr has not yet been implemented") + }) + } + if api.DevicePutDeviceNameRouteHandler == nil { + api.DevicePutDeviceNameRouteHandler = device.PutDeviceNameRouteHandlerFunc(func(params device.PutDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameRoute has not yet been implemented") + }) + } + if api.DevicePutDeviceNameVlanHandler == nil { + api.DevicePutDeviceNameVlanHandler = device.PutDeviceNameVlanHandlerFunc(func(params device.PutDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameVlan has not yet been implemented") + }) + } + if api.VirtualserverPutVsVipPortHandler == nil { + api.VirtualserverPutVsVipPortHandler = virtualserver.PutVsVipPortHandlerFunc(func(params virtualserver.PutVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPort has not yet been implemented") + }) + } + if api.VirtualserverPutVsVipPortLaddrHandler == nil { + api.VirtualserverPutVsVipPortLaddrHandler = virtualserver.PutVsVipPortLaddrHandlerFunc(func(params virtualserver.PutVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortLaddr has not yet been implemented") + }) + } + if api.VirtualserverPutVsVipPortRsHandler == nil { + api.VirtualserverPutVsVipPortRsHandler = virtualserver.PutVsVipPortRsHandlerFunc(func(params virtualserver.PutVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortRs has not yet been implemented") + }) + } + + api.PreServerShutdown = func() {} + + api.ServerShutdown = func() {} + + return setupGlobalMiddleware(api.Serve(setupMiddlewares)) +} + +// The TLS configuration before HTTPS server starts. +func configureTLS(tlsConfig *tls.Config) { + // Make all necessary changes to the TLS configuration here. +} + +// As soon as server is initialized but not run yet, this function will be called. +// If you need to modify a config, store server instance to stop it individually later, this is the place. +// This function can be called multiple times, depending on the number of serving schemes. +// scheme value will be set accordingly: "http", "https" or "unix". +func configureServer(s *http.Server, scheme, addr string) { +} + +// The middleware configuration is for the handler executors. These do not apply to the swagger.json document. +// The middleware executes after routing but before authentication, binding and validation. +func setupMiddlewares(handler http.Handler) http.Handler { + return handler +} + +// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document. +// So this is a good place to plug in a panic handling middleware, logging and metrics. +func setupGlobalMiddleware(handler http.Handler) http.Handler { + return handler +} diff --git a/tools/dpvs-agent/restapi/doc.go b/tools/dpvs-agent/restapi/doc.go new file mode 100644 index 000000000..d70edbc94 --- /dev/null +++ b/tools/dpvs-agent/restapi/doc.go @@ -0,0 +1,19 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// Package restapi dpvs agent +// +// dpvs agent api +// Schemes: +// http +// Host: petstore.swagger.io +// BasePath: /v2 +// Version: 1.0.0 +// +// Consumes: +// - application/json +// +// Produces: +// - application/json +// +// swagger:meta +package restapi diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go new file mode 100644 index 000000000..488b7f0fe --- /dev/null +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -0,0 +1,4449 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package restapi + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "encoding/json" +) + +var ( + // SwaggerJSON embedded version of the swagger document used at generation time + SwaggerJSON json.RawMessage + // FlatSwaggerJSON embedded flattened version of the swagger document used at generation time + FlatSwaggerJSON json.RawMessage +) + +func init() { + SwaggerJSON = json.RawMessage([]byte(`{ + "schemes": [ + "http" + ], + "swagger": "2.0", + "info": { + "description": "dpvs agent api", + "title": "dpvs agent", + "version": "1.0.0" + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "paths": { + "/device": { + "get": { + "tags": [ + "device" + ], + "summary": "display all net device list", + "parameters": [ + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/addr": { + "get": { + "tags": [ + "device" + ], + "summary": "display special net device ip addr", + "parameters": [ + { + "$ref": "#/parameters/stats" + }, + { + "$ref": "#/parameters/verbose" + }, + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device ip addr", + "parameters": [ + { + "$ref": "#/parameters/sapool" + }, + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/device-addr" + } + ], + "responses": { + "200": { + "description": "Update exist ip addr Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Add new ip addr Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device ip addr", + "parameters": [ + { + "$ref": "#/parameters/sapool" + }, + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/device-addr" + } + ], + "responses": { + "200": { + "description": "delete ip addr from device Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/netlink": { + "get": { + "tags": [ + "device" + ], + "summary": "ip link show dev ${name}", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "ip link set ${name} up", + "parameters": [ + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "ip link set ${name} down", + "parameters": [ + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/netlink/addr": { + "get": { + "tags": [ + "device" + ], + "summary": "display special linux net device addr detail", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "set ip cird to linux net device", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/device-addr" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete ip cird fron linux net device", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/device-addr" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/nic": { + "get": { + "tags": [ + "device" + ], + "summary": "dpip link show ${nic-name} -s -v", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/verbose" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/NicDeviceSpecList" + } + }, + "500": { + "description": "Failure", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "dpip link set ${nic-name} [forward2kni,link,promisc,tc-ingress,tc-egress] [on/up,off/down]", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/forward2kni" + }, + { + "$ref": "#/parameters/link" + }, + { + "$ref": "#/parameters/promisc" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failure", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/route": { + "get": { + "tags": [ + "device" + ], + "summary": "display special net device route", + "parameters": [ + { + "$ref": "#/parameters/stats" + }, + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device route", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/route-config" + } + ], + "responses": { + "200": { + "description": "Update exist route Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Add new route Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device route", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/route-config" + } + ], + "responses": { + "200": { + "description": "delete route Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/vlan": { + "get": { + "tags": [ + "device" + ], + "summary": "display all net device list", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device ", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/vlan-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device", + "parameters": [ + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/vs": { + "get": { + "tags": [ + "virtualserver" + ], + "summary": "display all vip:port:proto and rsip:port list", + "parameters": [ + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/VirtualServerList" + } + } + } + } + }, + "/vs/{VipPort}": { + "get": { + "tags": [ + "virtualserver" + ], + "summary": "get a specific virtual server", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/VirtualServerList" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "create or update virtual server", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/vs-config" + } + ], + "responses": { + "200": { + "description": "Updated", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/allow": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of ip from white list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update a fully white ip list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of ip form white list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/deny": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of ip from black list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update a fully black ip list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of ip form black list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/laddr": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/LocalAddressExpandList" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/laddr-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/laddr-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/rs": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of real server to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/rss-config" + }, + { + "$ref": "#/parameters/healthcheck" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update fully real server list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/rss-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of real server from vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/rss-config" + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + } + }, + "definitions": { + "AclAddrList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/CertAuthSpec" + } + } + } + }, + "AddrRange": { + "type": "object", + "properties": { + "End": { + "type": "string" + }, + "Start": { + "type": "string" + } + } + }, + "CertAuthSpec": { + "properties": { + "addr": { + "type": "string" + } + } + }, + "DestCheckSpec": { + "type": "string", + "enum": [ + "passive", + "tcp", + "udp", + "ping" + ] + }, + "Error": { + "type": "string" + }, + "InetAddrSpec": { + "properties": { + "addr": { + "type": "string" + }, + "broadcast": { + "type": "string" + }, + "scope": { + "type": "string" + } + } + }, + "LocalAddressExpandList": { + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/LocalAddressSpecExpand" + } + } + } + }, + "LocalAddressSpecExpand": { + "type": "object", + "properties": { + "addr": { + "type": "string" + }, + "af": { + "type": "integer", + "format": "uint32" + }, + "conns": { + "type": "integer", + "format": "uint32" + }, + "device": { + "type": "string" + }, + "portConflict": { + "type": "integer", + "format": "uint64" + } + } + }, + "LocalAddressSpecTiny": { + "properties": { + "addr": { + "type": "string" + }, + "device": { + "type": "string" + } + } + }, + "LocalAddressTinyList": { + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + } + } + }, + "MatchSpec": { + "type": "object", + "properties": { + "Dest": { + "$ref": "#/definitions/AddrRange" + }, + "InIfName": { + "type": "string" + }, + "OutIfName": { + "type": "string" + }, + "Src": { + "$ref": "#/definitions/AddrRange" + } + } + }, + "NicDeviceDetail": { + "type": "object", + "properties": { + "Flags": { + "type": "integer", + "format": "uint16" + }, + "ID": { + "type": "integer", + "format": "uint16" + }, + "MTU": { + "type": "integer", + "format": "uint16" + }, + "addr": { + "type": "string" + }, + "autoneg": { + "type": "string", + "enum": [ + "fixed-nego", + "auto-nego" + ] + }, + "duplex": { + "type": "string", + "enum": [ + "half-duplex", + "full-duplex" + ] + }, + "nRxQ": { + "type": "integer", + "format": "uint8" + }, + "nTxQ": { + "type": "integer", + "format": "uint8" + }, + "name": { + "type": "string" + }, + "socketID": { + "type": "integer", + "format": "uint8" + }, + "speed": { + "type": "integer", + "format": "uint32" + }, + "status": { + "type": "string", + "enum": [ + "UP", + "DOWN" + ] + } + } + }, + "NicDeviceQueueData": { + "type": "integer", + "format": "uint64" + }, + "NicDeviceSpec": { + "type": "object", + "properties": { + "detail": { + "$ref": "#/definitions/NicDeviceDetail" + }, + "stats": { + "$ref": "#/definitions/NicDeviceStats" + } + } + }, + "NicDeviceSpecList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceSpec" + } + } + } + }, + "NicDeviceStats": { + "type": "object", + "properties": { + "bufAvail": { + "type": "integer", + "format": "uint32" + }, + "bufInuse": { + "type": "integer", + "format": "uint32" + }, + "errorBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "id": { + "type": "integer", + "format": "uint16" + }, + "inBytes": { + "type": "integer", + "format": "uint64" + }, + "inBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "inErrors": { + "type": "integer", + "format": "uint64" + }, + "inMissed": { + "type": "integer", + "format": "uint64" + }, + "inPkts": { + "type": "integer", + "format": "uint64" + }, + "inPktsQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "outBytes": { + "type": "integer", + "format": "uint64" + }, + "outBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "outErrors": { + "type": "integer", + "format": "uint64" + }, + "outPkts": { + "type": "integer", + "format": "uint64" + }, + "outPktsQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "rxNoMbuf": { + "type": "integer", + "format": "uint64" + } + } + }, + "RealServerExpandList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/RealServerSpecExpand" + } + } + } + }, + "RealServerSpecExpand": { + "type": "object", + "properties": { + "Spec": { + "$ref": "#/definitions/RealServerSpecTiny" + }, + "Stats": { + "$ref": "#/definitions/ServerStats" + } + } + }, + "RealServerSpecTiny": { + "type": "object", + "properties": { + "inhibited": { + "type": "boolean", + "default": false + }, + "ip": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": [ + "FNAT", + "SNAT", + "DR", + "TUNNEL", + "NAT" + ] + }, + "overloaded": { + "type": "boolean", + "default": false + }, + "port": { + "type": "integer", + "format": "uint16", + "x-omitempty": false + }, + "weight": { + "type": "integer", + "format": "uint16", + "x-omitempty": false + } + } + }, + "RealServerTinyList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/RealServerSpecTiny" + } + } + } + }, + "RouteSpec": { + "properties": { + "device": { + "type": "string" + }, + "dst": { + "type": "string" + }, + "gateway": { + "type": "string" + }, + "metric": { + "type": "integer", + "format": "uint32" + }, + "mtu": { + "type": "integer", + "format": "uint32" + }, + "prefixSrc": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "src": { + "type": "string" + } + } + }, + "ServerStats": { + "type": "object", + "properties": { + "Conns": { + "type": "integer", + "format": "uint64" + }, + "Cps": { + "type": "integer", + "format": "uint32" + }, + "InBps": { + "type": "integer", + "format": "uint32" + }, + "InBytes": { + "type": "integer", + "format": "uint64" + }, + "InPkts": { + "type": "integer", + "format": "uint64" + }, + "InPps": { + "type": "integer", + "format": "uint32" + }, + "OutBps": { + "type": "integer", + "format": "uint32" + }, + "OutBytes": { + "type": "integer", + "format": "uint64" + }, + "OutPkts": { + "type": "integer", + "format": "uint64" + }, + "OutPps": { + "type": "integer", + "format": "uint32" + } + } + }, + "Status": { + "description": "Status of an individual component", + "type": "object", + "properties": { + "msg": { + "description": "Human readable status/error/warning message", + "type": "string" + }, + "state": { + "description": "State the component is in", + "type": "string", + "enum": [ + "Ok", + "Warning", + "Failure", + "Disabled" + ] + } + } + }, + "VirtualServerList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/VirtualServerSpecExpand" + } + } + } + }, + "VirtualServerSpecExpand": { + "type": "object", + "properties": { + "Addr": { + "type": "string" + }, + "Af": { + "type": "integer", + "format": "uint32" + }, + "Bps": { + "type": "integer", + "format": "uint32" + }, + "ConnTimeout": { + "type": "integer", + "format": "uint32" + }, + "DestCheck": { + "type": "array", + "items": { + "$ref": "#/definitions/DestCheckSpec" + } + }, + "ExpireQuiescent": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "Flags": { + "type": "string" + }, + "Fwmark": { + "type": "integer", + "format": "uint32" + }, + "LimitProportion": { + "type": "integer", + "format": "uint32" + }, + "Match": { + "$ref": "#/definitions/MatchSpec" + }, + "Netmask": { + "type": "integer", + "format": "uint32" + }, + "Port": { + "type": "integer", + "format": "uint16" + }, + "Proto": { + "type": "integer", + "format": "uint16" + }, + "RSs": { + "$ref": "#/definitions/RealServerExpandList" + }, + "SchedName": { + "type": "string", + "enum": [ + "rr", + "wrr", + "wlc", + "connhash" + ] + }, + "Stats": { + "$ref": "#/definitions/ServerStats" + }, + "SyncProxy": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "Timeout": { + "type": "integer", + "format": "uint32" + } + } + }, + "VirtualServerSpecTiny": { + "type": "object", + "properties": { + "Bps": { + "type": "integer", + "format": "uint32" + }, + "ConnTimeout": { + "type": "integer", + "format": "uint32" + }, + "ExpireQuiescent": { + "type": "boolean", + "default": false + }, + "Fwmark": { + "type": "integer", + "format": "uint32" + }, + "LimitProportion": { + "type": "integer", + "format": "uint32" + }, + "Match": { + "$ref": "#/definitions/MatchSpec" + }, + "SchedName": { + "type": "string", + "enum": [ + "rr", + "wrr", + "wlc", + "connhash" + ] + }, + "SyncProxy": { + "type": "boolean", + "default": false + }, + "Timeout": { + "type": "integer", + "format": "uint32" + } + } + }, + "VlanSpec": { + "properties": { + "device": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + }, + "parameters": { + "acl-config": { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + }, + "device-addr": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + }, + "device-name": { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + "forward2kni": { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "forward2Kni", + "in": "query" + }, + "healthcheck": { + "type": "boolean", + "default": false, + "name": "healthcheck", + "in": "query" + }, + "laddr-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + }, + "link": { + "enum": [ + "unset", + "up", + "down" + ], + "type": "string", + "default": "unset", + "name": "link", + "in": "query" + }, + "promisc": { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "promisc", + "in": "query" + }, + "realserver-id": { + "type": "string", + "name": "RipPort", + "in": "path", + "required": true + }, + "route-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RouteSpec" + } + }, + "rs-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerSpecTiny" + } + }, + "rss-config": { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + }, + "sapool": { + "type": "boolean", + "default": false, + "name": "sapool", + "in": "query" + }, + "service-id": { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + "stats": { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + }, + "verbose": { + "type": "boolean", + "default": false, + "name": "verbose", + "in": "query" + }, + "vlan-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VlanSpec" + } + }, + "vs-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VirtualServerSpecTiny" + } + } + }, + "tags": [ + { + "description": "virtualserver", + "name": "virtualserver" + }, + { + "description": "route", + "name": "route" + }, + { + "description": "laddr", + "name": "laddr" + }, + { + "description": "tunnel", + "name": "tunnel" + }, + { + "description": "inet addr", + "name": "inetaddr" + }, + { + "description": "white list", + "name": "white_list" + }, + { + "description": "black list", + "name": "black_list" + }, + { + "description": "arp", + "name": "arp" + } + ] +}`)) + FlatSwaggerJSON = json.RawMessage([]byte(`{ + "schemes": [ + "http" + ], + "swagger": "2.0", + "info": { + "description": "dpvs agent api", + "title": "dpvs agent", + "version": "1.0.0" + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "paths": { + "/device": { + "get": { + "tags": [ + "device" + ], + "summary": "display all net device list", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/addr": { + "get": { + "tags": [ + "device" + ], + "summary": "display special net device ip addr", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + }, + { + "type": "boolean", + "default": false, + "name": "verbose", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device ip addr", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "sapool", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + } + ], + "responses": { + "200": { + "description": "Update exist ip addr Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Add new ip addr Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device ip addr", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "sapool", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + } + ], + "responses": { + "200": { + "description": "delete ip addr from device Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/netlink": { + "get": { + "tags": [ + "device" + ], + "summary": "ip link show dev ${name}", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "ip link set ${name} up", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "ip link set ${name} down", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/netlink/addr": { + "get": { + "tags": [ + "device" + ], + "summary": "display special linux net device addr detail", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "set ip cird to linux net device", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete ip cird fron linux net device", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/nic": { + "get": { + "tags": [ + "device" + ], + "summary": "dpip link show ${nic-name} -s -v", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "verbose", + "in": "query" + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/NicDeviceSpecList" + } + }, + "500": { + "description": "Failure", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "dpip link set ${nic-name} [forward2kni,link,promisc,tc-ingress,tc-egress] [on/up,off/down]", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "forward2Kni", + "in": "query" + }, + { + "enum": [ + "unset", + "up", + "down" + ], + "type": "string", + "default": "unset", + "name": "link", + "in": "query" + }, + { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "promisc", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failure", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/route": { + "get": { + "tags": [ + "device" + ], + "summary": "display special net device route", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device route", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RouteSpec" + } + } + ], + "responses": { + "200": { + "description": "Update exist route Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Add new route Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device route", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RouteSpec" + } + } + ], + "responses": { + "200": { + "description": "delete route Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/vlan": { + "get": { + "tags": [ + "device" + ], + "summary": "display all net device list", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device ", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VlanSpec" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/vs": { + "get": { + "tags": [ + "virtualserver" + ], + "summary": "display all vip:port:proto and rsip:port list", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/VirtualServerList" + } + } + } + } + }, + "/vs/{VipPort}": { + "get": { + "tags": [ + "virtualserver" + ], + "summary": "get a specific virtual server", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/VirtualServerList" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "create or update virtual server", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VirtualServerSpecTiny" + } + } + ], + "responses": { + "200": { + "description": "Updated", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/allow": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of ip from white list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update a fully white ip list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of ip form white list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/deny": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of ip from black list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update a fully black ip list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of ip form black list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/laddr": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/LocalAddressExpandList" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/rs": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of real server to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + }, + { + "type": "boolean", + "default": false, + "name": "healthcheck", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update fully real server list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of real server from vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + } + }, + "definitions": { + "AclAddrList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/CertAuthSpec" + } + } + } + }, + "AddrRange": { + "type": "object", + "properties": { + "End": { + "type": "string" + }, + "Start": { + "type": "string" + } + } + }, + "CertAuthSpec": { + "properties": { + "addr": { + "type": "string" + } + } + }, + "DestCheckSpec": { + "type": "string", + "enum": [ + "passive", + "tcp", + "udp", + "ping" + ] + }, + "Error": { + "type": "string" + }, + "InetAddrSpec": { + "properties": { + "addr": { + "type": "string" + }, + "broadcast": { + "type": "string" + }, + "scope": { + "type": "string" + } + } + }, + "LocalAddressExpandList": { + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/LocalAddressSpecExpand" + } + } + } + }, + "LocalAddressSpecExpand": { + "type": "object", + "properties": { + "addr": { + "type": "string" + }, + "af": { + "type": "integer", + "format": "uint32" + }, + "conns": { + "type": "integer", + "format": "uint32" + }, + "device": { + "type": "string" + }, + "portConflict": { + "type": "integer", + "format": "uint64" + } + } + }, + "LocalAddressSpecTiny": { + "properties": { + "addr": { + "type": "string" + }, + "device": { + "type": "string" + } + } + }, + "LocalAddressTinyList": { + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + } + } + }, + "MatchSpec": { + "type": "object", + "properties": { + "Dest": { + "$ref": "#/definitions/AddrRange" + }, + "InIfName": { + "type": "string" + }, + "OutIfName": { + "type": "string" + }, + "Src": { + "$ref": "#/definitions/AddrRange" + } + } + }, + "NicDeviceDetail": { + "type": "object", + "properties": { + "Flags": { + "type": "integer", + "format": "uint16" + }, + "ID": { + "type": "integer", + "format": "uint16" + }, + "MTU": { + "type": "integer", + "format": "uint16" + }, + "addr": { + "type": "string" + }, + "autoneg": { + "type": "string", + "enum": [ + "fixed-nego", + "auto-nego" + ] + }, + "duplex": { + "type": "string", + "enum": [ + "half-duplex", + "full-duplex" + ] + }, + "nRxQ": { + "type": "integer", + "format": "uint8" + }, + "nTxQ": { + "type": "integer", + "format": "uint8" + }, + "name": { + "type": "string" + }, + "socketID": { + "type": "integer", + "format": "uint8" + }, + "speed": { + "type": "integer", + "format": "uint32" + }, + "status": { + "type": "string", + "enum": [ + "UP", + "DOWN" + ] + } + } + }, + "NicDeviceQueueData": { + "type": "integer", + "format": "uint64" + }, + "NicDeviceSpec": { + "type": "object", + "properties": { + "detail": { + "$ref": "#/definitions/NicDeviceDetail" + }, + "stats": { + "$ref": "#/definitions/NicDeviceStats" + } + } + }, + "NicDeviceSpecList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceSpec" + } + } + } + }, + "NicDeviceStats": { + "type": "object", + "properties": { + "bufAvail": { + "type": "integer", + "format": "uint32" + }, + "bufInuse": { + "type": "integer", + "format": "uint32" + }, + "errorBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "id": { + "type": "integer", + "format": "uint16" + }, + "inBytes": { + "type": "integer", + "format": "uint64" + }, + "inBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "inErrors": { + "type": "integer", + "format": "uint64" + }, + "inMissed": { + "type": "integer", + "format": "uint64" + }, + "inPkts": { + "type": "integer", + "format": "uint64" + }, + "inPktsQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "outBytes": { + "type": "integer", + "format": "uint64" + }, + "outBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "outErrors": { + "type": "integer", + "format": "uint64" + }, + "outPkts": { + "type": "integer", + "format": "uint64" + }, + "outPktsQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "rxNoMbuf": { + "type": "integer", + "format": "uint64" + } + } + }, + "RealServerExpandList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/RealServerSpecExpand" + } + } + } + }, + "RealServerSpecExpand": { + "type": "object", + "properties": { + "Spec": { + "$ref": "#/definitions/RealServerSpecTiny" + }, + "Stats": { + "$ref": "#/definitions/ServerStats" + } + } + }, + "RealServerSpecTiny": { + "type": "object", + "properties": { + "inhibited": { + "type": "boolean", + "default": false + }, + "ip": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": [ + "FNAT", + "SNAT", + "DR", + "TUNNEL", + "NAT" + ] + }, + "overloaded": { + "type": "boolean", + "default": false + }, + "port": { + "type": "integer", + "format": "uint16", + "x-omitempty": false + }, + "weight": { + "type": "integer", + "format": "uint16", + "x-omitempty": false + } + } + }, + "RealServerTinyList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/RealServerSpecTiny" + } + } + } + }, + "RouteSpec": { + "properties": { + "device": { + "type": "string" + }, + "dst": { + "type": "string" + }, + "gateway": { + "type": "string" + }, + "metric": { + "type": "integer", + "format": "uint32" + }, + "mtu": { + "type": "integer", + "format": "uint32" + }, + "prefixSrc": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "src": { + "type": "string" + } + } + }, + "ServerStats": { + "type": "object", + "properties": { + "Conns": { + "type": "integer", + "format": "uint64" + }, + "Cps": { + "type": "integer", + "format": "uint32" + }, + "InBps": { + "type": "integer", + "format": "uint32" + }, + "InBytes": { + "type": "integer", + "format": "uint64" + }, + "InPkts": { + "type": "integer", + "format": "uint64" + }, + "InPps": { + "type": "integer", + "format": "uint32" + }, + "OutBps": { + "type": "integer", + "format": "uint32" + }, + "OutBytes": { + "type": "integer", + "format": "uint64" + }, + "OutPkts": { + "type": "integer", + "format": "uint64" + }, + "OutPps": { + "type": "integer", + "format": "uint32" + } + } + }, + "Status": { + "description": "Status of an individual component", + "type": "object", + "properties": { + "msg": { + "description": "Human readable status/error/warning message", + "type": "string" + }, + "state": { + "description": "State the component is in", + "type": "string", + "enum": [ + "Ok", + "Warning", + "Failure", + "Disabled" + ] + } + } + }, + "VirtualServerList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/VirtualServerSpecExpand" + } + } + } + }, + "VirtualServerSpecExpand": { + "type": "object", + "properties": { + "Addr": { + "type": "string" + }, + "Af": { + "type": "integer", + "format": "uint32" + }, + "Bps": { + "type": "integer", + "format": "uint32" + }, + "ConnTimeout": { + "type": "integer", + "format": "uint32" + }, + "DestCheck": { + "type": "array", + "items": { + "$ref": "#/definitions/DestCheckSpec" + } + }, + "ExpireQuiescent": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "Flags": { + "type": "string" + }, + "Fwmark": { + "type": "integer", + "format": "uint32" + }, + "LimitProportion": { + "type": "integer", + "format": "uint32" + }, + "Match": { + "$ref": "#/definitions/MatchSpec" + }, + "Netmask": { + "type": "integer", + "format": "uint32" + }, + "Port": { + "type": "integer", + "format": "uint16" + }, + "Proto": { + "type": "integer", + "format": "uint16" + }, + "RSs": { + "$ref": "#/definitions/RealServerExpandList" + }, + "SchedName": { + "type": "string", + "enum": [ + "rr", + "wrr", + "wlc", + "connhash" + ] + }, + "Stats": { + "$ref": "#/definitions/ServerStats" + }, + "SyncProxy": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "Timeout": { + "type": "integer", + "format": "uint32" + } + } + }, + "VirtualServerSpecTiny": { + "type": "object", + "properties": { + "Bps": { + "type": "integer", + "format": "uint32" + }, + "ConnTimeout": { + "type": "integer", + "format": "uint32" + }, + "ExpireQuiescent": { + "type": "boolean", + "default": false + }, + "Fwmark": { + "type": "integer", + "format": "uint32" + }, + "LimitProportion": { + "type": "integer", + "format": "uint32" + }, + "Match": { + "$ref": "#/definitions/MatchSpec" + }, + "SchedName": { + "type": "string", + "enum": [ + "rr", + "wrr", + "wlc", + "connhash" + ] + }, + "SyncProxy": { + "type": "boolean", + "default": false + }, + "Timeout": { + "type": "integer", + "format": "uint32" + } + } + }, + "VlanSpec": { + "properties": { + "device": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + }, + "parameters": { + "acl-config": { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + }, + "device-addr": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + }, + "device-name": { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + "forward2kni": { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "forward2Kni", + "in": "query" + }, + "healthcheck": { + "type": "boolean", + "default": false, + "name": "healthcheck", + "in": "query" + }, + "laddr-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + }, + "link": { + "enum": [ + "unset", + "up", + "down" + ], + "type": "string", + "default": "unset", + "name": "link", + "in": "query" + }, + "promisc": { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "promisc", + "in": "query" + }, + "realserver-id": { + "type": "string", + "name": "RipPort", + "in": "path", + "required": true + }, + "route-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RouteSpec" + } + }, + "rs-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerSpecTiny" + } + }, + "rss-config": { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + }, + "sapool": { + "type": "boolean", + "default": false, + "name": "sapool", + "in": "query" + }, + "service-id": { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + "stats": { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + }, + "verbose": { + "type": "boolean", + "default": false, + "name": "verbose", + "in": "query" + }, + "vlan-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VlanSpec" + } + }, + "vs-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VirtualServerSpecTiny" + } + } + }, + "tags": [ + { + "description": "virtualserver", + "name": "virtualserver" + }, + { + "description": "route", + "name": "route" + }, + { + "description": "laddr", + "name": "laddr" + }, + { + "description": "tunnel", + "name": "tunnel" + }, + { + "description": "inet addr", + "name": "inetaddr" + }, + { + "description": "white list", + "name": "white_list" + }, + { + "description": "black list", + "name": "black_list" + }, + { + "description": "arp", + "name": "arp" + } + ] +}`)) +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr.go new file mode 100644 index 000000000..ecb1bab59 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameAddrHandlerFunc turns a function with the right signature into a delete device name addr handler +type DeleteDeviceNameAddrHandlerFunc func(DeleteDeviceNameAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameAddrHandlerFunc) Handle(params DeleteDeviceNameAddrParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameAddrHandler interface for that can handle valid delete device name addr params +type DeleteDeviceNameAddrHandler interface { + Handle(DeleteDeviceNameAddrParams) middleware.Responder +} + +// NewDeleteDeviceNameAddr creates a new http.Handler for the delete device name addr operation +func NewDeleteDeviceNameAddr(ctx *middleware.Context, handler DeleteDeviceNameAddrHandler) *DeleteDeviceNameAddr { + return &DeleteDeviceNameAddr{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameAddr swagger:route DELETE /device/{name}/addr device deleteDeviceNameAddr + +delete special net device ip addr +*/ +type DeleteDeviceNameAddr struct { + Context *middleware.Context + Handler DeleteDeviceNameAddrHandler +} + +func (o *DeleteDeviceNameAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_parameters.go new file mode 100644 index 000000000..c4134b592 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_parameters.go @@ -0,0 +1,145 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteDeviceNameAddrParams creates a new DeleteDeviceNameAddrParams object +// with the default values initialized. +func NewDeleteDeviceNameAddrParams() DeleteDeviceNameAddrParams { + + var ( + // initialize parameters with default values + + sapoolDefault = bool(false) + ) + + return DeleteDeviceNameAddrParams{ + Sapool: &sapoolDefault, + } +} + +// DeleteDeviceNameAddrParams contains all the bound params for the delete device name addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameAddr +type DeleteDeviceNameAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Sapool *bool + /* + In: body + */ + Spec *models.InetAddrSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameAddrParams() beforehand. +func (o *DeleteDeviceNameAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qSapool, qhkSapool, _ := qs.GetOK("sapool") + if err := o.bindSapool(qSapool, qhkSapool, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.InetAddrSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindSapool binds and validates parameter Sapool from query. +func (o *DeleteDeviceNameAddrParams) bindSapool(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewDeleteDeviceNameAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("sapool", "query", "bool", raw) + } + o.Sapool = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_responses.go new file mode 100644 index 000000000..82afd7bb0 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameAddrOKCode is the HTTP code returned for type DeleteDeviceNameAddrOK +const DeleteDeviceNameAddrOKCode int = 200 + +/* +DeleteDeviceNameAddrOK delete ip addr from device Success + +swagger:response deleteDeviceNameAddrOK +*/ +type DeleteDeviceNameAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameAddrOK creates DeleteDeviceNameAddrOK with default headers values +func NewDeleteDeviceNameAddrOK() *DeleteDeviceNameAddrOK { + + return &DeleteDeviceNameAddrOK{} +} + +// WithPayload adds the payload to the delete device name addr o k response +func (o *DeleteDeviceNameAddrOK) WithPayload(payload string) *DeleteDeviceNameAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name addr o k response +func (o *DeleteDeviceNameAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameAddrInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameAddrInternalServerError +const DeleteDeviceNameAddrInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameAddrInternalServerError Failed + +swagger:response deleteDeviceNameAddrInternalServerError +*/ +type DeleteDeviceNameAddrInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameAddrInternalServerError creates DeleteDeviceNameAddrInternalServerError with default headers values +func NewDeleteDeviceNameAddrInternalServerError() *DeleteDeviceNameAddrInternalServerError { + + return &DeleteDeviceNameAddrInternalServerError{} +} + +// WithPayload adds the payload to the delete device name addr internal server error response +func (o *DeleteDeviceNameAddrInternalServerError) WithPayload(payload string) *DeleteDeviceNameAddrInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name addr internal server error response +func (o *DeleteDeviceNameAddrInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameAddrInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_urlbuilder.go new file mode 100644 index 000000000..e58276264 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// DeleteDeviceNameAddrURL generates an URL for the delete device name addr operation +type DeleteDeviceNameAddrURL struct { + Name string + + Sapool *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameAddrURL) WithBasePath(bp string) *DeleteDeviceNameAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var sapoolQ string + if o.Sapool != nil { + sapoolQ = swag.FormatBool(*o.Sapool) + } + if sapoolQ != "" { + qs.Set("sapool", sapoolQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink.go new file mode 100644 index 000000000..5429f3a10 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameNetlinkHandlerFunc turns a function with the right signature into a delete device name netlink handler +type DeleteDeviceNameNetlinkHandlerFunc func(DeleteDeviceNameNetlinkParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameNetlinkHandlerFunc) Handle(params DeleteDeviceNameNetlinkParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameNetlinkHandler interface for that can handle valid delete device name netlink params +type DeleteDeviceNameNetlinkHandler interface { + Handle(DeleteDeviceNameNetlinkParams) middleware.Responder +} + +// NewDeleteDeviceNameNetlink creates a new http.Handler for the delete device name netlink operation +func NewDeleteDeviceNameNetlink(ctx *middleware.Context, handler DeleteDeviceNameNetlinkHandler) *DeleteDeviceNameNetlink { + return &DeleteDeviceNameNetlink{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameNetlink swagger:route DELETE /device/{name}/netlink device deleteDeviceNameNetlink + +ip link set ${name} down +*/ +type DeleteDeviceNameNetlink struct { + Context *middleware.Context + Handler DeleteDeviceNameNetlinkHandler +} + +func (o *DeleteDeviceNameNetlink) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameNetlinkParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go new file mode 100644 index 000000000..63cb56c24 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameNetlinkAddrHandlerFunc turns a function with the right signature into a delete device name netlink addr handler +type DeleteDeviceNameNetlinkAddrHandlerFunc func(DeleteDeviceNameNetlinkAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameNetlinkAddrHandlerFunc) Handle(params DeleteDeviceNameNetlinkAddrParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameNetlinkAddrHandler interface for that can handle valid delete device name netlink addr params +type DeleteDeviceNameNetlinkAddrHandler interface { + Handle(DeleteDeviceNameNetlinkAddrParams) middleware.Responder +} + +// NewDeleteDeviceNameNetlinkAddr creates a new http.Handler for the delete device name netlink addr operation +func NewDeleteDeviceNameNetlinkAddr(ctx *middleware.Context, handler DeleteDeviceNameNetlinkAddrHandler) *DeleteDeviceNameNetlinkAddr { + return &DeleteDeviceNameNetlinkAddr{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameNetlinkAddr swagger:route DELETE /device/{name}/netlink/addr device deleteDeviceNameNetlinkAddr + +delete ip cird fron linux net device +*/ +type DeleteDeviceNameNetlinkAddr struct { + Context *middleware.Context + Handler DeleteDeviceNameNetlinkAddrHandler +} + +func (o *DeleteDeviceNameNetlinkAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameNetlinkAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_parameters.go new file mode 100644 index 000000000..9727f0252 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteDeviceNameNetlinkAddrParams creates a new DeleteDeviceNameNetlinkAddrParams object +// +// There are no default values defined in the spec. +func NewDeleteDeviceNameNetlinkAddrParams() DeleteDeviceNameNetlinkAddrParams { + + return DeleteDeviceNameNetlinkAddrParams{} +} + +// DeleteDeviceNameNetlinkAddrParams contains all the bound params for the delete device name netlink addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameNetlinkAddr +type DeleteDeviceNameNetlinkAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.InetAddrSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameNetlinkAddrParams() beforehand. +func (o *DeleteDeviceNameNetlinkAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.InetAddrSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameNetlinkAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_responses.go new file mode 100644 index 000000000..25d71dc7d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameNetlinkAddrOKCode is the HTTP code returned for type DeleteDeviceNameNetlinkAddrOK +const DeleteDeviceNameNetlinkAddrOKCode int = 200 + +/* +DeleteDeviceNameNetlinkAddrOK Success + +swagger:response deleteDeviceNameNetlinkAddrOK +*/ +type DeleteDeviceNameNetlinkAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameNetlinkAddrOK creates DeleteDeviceNameNetlinkAddrOK with default headers values +func NewDeleteDeviceNameNetlinkAddrOK() *DeleteDeviceNameNetlinkAddrOK { + + return &DeleteDeviceNameNetlinkAddrOK{} +} + +// WithPayload adds the payload to the delete device name netlink addr o k response +func (o *DeleteDeviceNameNetlinkAddrOK) WithPayload(payload string) *DeleteDeviceNameNetlinkAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name netlink addr o k response +func (o *DeleteDeviceNameNetlinkAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameNetlinkAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameNetlinkAddrInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameNetlinkAddrInternalServerError +const DeleteDeviceNameNetlinkAddrInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameNetlinkAddrInternalServerError Not Found + +swagger:response deleteDeviceNameNetlinkAddrInternalServerError +*/ +type DeleteDeviceNameNetlinkAddrInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameNetlinkAddrInternalServerError creates DeleteDeviceNameNetlinkAddrInternalServerError with default headers values +func NewDeleteDeviceNameNetlinkAddrInternalServerError() *DeleteDeviceNameNetlinkAddrInternalServerError { + + return &DeleteDeviceNameNetlinkAddrInternalServerError{} +} + +// WithPayload adds the payload to the delete device name netlink addr internal server error response +func (o *DeleteDeviceNameNetlinkAddrInternalServerError) WithPayload(payload string) *DeleteDeviceNameNetlinkAddrInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name netlink addr internal server error response +func (o *DeleteDeviceNameNetlinkAddrInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameNetlinkAddrInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_urlbuilder.go new file mode 100644 index 000000000..581dbc5f3 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteDeviceNameNetlinkAddrURL generates an URL for the delete device name netlink addr operation +type DeleteDeviceNameNetlinkAddrURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameNetlinkAddrURL) WithBasePath(bp string) *DeleteDeviceNameNetlinkAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameNetlinkAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameNetlinkAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameNetlinkAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameNetlinkAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameNetlinkAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameNetlinkAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameNetlinkAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameNetlinkAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameNetlinkAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_parameters.go new file mode 100644 index 000000000..8dd329583 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewDeleteDeviceNameNetlinkParams creates a new DeleteDeviceNameNetlinkParams object +// +// There are no default values defined in the spec. +func NewDeleteDeviceNameNetlinkParams() DeleteDeviceNameNetlinkParams { + + return DeleteDeviceNameNetlinkParams{} +} + +// DeleteDeviceNameNetlinkParams contains all the bound params for the delete device name netlink operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameNetlink +type DeleteDeviceNameNetlinkParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameNetlinkParams() beforehand. +func (o *DeleteDeviceNameNetlinkParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameNetlinkParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_responses.go new file mode 100644 index 000000000..fd82c62e1 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameNetlinkOKCode is the HTTP code returned for type DeleteDeviceNameNetlinkOK +const DeleteDeviceNameNetlinkOKCode int = 200 + +/* +DeleteDeviceNameNetlinkOK Success + +swagger:response deleteDeviceNameNetlinkOK +*/ +type DeleteDeviceNameNetlinkOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameNetlinkOK creates DeleteDeviceNameNetlinkOK with default headers values +func NewDeleteDeviceNameNetlinkOK() *DeleteDeviceNameNetlinkOK { + + return &DeleteDeviceNameNetlinkOK{} +} + +// WithPayload adds the payload to the delete device name netlink o k response +func (o *DeleteDeviceNameNetlinkOK) WithPayload(payload string) *DeleteDeviceNameNetlinkOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name netlink o k response +func (o *DeleteDeviceNameNetlinkOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameNetlinkOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameNetlinkInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameNetlinkInternalServerError +const DeleteDeviceNameNetlinkInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameNetlinkInternalServerError Not Found + +swagger:response deleteDeviceNameNetlinkInternalServerError +*/ +type DeleteDeviceNameNetlinkInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameNetlinkInternalServerError creates DeleteDeviceNameNetlinkInternalServerError with default headers values +func NewDeleteDeviceNameNetlinkInternalServerError() *DeleteDeviceNameNetlinkInternalServerError { + + return &DeleteDeviceNameNetlinkInternalServerError{} +} + +// WithPayload adds the payload to the delete device name netlink internal server error response +func (o *DeleteDeviceNameNetlinkInternalServerError) WithPayload(payload string) *DeleteDeviceNameNetlinkInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name netlink internal server error response +func (o *DeleteDeviceNameNetlinkInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameNetlinkInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_urlbuilder.go new file mode 100644 index 000000000..460186582 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteDeviceNameNetlinkURL generates an URL for the delete device name netlink operation +type DeleteDeviceNameNetlinkURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameNetlinkURL) WithBasePath(bp string) *DeleteDeviceNameNetlinkURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameNetlinkURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameNetlinkURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameNetlinkURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameNetlinkURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameNetlinkURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameNetlinkURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameNetlinkURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameNetlinkURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameNetlinkURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_route.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route.go new file mode 100644 index 000000000..8cce8d372 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameRouteHandlerFunc turns a function with the right signature into a delete device name route handler +type DeleteDeviceNameRouteHandlerFunc func(DeleteDeviceNameRouteParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameRouteHandlerFunc) Handle(params DeleteDeviceNameRouteParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameRouteHandler interface for that can handle valid delete device name route params +type DeleteDeviceNameRouteHandler interface { + Handle(DeleteDeviceNameRouteParams) middleware.Responder +} + +// NewDeleteDeviceNameRoute creates a new http.Handler for the delete device name route operation +func NewDeleteDeviceNameRoute(ctx *middleware.Context, handler DeleteDeviceNameRouteHandler) *DeleteDeviceNameRoute { + return &DeleteDeviceNameRoute{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameRoute swagger:route DELETE /device/{name}/route device deleteDeviceNameRoute + +delete special net device route +*/ +type DeleteDeviceNameRoute struct { + Context *middleware.Context + Handler DeleteDeviceNameRouteHandler +} + +func (o *DeleteDeviceNameRoute) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameRouteParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_parameters.go new file mode 100644 index 000000000..47b47fba7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteDeviceNameRouteParams creates a new DeleteDeviceNameRouteParams object +// +// There are no default values defined in the spec. +func NewDeleteDeviceNameRouteParams() DeleteDeviceNameRouteParams { + + return DeleteDeviceNameRouteParams{} +} + +// DeleteDeviceNameRouteParams contains all the bound params for the delete device name route operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameRoute +type DeleteDeviceNameRouteParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.RouteSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameRouteParams() beforehand. +func (o *DeleteDeviceNameRouteParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RouteSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameRouteParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_responses.go new file mode 100644 index 000000000..c9146f0fe --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameRouteOKCode is the HTTP code returned for type DeleteDeviceNameRouteOK +const DeleteDeviceNameRouteOKCode int = 200 + +/* +DeleteDeviceNameRouteOK delete route Success + +swagger:response deleteDeviceNameRouteOK +*/ +type DeleteDeviceNameRouteOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameRouteOK creates DeleteDeviceNameRouteOK with default headers values +func NewDeleteDeviceNameRouteOK() *DeleteDeviceNameRouteOK { + + return &DeleteDeviceNameRouteOK{} +} + +// WithPayload adds the payload to the delete device name route o k response +func (o *DeleteDeviceNameRouteOK) WithPayload(payload string) *DeleteDeviceNameRouteOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name route o k response +func (o *DeleteDeviceNameRouteOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameRouteOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameRouteInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameRouteInternalServerError +const DeleteDeviceNameRouteInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameRouteInternalServerError Failed + +swagger:response deleteDeviceNameRouteInternalServerError +*/ +type DeleteDeviceNameRouteInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameRouteInternalServerError creates DeleteDeviceNameRouteInternalServerError with default headers values +func NewDeleteDeviceNameRouteInternalServerError() *DeleteDeviceNameRouteInternalServerError { + + return &DeleteDeviceNameRouteInternalServerError{} +} + +// WithPayload adds the payload to the delete device name route internal server error response +func (o *DeleteDeviceNameRouteInternalServerError) WithPayload(payload string) *DeleteDeviceNameRouteInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name route internal server error response +func (o *DeleteDeviceNameRouteInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameRouteInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_urlbuilder.go new file mode 100644 index 000000000..8be3d0374 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteDeviceNameRouteURL generates an URL for the delete device name route operation +type DeleteDeviceNameRouteURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameRouteURL) WithBasePath(bp string) *DeleteDeviceNameRouteURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameRouteURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameRouteURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/route" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameRouteURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameRouteURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameRouteURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameRouteURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameRouteURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameRouteURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameRouteURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan.go new file mode 100644 index 000000000..88d8a8feb --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameVlanHandlerFunc turns a function with the right signature into a delete device name vlan handler +type DeleteDeviceNameVlanHandlerFunc func(DeleteDeviceNameVlanParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameVlanHandlerFunc) Handle(params DeleteDeviceNameVlanParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameVlanHandler interface for that can handle valid delete device name vlan params +type DeleteDeviceNameVlanHandler interface { + Handle(DeleteDeviceNameVlanParams) middleware.Responder +} + +// NewDeleteDeviceNameVlan creates a new http.Handler for the delete device name vlan operation +func NewDeleteDeviceNameVlan(ctx *middleware.Context, handler DeleteDeviceNameVlanHandler) *DeleteDeviceNameVlan { + return &DeleteDeviceNameVlan{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameVlan swagger:route DELETE /device/{name}/vlan device deleteDeviceNameVlan + +delete special net device +*/ +type DeleteDeviceNameVlan struct { + Context *middleware.Context + Handler DeleteDeviceNameVlanHandler +} + +func (o *DeleteDeviceNameVlan) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameVlanParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_parameters.go new file mode 100644 index 000000000..ab157fa5a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewDeleteDeviceNameVlanParams creates a new DeleteDeviceNameVlanParams object +// +// There are no default values defined in the spec. +func NewDeleteDeviceNameVlanParams() DeleteDeviceNameVlanParams { + + return DeleteDeviceNameVlanParams{} +} + +// DeleteDeviceNameVlanParams contains all the bound params for the delete device name vlan operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameVlan +type DeleteDeviceNameVlanParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameVlanParams() beforehand. +func (o *DeleteDeviceNameVlanParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameVlanParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_responses.go new file mode 100644 index 000000000..f6a934a11 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameVlanOKCode is the HTTP code returned for type DeleteDeviceNameVlanOK +const DeleteDeviceNameVlanOKCode int = 200 + +/* +DeleteDeviceNameVlanOK Success + +swagger:response deleteDeviceNameVlanOK +*/ +type DeleteDeviceNameVlanOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameVlanOK creates DeleteDeviceNameVlanOK with default headers values +func NewDeleteDeviceNameVlanOK() *DeleteDeviceNameVlanOK { + + return &DeleteDeviceNameVlanOK{} +} + +// WithPayload adds the payload to the delete device name vlan o k response +func (o *DeleteDeviceNameVlanOK) WithPayload(payload string) *DeleteDeviceNameVlanOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name vlan o k response +func (o *DeleteDeviceNameVlanOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameVlanOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameVlanInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameVlanInternalServerError +const DeleteDeviceNameVlanInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameVlanInternalServerError Failed + +swagger:response deleteDeviceNameVlanInternalServerError +*/ +type DeleteDeviceNameVlanInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameVlanInternalServerError creates DeleteDeviceNameVlanInternalServerError with default headers values +func NewDeleteDeviceNameVlanInternalServerError() *DeleteDeviceNameVlanInternalServerError { + + return &DeleteDeviceNameVlanInternalServerError{} +} + +// WithPayload adds the payload to the delete device name vlan internal server error response +func (o *DeleteDeviceNameVlanInternalServerError) WithPayload(payload string) *DeleteDeviceNameVlanInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name vlan internal server error response +func (o *DeleteDeviceNameVlanInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameVlanInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_urlbuilder.go new file mode 100644 index 000000000..e0e5ef6cf --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteDeviceNameVlanURL generates an URL for the delete device name vlan operation +type DeleteDeviceNameVlanURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameVlanURL) WithBasePath(bp string) *DeleteDeviceNameVlanURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameVlanURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameVlanURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/vlan" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameVlanURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameVlanURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameVlanURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameVlanURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameVlanURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameVlanURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameVlanURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device.go b/tools/dpvs-agent/restapi/operations/device/get_device.go new file mode 100644 index 000000000..f9f968395 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceHandlerFunc turns a function with the right signature into a get device handler +type GetDeviceHandlerFunc func(GetDeviceParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceHandlerFunc) Handle(params GetDeviceParams) middleware.Responder { + return fn(params) +} + +// GetDeviceHandler interface for that can handle valid get device params +type GetDeviceHandler interface { + Handle(GetDeviceParams) middleware.Responder +} + +// NewGetDevice creates a new http.Handler for the get device operation +func NewGetDevice(ctx *middleware.Context, handler GetDeviceHandler) *GetDevice { + return &GetDevice{Context: ctx, Handler: handler} +} + +/* + GetDevice swagger:route GET /device device getDevice + +display all net device list +*/ +type GetDevice struct { + Context *middleware.Context + Handler GetDeviceHandler +} + +func (o *GetDevice) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_addr.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr.go new file mode 100644 index 000000000..0c159713c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameAddrHandlerFunc turns a function with the right signature into a get device name addr handler +type GetDeviceNameAddrHandlerFunc func(GetDeviceNameAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameAddrHandlerFunc) Handle(params GetDeviceNameAddrParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameAddrHandler interface for that can handle valid get device name addr params +type GetDeviceNameAddrHandler interface { + Handle(GetDeviceNameAddrParams) middleware.Responder +} + +// NewGetDeviceNameAddr creates a new http.Handler for the get device name addr operation +func NewGetDeviceNameAddr(ctx *middleware.Context, handler GetDeviceNameAddrHandler) *GetDeviceNameAddr { + return &GetDeviceNameAddr{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameAddr swagger:route GET /device/{name}/addr device getDeviceNameAddr + +display special net device ip addr +*/ +type GetDeviceNameAddr struct { + Context *middleware.Context + Handler GetDeviceNameAddrHandler +} + +func (o *GetDeviceNameAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_parameters.go new file mode 100644 index 000000000..cc1620fa7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_parameters.go @@ -0,0 +1,153 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameAddrParams creates a new GetDeviceNameAddrParams object +// with the default values initialized. +func NewGetDeviceNameAddrParams() GetDeviceNameAddrParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + verboseDefault = bool(false) + ) + + return GetDeviceNameAddrParams{ + Stats: &statsDefault, + + Verbose: &verboseDefault, + } +} + +// GetDeviceNameAddrParams contains all the bound params for the get device name addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameAddr +type GetDeviceNameAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool + /* + In: query + Default: false + */ + Verbose *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameAddrParams() beforehand. +func (o *GetDeviceNameAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + + qVerbose, qhkVerbose, _ := qs.GetOK("verbose") + if err := o.bindVerbose(qVerbose, qhkVerbose, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameAddrParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} + +// bindVerbose binds and validates parameter Verbose from query. +func (o *GetDeviceNameAddrParams) bindVerbose(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("verbose", "query", "bool", raw) + } + o.Verbose = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_responses.go new file mode 100644 index 000000000..e2ff4ac14 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameAddrOKCode is the HTTP code returned for type GetDeviceNameAddrOK +const GetDeviceNameAddrOKCode int = 200 + +/* +GetDeviceNameAddrOK Success + +swagger:response getDeviceNameAddrOK +*/ +type GetDeviceNameAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameAddrOK creates GetDeviceNameAddrOK with default headers values +func NewGetDeviceNameAddrOK() *GetDeviceNameAddrOK { + + return &GetDeviceNameAddrOK{} +} + +// WithPayload adds the payload to the get device name addr o k response +func (o *GetDeviceNameAddrOK) WithPayload(payload string) *GetDeviceNameAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name addr o k response +func (o *GetDeviceNameAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameAddrNotFoundCode is the HTTP code returned for type GetDeviceNameAddrNotFound +const GetDeviceNameAddrNotFoundCode int = 404 + +/* +GetDeviceNameAddrNotFound Not Found + +swagger:response getDeviceNameAddrNotFound +*/ +type GetDeviceNameAddrNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameAddrNotFound creates GetDeviceNameAddrNotFound with default headers values +func NewGetDeviceNameAddrNotFound() *GetDeviceNameAddrNotFound { + + return &GetDeviceNameAddrNotFound{} +} + +// WithPayload adds the payload to the get device name addr not found response +func (o *GetDeviceNameAddrNotFound) WithPayload(payload string) *GetDeviceNameAddrNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name addr not found response +func (o *GetDeviceNameAddrNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameAddrNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_urlbuilder.go new file mode 100644 index 000000000..a4c2cd9db --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_urlbuilder.go @@ -0,0 +1,124 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameAddrURL generates an URL for the get device name addr operation +type GetDeviceNameAddrURL struct { + Name string + + Stats *bool + Verbose *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameAddrURL) WithBasePath(bp string) *GetDeviceNameAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + var verboseQ string + if o.Verbose != nil { + verboseQ = swag.FormatBool(*o.Verbose) + } + if verboseQ != "" { + qs.Set("verbose", verboseQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink.go new file mode 100644 index 000000000..04f4f4ce7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameNetlinkHandlerFunc turns a function with the right signature into a get device name netlink handler +type GetDeviceNameNetlinkHandlerFunc func(GetDeviceNameNetlinkParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameNetlinkHandlerFunc) Handle(params GetDeviceNameNetlinkParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameNetlinkHandler interface for that can handle valid get device name netlink params +type GetDeviceNameNetlinkHandler interface { + Handle(GetDeviceNameNetlinkParams) middleware.Responder +} + +// NewGetDeviceNameNetlink creates a new http.Handler for the get device name netlink operation +func NewGetDeviceNameNetlink(ctx *middleware.Context, handler GetDeviceNameNetlinkHandler) *GetDeviceNameNetlink { + return &GetDeviceNameNetlink{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameNetlink swagger:route GET /device/{name}/netlink device getDeviceNameNetlink + +ip link show dev ${name} +*/ +type GetDeviceNameNetlink struct { + Context *middleware.Context + Handler GetDeviceNameNetlinkHandler +} + +func (o *GetDeviceNameNetlink) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameNetlinkParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go new file mode 100644 index 000000000..d9670c047 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameNetlinkAddrHandlerFunc turns a function with the right signature into a get device name netlink addr handler +type GetDeviceNameNetlinkAddrHandlerFunc func(GetDeviceNameNetlinkAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameNetlinkAddrHandlerFunc) Handle(params GetDeviceNameNetlinkAddrParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameNetlinkAddrHandler interface for that can handle valid get device name netlink addr params +type GetDeviceNameNetlinkAddrHandler interface { + Handle(GetDeviceNameNetlinkAddrParams) middleware.Responder +} + +// NewGetDeviceNameNetlinkAddr creates a new http.Handler for the get device name netlink addr operation +func NewGetDeviceNameNetlinkAddr(ctx *middleware.Context, handler GetDeviceNameNetlinkAddrHandler) *GetDeviceNameNetlinkAddr { + return &GetDeviceNameNetlinkAddr{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameNetlinkAddr swagger:route GET /device/{name}/netlink/addr device getDeviceNameNetlinkAddr + +display special linux net device addr detail +*/ +type GetDeviceNameNetlinkAddr struct { + Context *middleware.Context + Handler GetDeviceNameNetlinkAddrHandler +} + +func (o *GetDeviceNameNetlinkAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameNetlinkAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_parameters.go new file mode 100644 index 000000000..ff3ffbf49 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameNetlinkAddrParams creates a new GetDeviceNameNetlinkAddrParams object +// with the default values initialized. +func NewGetDeviceNameNetlinkAddrParams() GetDeviceNameNetlinkAddrParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceNameNetlinkAddrParams{ + Stats: &statsDefault, + } +} + +// GetDeviceNameNetlinkAddrParams contains all the bound params for the get device name netlink addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameNetlinkAddr +type GetDeviceNameNetlinkAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameNetlinkAddrParams() beforehand. +func (o *GetDeviceNameNetlinkAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameNetlinkAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameNetlinkAddrParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameNetlinkAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_responses.go new file mode 100644 index 000000000..ee54be55b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameNetlinkAddrOKCode is the HTTP code returned for type GetDeviceNameNetlinkAddrOK +const GetDeviceNameNetlinkAddrOKCode int = 200 + +/* +GetDeviceNameNetlinkAddrOK Success + +swagger:response getDeviceNameNetlinkAddrOK +*/ +type GetDeviceNameNetlinkAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNetlinkAddrOK creates GetDeviceNameNetlinkAddrOK with default headers values +func NewGetDeviceNameNetlinkAddrOK() *GetDeviceNameNetlinkAddrOK { + + return &GetDeviceNameNetlinkAddrOK{} +} + +// WithPayload adds the payload to the get device name netlink addr o k response +func (o *GetDeviceNameNetlinkAddrOK) WithPayload(payload string) *GetDeviceNameNetlinkAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name netlink addr o k response +func (o *GetDeviceNameNetlinkAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNetlinkAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameNetlinkAddrNotFoundCode is the HTTP code returned for type GetDeviceNameNetlinkAddrNotFound +const GetDeviceNameNetlinkAddrNotFoundCode int = 404 + +/* +GetDeviceNameNetlinkAddrNotFound Not Found + +swagger:response getDeviceNameNetlinkAddrNotFound +*/ +type GetDeviceNameNetlinkAddrNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNetlinkAddrNotFound creates GetDeviceNameNetlinkAddrNotFound with default headers values +func NewGetDeviceNameNetlinkAddrNotFound() *GetDeviceNameNetlinkAddrNotFound { + + return &GetDeviceNameNetlinkAddrNotFound{} +} + +// WithPayload adds the payload to the get device name netlink addr not found response +func (o *GetDeviceNameNetlinkAddrNotFound) WithPayload(payload string) *GetDeviceNameNetlinkAddrNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name netlink addr not found response +func (o *GetDeviceNameNetlinkAddrNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNetlinkAddrNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_urlbuilder.go new file mode 100644 index 000000000..463da03fe --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameNetlinkAddrURL generates an URL for the get device name netlink addr operation +type GetDeviceNameNetlinkAddrURL struct { + Name string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNetlinkAddrURL) WithBasePath(bp string) *GetDeviceNameNetlinkAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNetlinkAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameNetlinkAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameNetlinkAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameNetlinkAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameNetlinkAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameNetlinkAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameNetlinkAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameNetlinkAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameNetlinkAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_parameters.go new file mode 100644 index 000000000..99f198265 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameNetlinkParams creates a new GetDeviceNameNetlinkParams object +// with the default values initialized. +func NewGetDeviceNameNetlinkParams() GetDeviceNameNetlinkParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceNameNetlinkParams{ + Stats: &statsDefault, + } +} + +// GetDeviceNameNetlinkParams contains all the bound params for the get device name netlink operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameNetlink +type GetDeviceNameNetlinkParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameNetlinkParams() beforehand. +func (o *GetDeviceNameNetlinkParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameNetlinkParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameNetlinkParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameNetlinkParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_responses.go new file mode 100644 index 000000000..865e01439 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameNetlinkOKCode is the HTTP code returned for type GetDeviceNameNetlinkOK +const GetDeviceNameNetlinkOKCode int = 200 + +/* +GetDeviceNameNetlinkOK Success + +swagger:response getDeviceNameNetlinkOK +*/ +type GetDeviceNameNetlinkOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNetlinkOK creates GetDeviceNameNetlinkOK with default headers values +func NewGetDeviceNameNetlinkOK() *GetDeviceNameNetlinkOK { + + return &GetDeviceNameNetlinkOK{} +} + +// WithPayload adds the payload to the get device name netlink o k response +func (o *GetDeviceNameNetlinkOK) WithPayload(payload string) *GetDeviceNameNetlinkOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name netlink o k response +func (o *GetDeviceNameNetlinkOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNetlinkOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameNetlinkNotFoundCode is the HTTP code returned for type GetDeviceNameNetlinkNotFound +const GetDeviceNameNetlinkNotFoundCode int = 404 + +/* +GetDeviceNameNetlinkNotFound Not Found + +swagger:response getDeviceNameNetlinkNotFound +*/ +type GetDeviceNameNetlinkNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNetlinkNotFound creates GetDeviceNameNetlinkNotFound with default headers values +func NewGetDeviceNameNetlinkNotFound() *GetDeviceNameNetlinkNotFound { + + return &GetDeviceNameNetlinkNotFound{} +} + +// WithPayload adds the payload to the get device name netlink not found response +func (o *GetDeviceNameNetlinkNotFound) WithPayload(payload string) *GetDeviceNameNetlinkNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name netlink not found response +func (o *GetDeviceNameNetlinkNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNetlinkNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_urlbuilder.go new file mode 100644 index 000000000..2f9847cdc --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameNetlinkURL generates an URL for the get device name netlink operation +type GetDeviceNameNetlinkURL struct { + Name string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNetlinkURL) WithBasePath(bp string) *GetDeviceNameNetlinkURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNetlinkURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameNetlinkURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameNetlinkURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameNetlinkURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameNetlinkURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameNetlinkURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameNetlinkURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameNetlinkURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameNetlinkURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_nic.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic.go new file mode 100644 index 000000000..1f58cbd38 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameNicHandlerFunc turns a function with the right signature into a get device name nic handler +type GetDeviceNameNicHandlerFunc func(GetDeviceNameNicParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameNicHandlerFunc) Handle(params GetDeviceNameNicParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameNicHandler interface for that can handle valid get device name nic params +type GetDeviceNameNicHandler interface { + Handle(GetDeviceNameNicParams) middleware.Responder +} + +// NewGetDeviceNameNic creates a new http.Handler for the get device name nic operation +func NewGetDeviceNameNic(ctx *middleware.Context, handler GetDeviceNameNicHandler) *GetDeviceNameNic { + return &GetDeviceNameNic{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameNic swagger:route GET /device/{name}/nic device getDeviceNameNic + +dpip link show ${nic-name} -s -v +*/ +type GetDeviceNameNic struct { + Context *middleware.Context + Handler GetDeviceNameNicHandler +} + +func (o *GetDeviceNameNic) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameNicParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_parameters.go new file mode 100644 index 000000000..d09091d52 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_parameters.go @@ -0,0 +1,153 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameNicParams creates a new GetDeviceNameNicParams object +// with the default values initialized. +func NewGetDeviceNameNicParams() GetDeviceNameNicParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + verboseDefault = bool(false) + ) + + return GetDeviceNameNicParams{ + Stats: &statsDefault, + + Verbose: &verboseDefault, + } +} + +// GetDeviceNameNicParams contains all the bound params for the get device name nic operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameNic +type GetDeviceNameNicParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool + /* + In: query + Default: false + */ + Verbose *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameNicParams() beforehand. +func (o *GetDeviceNameNicParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + + qVerbose, qhkVerbose, _ := qs.GetOK("verbose") + if err := o.bindVerbose(qVerbose, qhkVerbose, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameNicParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameNicParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameNicParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} + +// bindVerbose binds and validates parameter Verbose from query. +func (o *GetDeviceNameNicParams) bindVerbose(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameNicParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("verbose", "query", "bool", raw) + } + o.Verbose = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_responses.go new file mode 100644 index 000000000..b55984b92 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_responses.go @@ -0,0 +1,102 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// GetDeviceNameNicOKCode is the HTTP code returned for type GetDeviceNameNicOK +const GetDeviceNameNicOKCode int = 200 + +/* +GetDeviceNameNicOK Success + +swagger:response getDeviceNameNicOK +*/ +type GetDeviceNameNicOK struct { + + /* + In: Body + */ + Payload *models.NicDeviceSpecList `json:"body,omitempty"` +} + +// NewGetDeviceNameNicOK creates GetDeviceNameNicOK with default headers values +func NewGetDeviceNameNicOK() *GetDeviceNameNicOK { + + return &GetDeviceNameNicOK{} +} + +// WithPayload adds the payload to the get device name nic o k response +func (o *GetDeviceNameNicOK) WithPayload(payload *models.NicDeviceSpecList) *GetDeviceNameNicOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name nic o k response +func (o *GetDeviceNameNicOK) SetPayload(payload *models.NicDeviceSpecList) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNicOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetDeviceNameNicInternalServerErrorCode is the HTTP code returned for type GetDeviceNameNicInternalServerError +const GetDeviceNameNicInternalServerErrorCode int = 500 + +/* +GetDeviceNameNicInternalServerError Failure + +swagger:response getDeviceNameNicInternalServerError +*/ +type GetDeviceNameNicInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNicInternalServerError creates GetDeviceNameNicInternalServerError with default headers values +func NewGetDeviceNameNicInternalServerError() *GetDeviceNameNicInternalServerError { + + return &GetDeviceNameNicInternalServerError{} +} + +// WithPayload adds the payload to the get device name nic internal server error response +func (o *GetDeviceNameNicInternalServerError) WithPayload(payload string) *GetDeviceNameNicInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name nic internal server error response +func (o *GetDeviceNameNicInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNicInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_urlbuilder.go new file mode 100644 index 000000000..9d1b99104 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_urlbuilder.go @@ -0,0 +1,124 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameNicURL generates an URL for the get device name nic operation +type GetDeviceNameNicURL struct { + Name string + + Stats *bool + Verbose *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNicURL) WithBasePath(bp string) *GetDeviceNameNicURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNicURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameNicURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/nic" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameNicURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + var verboseQ string + if o.Verbose != nil { + verboseQ = swag.FormatBool(*o.Verbose) + } + if verboseQ != "" { + qs.Set("verbose", verboseQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameNicURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameNicURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameNicURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameNicURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameNicURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameNicURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_route.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_route.go new file mode 100644 index 000000000..fe7625fc1 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_route.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameRouteHandlerFunc turns a function with the right signature into a get device name route handler +type GetDeviceNameRouteHandlerFunc func(GetDeviceNameRouteParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameRouteHandlerFunc) Handle(params GetDeviceNameRouteParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameRouteHandler interface for that can handle valid get device name route params +type GetDeviceNameRouteHandler interface { + Handle(GetDeviceNameRouteParams) middleware.Responder +} + +// NewGetDeviceNameRoute creates a new http.Handler for the get device name route operation +func NewGetDeviceNameRoute(ctx *middleware.Context, handler GetDeviceNameRouteHandler) *GetDeviceNameRoute { + return &GetDeviceNameRoute{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameRoute swagger:route GET /device/{name}/route device getDeviceNameRoute + +display special net device route +*/ +type GetDeviceNameRoute struct { + Context *middleware.Context + Handler GetDeviceNameRouteHandler +} + +func (o *GetDeviceNameRoute) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameRouteParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_route_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_parameters.go new file mode 100644 index 000000000..00ab725c6 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameRouteParams creates a new GetDeviceNameRouteParams object +// with the default values initialized. +func NewGetDeviceNameRouteParams() GetDeviceNameRouteParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceNameRouteParams{ + Stats: &statsDefault, + } +} + +// GetDeviceNameRouteParams contains all the bound params for the get device name route operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameRoute +type GetDeviceNameRouteParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameRouteParams() beforehand. +func (o *GetDeviceNameRouteParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameRouteParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameRouteParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameRouteParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_route_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_responses.go new file mode 100644 index 000000000..d66415808 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameRouteOKCode is the HTTP code returned for type GetDeviceNameRouteOK +const GetDeviceNameRouteOKCode int = 200 + +/* +GetDeviceNameRouteOK Success + +swagger:response getDeviceNameRouteOK +*/ +type GetDeviceNameRouteOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameRouteOK creates GetDeviceNameRouteOK with default headers values +func NewGetDeviceNameRouteOK() *GetDeviceNameRouteOK { + + return &GetDeviceNameRouteOK{} +} + +// WithPayload adds the payload to the get device name route o k response +func (o *GetDeviceNameRouteOK) WithPayload(payload string) *GetDeviceNameRouteOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name route o k response +func (o *GetDeviceNameRouteOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameRouteOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameRouteNotFoundCode is the HTTP code returned for type GetDeviceNameRouteNotFound +const GetDeviceNameRouteNotFoundCode int = 404 + +/* +GetDeviceNameRouteNotFound Not Found + +swagger:response getDeviceNameRouteNotFound +*/ +type GetDeviceNameRouteNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameRouteNotFound creates GetDeviceNameRouteNotFound with default headers values +func NewGetDeviceNameRouteNotFound() *GetDeviceNameRouteNotFound { + + return &GetDeviceNameRouteNotFound{} +} + +// WithPayload adds the payload to the get device name route not found response +func (o *GetDeviceNameRouteNotFound) WithPayload(payload string) *GetDeviceNameRouteNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name route not found response +func (o *GetDeviceNameRouteNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameRouteNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_route_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_urlbuilder.go new file mode 100644 index 000000000..167d1f25a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameRouteURL generates an URL for the get device name route operation +type GetDeviceNameRouteURL struct { + Name string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameRouteURL) WithBasePath(bp string) *GetDeviceNameRouteURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameRouteURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameRouteURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/route" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameRouteURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameRouteURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameRouteURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameRouteURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameRouteURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameRouteURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameRouteURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan.go new file mode 100644 index 000000000..78539a3f5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameVlanHandlerFunc turns a function with the right signature into a get device name vlan handler +type GetDeviceNameVlanHandlerFunc func(GetDeviceNameVlanParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameVlanHandlerFunc) Handle(params GetDeviceNameVlanParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameVlanHandler interface for that can handle valid get device name vlan params +type GetDeviceNameVlanHandler interface { + Handle(GetDeviceNameVlanParams) middleware.Responder +} + +// NewGetDeviceNameVlan creates a new http.Handler for the get device name vlan operation +func NewGetDeviceNameVlan(ctx *middleware.Context, handler GetDeviceNameVlanHandler) *GetDeviceNameVlan { + return &GetDeviceNameVlan{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameVlan swagger:route GET /device/{name}/vlan device getDeviceNameVlan + +display all net device list +*/ +type GetDeviceNameVlan struct { + Context *middleware.Context + Handler GetDeviceNameVlanHandler +} + +func (o *GetDeviceNameVlan) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameVlanParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_parameters.go new file mode 100644 index 000000000..1188161c8 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameVlanParams creates a new GetDeviceNameVlanParams object +// with the default values initialized. +func NewGetDeviceNameVlanParams() GetDeviceNameVlanParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceNameVlanParams{ + Stats: &statsDefault, + } +} + +// GetDeviceNameVlanParams contains all the bound params for the get device name vlan operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameVlan +type GetDeviceNameVlanParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameVlanParams() beforehand. +func (o *GetDeviceNameVlanParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameVlanParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameVlanParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameVlanParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_responses.go new file mode 100644 index 000000000..d3bf35e47 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameVlanOKCode is the HTTP code returned for type GetDeviceNameVlanOK +const GetDeviceNameVlanOKCode int = 200 + +/* +GetDeviceNameVlanOK Success + +swagger:response getDeviceNameVlanOK +*/ +type GetDeviceNameVlanOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameVlanOK creates GetDeviceNameVlanOK with default headers values +func NewGetDeviceNameVlanOK() *GetDeviceNameVlanOK { + + return &GetDeviceNameVlanOK{} +} + +// WithPayload adds the payload to the get device name vlan o k response +func (o *GetDeviceNameVlanOK) WithPayload(payload string) *GetDeviceNameVlanOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name vlan o k response +func (o *GetDeviceNameVlanOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameVlanOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameVlanNotFoundCode is the HTTP code returned for type GetDeviceNameVlanNotFound +const GetDeviceNameVlanNotFoundCode int = 404 + +/* +GetDeviceNameVlanNotFound Not Found + +swagger:response getDeviceNameVlanNotFound +*/ +type GetDeviceNameVlanNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameVlanNotFound creates GetDeviceNameVlanNotFound with default headers values +func NewGetDeviceNameVlanNotFound() *GetDeviceNameVlanNotFound { + + return &GetDeviceNameVlanNotFound{} +} + +// WithPayload adds the payload to the get device name vlan not found response +func (o *GetDeviceNameVlanNotFound) WithPayload(payload string) *GetDeviceNameVlanNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name vlan not found response +func (o *GetDeviceNameVlanNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameVlanNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_urlbuilder.go new file mode 100644 index 000000000..7044acbc9 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameVlanURL generates an URL for the get device name vlan operation +type GetDeviceNameVlanURL struct { + Name string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameVlanURL) WithBasePath(bp string) *GetDeviceNameVlanURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameVlanURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameVlanURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/vlan" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameVlanURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameVlanURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameVlanURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameVlanURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameVlanURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameVlanURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameVlanURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_parameters.go new file mode 100644 index 000000000..59c367e91 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_parameters.go @@ -0,0 +1,92 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceParams creates a new GetDeviceParams object +// with the default values initialized. +func NewGetDeviceParams() GetDeviceParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceParams{ + Stats: &statsDefault, + } +} + +// GetDeviceParams contains all the bound params for the get device operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDevice +type GetDeviceParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceParams() beforehand. +func (o *GetDeviceParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_responses.go new file mode 100644 index 000000000..c9b51cc5e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_responses.go @@ -0,0 +1,55 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceOKCode is the HTTP code returned for type GetDeviceOK +const GetDeviceOKCode int = 200 + +/* +GetDeviceOK Success + +swagger:response getDeviceOK +*/ +type GetDeviceOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceOK creates GetDeviceOK with default headers values +func NewGetDeviceOK() *GetDeviceOK { + + return &GetDeviceOK{} +} + +// WithPayload adds the payload to the get device o k response +func (o *GetDeviceOK) WithPayload(payload string) *GetDeviceOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device o k response +func (o *GetDeviceOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_urlbuilder.go new file mode 100644 index 000000000..87d5f1eab --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_urlbuilder.go @@ -0,0 +1,105 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + + "github.com/go-openapi/swag" +) + +// GetDeviceURL generates an URL for the get device operation +type GetDeviceURL struct { + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceURL) WithBasePath(bp string) *GetDeviceURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_addr.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr.go new file mode 100644 index 000000000..2d46e6c55 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameAddrHandlerFunc turns a function with the right signature into a put device name addr handler +type PutDeviceNameAddrHandlerFunc func(PutDeviceNameAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameAddrHandlerFunc) Handle(params PutDeviceNameAddrParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameAddrHandler interface for that can handle valid put device name addr params +type PutDeviceNameAddrHandler interface { + Handle(PutDeviceNameAddrParams) middleware.Responder +} + +// NewPutDeviceNameAddr creates a new http.Handler for the put device name addr operation +func NewPutDeviceNameAddr(ctx *middleware.Context, handler PutDeviceNameAddrHandler) *PutDeviceNameAddr { + return &PutDeviceNameAddr{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameAddr swagger:route PUT /device/{name}/addr device putDeviceNameAddr + +add/update special net device ip addr +*/ +type PutDeviceNameAddr struct { + Context *middleware.Context + Handler PutDeviceNameAddrHandler +} + +func (o *PutDeviceNameAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_parameters.go new file mode 100644 index 000000000..07bc411bb --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_parameters.go @@ -0,0 +1,145 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutDeviceNameAddrParams creates a new PutDeviceNameAddrParams object +// with the default values initialized. +func NewPutDeviceNameAddrParams() PutDeviceNameAddrParams { + + var ( + // initialize parameters with default values + + sapoolDefault = bool(false) + ) + + return PutDeviceNameAddrParams{ + Sapool: &sapoolDefault, + } +} + +// PutDeviceNameAddrParams contains all the bound params for the put device name addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameAddr +type PutDeviceNameAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Sapool *bool + /* + In: body + */ + Spec *models.InetAddrSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameAddrParams() beforehand. +func (o *PutDeviceNameAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qSapool, qhkSapool, _ := qs.GetOK("sapool") + if err := o.bindSapool(qSapool, qhkSapool, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.InetAddrSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindSapool binds and validates parameter Sapool from query. +func (o *PutDeviceNameAddrParams) bindSapool(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutDeviceNameAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("sapool", "query", "bool", raw) + } + o.Sapool = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_responses.go new file mode 100644 index 000000000..417f1d91d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_responses.go @@ -0,0 +1,141 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameAddrOKCode is the HTTP code returned for type PutDeviceNameAddrOK +const PutDeviceNameAddrOKCode int = 200 + +/* +PutDeviceNameAddrOK Update exist ip addr Success + +swagger:response putDeviceNameAddrOK +*/ +type PutDeviceNameAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameAddrOK creates PutDeviceNameAddrOK with default headers values +func NewPutDeviceNameAddrOK() *PutDeviceNameAddrOK { + + return &PutDeviceNameAddrOK{} +} + +// WithPayload adds the payload to the put device name addr o k response +func (o *PutDeviceNameAddrOK) WithPayload(payload string) *PutDeviceNameAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name addr o k response +func (o *PutDeviceNameAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameAddrCreatedCode is the HTTP code returned for type PutDeviceNameAddrCreated +const PutDeviceNameAddrCreatedCode int = 201 + +/* +PutDeviceNameAddrCreated Add new ip addr Success + +swagger:response putDeviceNameAddrCreated +*/ +type PutDeviceNameAddrCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameAddrCreated creates PutDeviceNameAddrCreated with default headers values +func NewPutDeviceNameAddrCreated() *PutDeviceNameAddrCreated { + + return &PutDeviceNameAddrCreated{} +} + +// WithPayload adds the payload to the put device name addr created response +func (o *PutDeviceNameAddrCreated) WithPayload(payload string) *PutDeviceNameAddrCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name addr created response +func (o *PutDeviceNameAddrCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameAddrCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameAddrInternalServerErrorCode is the HTTP code returned for type PutDeviceNameAddrInternalServerError +const PutDeviceNameAddrInternalServerErrorCode int = 500 + +/* +PutDeviceNameAddrInternalServerError Failed + +swagger:response putDeviceNameAddrInternalServerError +*/ +type PutDeviceNameAddrInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameAddrInternalServerError creates PutDeviceNameAddrInternalServerError with default headers values +func NewPutDeviceNameAddrInternalServerError() *PutDeviceNameAddrInternalServerError { + + return &PutDeviceNameAddrInternalServerError{} +} + +// WithPayload adds the payload to the put device name addr internal server error response +func (o *PutDeviceNameAddrInternalServerError) WithPayload(payload string) *PutDeviceNameAddrInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name addr internal server error response +func (o *PutDeviceNameAddrInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameAddrInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_urlbuilder.go new file mode 100644 index 000000000..a136e39c6 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// PutDeviceNameAddrURL generates an URL for the put device name addr operation +type PutDeviceNameAddrURL struct { + Name string + + Sapool *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameAddrURL) WithBasePath(bp string) *PutDeviceNameAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var sapoolQ string + if o.Sapool != nil { + sapoolQ = swag.FormatBool(*o.Sapool) + } + if sapoolQ != "" { + qs.Set("sapool", sapoolQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink.go new file mode 100644 index 000000000..41ba0fcd6 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameNetlinkHandlerFunc turns a function with the right signature into a put device name netlink handler +type PutDeviceNameNetlinkHandlerFunc func(PutDeviceNameNetlinkParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameNetlinkHandlerFunc) Handle(params PutDeviceNameNetlinkParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameNetlinkHandler interface for that can handle valid put device name netlink params +type PutDeviceNameNetlinkHandler interface { + Handle(PutDeviceNameNetlinkParams) middleware.Responder +} + +// NewPutDeviceNameNetlink creates a new http.Handler for the put device name netlink operation +func NewPutDeviceNameNetlink(ctx *middleware.Context, handler PutDeviceNameNetlinkHandler) *PutDeviceNameNetlink { + return &PutDeviceNameNetlink{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameNetlink swagger:route PUT /device/{name}/netlink device putDeviceNameNetlink + +ip link set ${name} up +*/ +type PutDeviceNameNetlink struct { + Context *middleware.Context + Handler PutDeviceNameNetlinkHandler +} + +func (o *PutDeviceNameNetlink) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameNetlinkParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go new file mode 100644 index 000000000..b08ea86b7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameNetlinkAddrHandlerFunc turns a function with the right signature into a put device name netlink addr handler +type PutDeviceNameNetlinkAddrHandlerFunc func(PutDeviceNameNetlinkAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameNetlinkAddrHandlerFunc) Handle(params PutDeviceNameNetlinkAddrParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameNetlinkAddrHandler interface for that can handle valid put device name netlink addr params +type PutDeviceNameNetlinkAddrHandler interface { + Handle(PutDeviceNameNetlinkAddrParams) middleware.Responder +} + +// NewPutDeviceNameNetlinkAddr creates a new http.Handler for the put device name netlink addr operation +func NewPutDeviceNameNetlinkAddr(ctx *middleware.Context, handler PutDeviceNameNetlinkAddrHandler) *PutDeviceNameNetlinkAddr { + return &PutDeviceNameNetlinkAddr{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameNetlinkAddr swagger:route PUT /device/{name}/netlink/addr device putDeviceNameNetlinkAddr + +set ip cird to linux net device +*/ +type PutDeviceNameNetlinkAddr struct { + Context *middleware.Context + Handler PutDeviceNameNetlinkAddrHandler +} + +func (o *PutDeviceNameNetlinkAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameNetlinkAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_parameters.go new file mode 100644 index 000000000..7fcd77b11 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutDeviceNameNetlinkAddrParams creates a new PutDeviceNameNetlinkAddrParams object +// +// There are no default values defined in the spec. +func NewPutDeviceNameNetlinkAddrParams() PutDeviceNameNetlinkAddrParams { + + return PutDeviceNameNetlinkAddrParams{} +} + +// PutDeviceNameNetlinkAddrParams contains all the bound params for the put device name netlink addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameNetlinkAddr +type PutDeviceNameNetlinkAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.InetAddrSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameNetlinkAddrParams() beforehand. +func (o *PutDeviceNameNetlinkAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.InetAddrSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameNetlinkAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_responses.go new file mode 100644 index 000000000..b0287d36b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameNetlinkAddrOKCode is the HTTP code returned for type PutDeviceNameNetlinkAddrOK +const PutDeviceNameNetlinkAddrOKCode int = 200 + +/* +PutDeviceNameNetlinkAddrOK Success + +swagger:response putDeviceNameNetlinkAddrOK +*/ +type PutDeviceNameNetlinkAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNetlinkAddrOK creates PutDeviceNameNetlinkAddrOK with default headers values +func NewPutDeviceNameNetlinkAddrOK() *PutDeviceNameNetlinkAddrOK { + + return &PutDeviceNameNetlinkAddrOK{} +} + +// WithPayload adds the payload to the put device name netlink addr o k response +func (o *PutDeviceNameNetlinkAddrOK) WithPayload(payload string) *PutDeviceNameNetlinkAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name netlink addr o k response +func (o *PutDeviceNameNetlinkAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNetlinkAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameNetlinkAddrInternalServerErrorCode is the HTTP code returned for type PutDeviceNameNetlinkAddrInternalServerError +const PutDeviceNameNetlinkAddrInternalServerErrorCode int = 500 + +/* +PutDeviceNameNetlinkAddrInternalServerError Not Found + +swagger:response putDeviceNameNetlinkAddrInternalServerError +*/ +type PutDeviceNameNetlinkAddrInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNetlinkAddrInternalServerError creates PutDeviceNameNetlinkAddrInternalServerError with default headers values +func NewPutDeviceNameNetlinkAddrInternalServerError() *PutDeviceNameNetlinkAddrInternalServerError { + + return &PutDeviceNameNetlinkAddrInternalServerError{} +} + +// WithPayload adds the payload to the put device name netlink addr internal server error response +func (o *PutDeviceNameNetlinkAddrInternalServerError) WithPayload(payload string) *PutDeviceNameNetlinkAddrInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name netlink addr internal server error response +func (o *PutDeviceNameNetlinkAddrInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNetlinkAddrInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_urlbuilder.go new file mode 100644 index 000000000..ef47a83b2 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameNetlinkAddrURL generates an URL for the put device name netlink addr operation +type PutDeviceNameNetlinkAddrURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNetlinkAddrURL) WithBasePath(bp string) *PutDeviceNameNetlinkAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNetlinkAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameNetlinkAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameNetlinkAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameNetlinkAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameNetlinkAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameNetlinkAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameNetlinkAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameNetlinkAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameNetlinkAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_parameters.go new file mode 100644 index 000000000..d8d9e20f1 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewPutDeviceNameNetlinkParams creates a new PutDeviceNameNetlinkParams object +// +// There are no default values defined in the spec. +func NewPutDeviceNameNetlinkParams() PutDeviceNameNetlinkParams { + + return PutDeviceNameNetlinkParams{} +} + +// PutDeviceNameNetlinkParams contains all the bound params for the put device name netlink operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameNetlink +type PutDeviceNameNetlinkParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameNetlinkParams() beforehand. +func (o *PutDeviceNameNetlinkParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameNetlinkParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_responses.go new file mode 100644 index 000000000..ba2a6d07f --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameNetlinkOKCode is the HTTP code returned for type PutDeviceNameNetlinkOK +const PutDeviceNameNetlinkOKCode int = 200 + +/* +PutDeviceNameNetlinkOK Success + +swagger:response putDeviceNameNetlinkOK +*/ +type PutDeviceNameNetlinkOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNetlinkOK creates PutDeviceNameNetlinkOK with default headers values +func NewPutDeviceNameNetlinkOK() *PutDeviceNameNetlinkOK { + + return &PutDeviceNameNetlinkOK{} +} + +// WithPayload adds the payload to the put device name netlink o k response +func (o *PutDeviceNameNetlinkOK) WithPayload(payload string) *PutDeviceNameNetlinkOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name netlink o k response +func (o *PutDeviceNameNetlinkOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNetlinkOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameNetlinkInternalServerErrorCode is the HTTP code returned for type PutDeviceNameNetlinkInternalServerError +const PutDeviceNameNetlinkInternalServerErrorCode int = 500 + +/* +PutDeviceNameNetlinkInternalServerError Not Found + +swagger:response putDeviceNameNetlinkInternalServerError +*/ +type PutDeviceNameNetlinkInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNetlinkInternalServerError creates PutDeviceNameNetlinkInternalServerError with default headers values +func NewPutDeviceNameNetlinkInternalServerError() *PutDeviceNameNetlinkInternalServerError { + + return &PutDeviceNameNetlinkInternalServerError{} +} + +// WithPayload adds the payload to the put device name netlink internal server error response +func (o *PutDeviceNameNetlinkInternalServerError) WithPayload(payload string) *PutDeviceNameNetlinkInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name netlink internal server error response +func (o *PutDeviceNameNetlinkInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNetlinkInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_urlbuilder.go new file mode 100644 index 000000000..1b636026c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameNetlinkURL generates an URL for the put device name netlink operation +type PutDeviceNameNetlinkURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNetlinkURL) WithBasePath(bp string) *PutDeviceNameNetlinkURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNetlinkURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameNetlinkURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameNetlinkURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameNetlinkURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameNetlinkURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameNetlinkURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameNetlinkURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameNetlinkURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameNetlinkURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic.go new file mode 100644 index 000000000..4bf05efd7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameNicHandlerFunc turns a function with the right signature into a put device name nic handler +type PutDeviceNameNicHandlerFunc func(PutDeviceNameNicParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameNicHandlerFunc) Handle(params PutDeviceNameNicParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameNicHandler interface for that can handle valid put device name nic params +type PutDeviceNameNicHandler interface { + Handle(PutDeviceNameNicParams) middleware.Responder +} + +// NewPutDeviceNameNic creates a new http.Handler for the put device name nic operation +func NewPutDeviceNameNic(ctx *middleware.Context, handler PutDeviceNameNicHandler) *PutDeviceNameNic { + return &PutDeviceNameNic{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameNic swagger:route PUT /device/{name}/nic device putDeviceNameNic + +dpip link set ${nic-name} [forward2kni,link,promisc,tc-ingress,tc-egress] [on/up,off/down] +*/ +type PutDeviceNameNic struct { + Context *middleware.Context + Handler PutDeviceNameNicHandler +} + +func (o *PutDeviceNameNic) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameNicParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go new file mode 100644 index 000000000..a8cd915e3 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go @@ -0,0 +1,218 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// NewPutDeviceNameNicParams creates a new PutDeviceNameNicParams object +// with the default values initialized. +func NewPutDeviceNameNicParams() PutDeviceNameNicParams { + + var ( + // initialize parameters with default values + + forward2KniDefault = string("unset") + linkDefault = string("unset") + + promiscDefault = string("unset") + ) + + return PutDeviceNameNicParams{ + Forward2Kni: &forward2KniDefault, + + Link: &linkDefault, + + Promisc: &promiscDefault, + } +} + +// PutDeviceNameNicParams contains all the bound params for the put device name nic operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameNic +type PutDeviceNameNicParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: query + Default: "unset" + */ + Forward2Kni *string + /* + In: query + Default: "unset" + */ + Link *string + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: "unset" + */ + Promisc *string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameNicParams() beforehand. +func (o *PutDeviceNameNicParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + qForward2Kni, qhkForward2Kni, _ := qs.GetOK("forward2Kni") + if err := o.bindForward2Kni(qForward2Kni, qhkForward2Kni, route.Formats); err != nil { + res = append(res, err) + } + + qLink, qhkLink, _ := qs.GetOK("link") + if err := o.bindLink(qLink, qhkLink, route.Formats); err != nil { + res = append(res, err) + } + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qPromisc, qhkPromisc, _ := qs.GetOK("promisc") + if err := o.bindPromisc(qPromisc, qhkPromisc, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindForward2Kni binds and validates parameter Forward2Kni from query. +func (o *PutDeviceNameNicParams) bindForward2Kni(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutDeviceNameNicParams() + return nil + } + o.Forward2Kni = &raw + + if err := o.validateForward2Kni(formats); err != nil { + return err + } + + return nil +} + +// validateForward2Kni carries on validations for parameter Forward2Kni +func (o *PutDeviceNameNicParams) validateForward2Kni(formats strfmt.Registry) error { + + if err := validate.EnumCase("forward2Kni", "query", *o.Forward2Kni, []interface{}{"unset", "on", "off"}, true); err != nil { + return err + } + + return nil +} + +// bindLink binds and validates parameter Link from query. +func (o *PutDeviceNameNicParams) bindLink(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutDeviceNameNicParams() + return nil + } + o.Link = &raw + + if err := o.validateLink(formats); err != nil { + return err + } + + return nil +} + +// validateLink carries on validations for parameter Link +func (o *PutDeviceNameNicParams) validateLink(formats strfmt.Registry) error { + + if err := validate.EnumCase("link", "query", *o.Link, []interface{}{"unset", "up", "down"}, true); err != nil { + return err + } + + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameNicParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindPromisc binds and validates parameter Promisc from query. +func (o *PutDeviceNameNicParams) bindPromisc(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutDeviceNameNicParams() + return nil + } + o.Promisc = &raw + + if err := o.validatePromisc(formats); err != nil { + return err + } + + return nil +} + +// validatePromisc carries on validations for parameter Promisc +func (o *PutDeviceNameNicParams) validatePromisc(formats strfmt.Registry) error { + + if err := validate.EnumCase("promisc", "query", *o.Promisc, []interface{}{"unset", "on", "off"}, true); err != nil { + return err + } + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_responses.go new file mode 100644 index 000000000..2ca881446 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameNicOKCode is the HTTP code returned for type PutDeviceNameNicOK +const PutDeviceNameNicOKCode int = 200 + +/* +PutDeviceNameNicOK Success + +swagger:response putDeviceNameNicOK +*/ +type PutDeviceNameNicOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNicOK creates PutDeviceNameNicOK with default headers values +func NewPutDeviceNameNicOK() *PutDeviceNameNicOK { + + return &PutDeviceNameNicOK{} +} + +// WithPayload adds the payload to the put device name nic o k response +func (o *PutDeviceNameNicOK) WithPayload(payload string) *PutDeviceNameNicOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name nic o k response +func (o *PutDeviceNameNicOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNicOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameNicInternalServerErrorCode is the HTTP code returned for type PutDeviceNameNicInternalServerError +const PutDeviceNameNicInternalServerErrorCode int = 500 + +/* +PutDeviceNameNicInternalServerError Failure + +swagger:response putDeviceNameNicInternalServerError +*/ +type PutDeviceNameNicInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNicInternalServerError creates PutDeviceNameNicInternalServerError with default headers values +func NewPutDeviceNameNicInternalServerError() *PutDeviceNameNicInternalServerError { + + return &PutDeviceNameNicInternalServerError{} +} + +// WithPayload adds the payload to the put device name nic internal server error response +func (o *PutDeviceNameNicInternalServerError) WithPayload(payload string) *PutDeviceNameNicInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name nic internal server error response +func (o *PutDeviceNameNicInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNicInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_urlbuilder.go new file mode 100644 index 000000000..865956941 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_urlbuilder.go @@ -0,0 +1,131 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameNicURL generates an URL for the put device name nic operation +type PutDeviceNameNicURL struct { + Name string + + Forward2Kni *string + Link *string + Promisc *string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNicURL) WithBasePath(bp string) *PutDeviceNameNicURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNicURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameNicURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/nic" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameNicURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var forward2KniQ string + if o.Forward2Kni != nil { + forward2KniQ = *o.Forward2Kni + } + if forward2KniQ != "" { + qs.Set("forward2Kni", forward2KniQ) + } + + var linkQ string + if o.Link != nil { + linkQ = *o.Link + } + if linkQ != "" { + qs.Set("link", linkQ) + } + + var promiscQ string + if o.Promisc != nil { + promiscQ = *o.Promisc + } + if promiscQ != "" { + qs.Set("promisc", promiscQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameNicURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameNicURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameNicURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameNicURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameNicURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameNicURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_route.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_route.go new file mode 100644 index 000000000..e5b7940c5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_route.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameRouteHandlerFunc turns a function with the right signature into a put device name route handler +type PutDeviceNameRouteHandlerFunc func(PutDeviceNameRouteParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameRouteHandlerFunc) Handle(params PutDeviceNameRouteParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameRouteHandler interface for that can handle valid put device name route params +type PutDeviceNameRouteHandler interface { + Handle(PutDeviceNameRouteParams) middleware.Responder +} + +// NewPutDeviceNameRoute creates a new http.Handler for the put device name route operation +func NewPutDeviceNameRoute(ctx *middleware.Context, handler PutDeviceNameRouteHandler) *PutDeviceNameRoute { + return &PutDeviceNameRoute{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameRoute swagger:route PUT /device/{name}/route device putDeviceNameRoute + +add/update special net device route +*/ +type PutDeviceNameRoute struct { + Context *middleware.Context + Handler PutDeviceNameRouteHandler +} + +func (o *PutDeviceNameRoute) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameRouteParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_route_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_parameters.go new file mode 100644 index 000000000..29831e533 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutDeviceNameRouteParams creates a new PutDeviceNameRouteParams object +// +// There are no default values defined in the spec. +func NewPutDeviceNameRouteParams() PutDeviceNameRouteParams { + + return PutDeviceNameRouteParams{} +} + +// PutDeviceNameRouteParams contains all the bound params for the put device name route operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameRoute +type PutDeviceNameRouteParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.RouteSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameRouteParams() beforehand. +func (o *PutDeviceNameRouteParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RouteSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameRouteParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_route_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_responses.go new file mode 100644 index 000000000..87f0b47ed --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_responses.go @@ -0,0 +1,141 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameRouteOKCode is the HTTP code returned for type PutDeviceNameRouteOK +const PutDeviceNameRouteOKCode int = 200 + +/* +PutDeviceNameRouteOK Update exist route Success + +swagger:response putDeviceNameRouteOK +*/ +type PutDeviceNameRouteOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameRouteOK creates PutDeviceNameRouteOK with default headers values +func NewPutDeviceNameRouteOK() *PutDeviceNameRouteOK { + + return &PutDeviceNameRouteOK{} +} + +// WithPayload adds the payload to the put device name route o k response +func (o *PutDeviceNameRouteOK) WithPayload(payload string) *PutDeviceNameRouteOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name route o k response +func (o *PutDeviceNameRouteOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameRouteOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameRouteCreatedCode is the HTTP code returned for type PutDeviceNameRouteCreated +const PutDeviceNameRouteCreatedCode int = 201 + +/* +PutDeviceNameRouteCreated Add new route Success + +swagger:response putDeviceNameRouteCreated +*/ +type PutDeviceNameRouteCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameRouteCreated creates PutDeviceNameRouteCreated with default headers values +func NewPutDeviceNameRouteCreated() *PutDeviceNameRouteCreated { + + return &PutDeviceNameRouteCreated{} +} + +// WithPayload adds the payload to the put device name route created response +func (o *PutDeviceNameRouteCreated) WithPayload(payload string) *PutDeviceNameRouteCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name route created response +func (o *PutDeviceNameRouteCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameRouteCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameRouteInternalServerErrorCode is the HTTP code returned for type PutDeviceNameRouteInternalServerError +const PutDeviceNameRouteInternalServerErrorCode int = 500 + +/* +PutDeviceNameRouteInternalServerError Failed + +swagger:response putDeviceNameRouteInternalServerError +*/ +type PutDeviceNameRouteInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameRouteInternalServerError creates PutDeviceNameRouteInternalServerError with default headers values +func NewPutDeviceNameRouteInternalServerError() *PutDeviceNameRouteInternalServerError { + + return &PutDeviceNameRouteInternalServerError{} +} + +// WithPayload adds the payload to the put device name route internal server error response +func (o *PutDeviceNameRouteInternalServerError) WithPayload(payload string) *PutDeviceNameRouteInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name route internal server error response +func (o *PutDeviceNameRouteInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameRouteInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_route_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_urlbuilder.go new file mode 100644 index 000000000..3776a3036 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameRouteURL generates an URL for the put device name route operation +type PutDeviceNameRouteURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameRouteURL) WithBasePath(bp string) *PutDeviceNameRouteURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameRouteURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameRouteURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/route" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameRouteURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameRouteURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameRouteURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameRouteURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameRouteURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameRouteURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameRouteURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan.go new file mode 100644 index 000000000..dd519e482 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameVlanHandlerFunc turns a function with the right signature into a put device name vlan handler +type PutDeviceNameVlanHandlerFunc func(PutDeviceNameVlanParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameVlanHandlerFunc) Handle(params PutDeviceNameVlanParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameVlanHandler interface for that can handle valid put device name vlan params +type PutDeviceNameVlanHandler interface { + Handle(PutDeviceNameVlanParams) middleware.Responder +} + +// NewPutDeviceNameVlan creates a new http.Handler for the put device name vlan operation +func NewPutDeviceNameVlan(ctx *middleware.Context, handler PutDeviceNameVlanHandler) *PutDeviceNameVlan { + return &PutDeviceNameVlan{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameVlan swagger:route PUT /device/{name}/vlan device putDeviceNameVlan + +add/update special net device +*/ +type PutDeviceNameVlan struct { + Context *middleware.Context + Handler PutDeviceNameVlanHandler +} + +func (o *PutDeviceNameVlan) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameVlanParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_parameters.go new file mode 100644 index 000000000..63c5965c5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutDeviceNameVlanParams creates a new PutDeviceNameVlanParams object +// +// There are no default values defined in the spec. +func NewPutDeviceNameVlanParams() PutDeviceNameVlanParams { + + return PutDeviceNameVlanParams{} +} + +// PutDeviceNameVlanParams contains all the bound params for the put device name vlan operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameVlan +type PutDeviceNameVlanParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.VlanSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameVlanParams() beforehand. +func (o *PutDeviceNameVlanParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.VlanSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameVlanParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_responses.go new file mode 100644 index 000000000..241b8ef3d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameVlanOKCode is the HTTP code returned for type PutDeviceNameVlanOK +const PutDeviceNameVlanOKCode int = 200 + +/* +PutDeviceNameVlanOK Success + +swagger:response putDeviceNameVlanOK +*/ +type PutDeviceNameVlanOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameVlanOK creates PutDeviceNameVlanOK with default headers values +func NewPutDeviceNameVlanOK() *PutDeviceNameVlanOK { + + return &PutDeviceNameVlanOK{} +} + +// WithPayload adds the payload to the put device name vlan o k response +func (o *PutDeviceNameVlanOK) WithPayload(payload string) *PutDeviceNameVlanOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name vlan o k response +func (o *PutDeviceNameVlanOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameVlanOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameVlanInternalServerErrorCode is the HTTP code returned for type PutDeviceNameVlanInternalServerError +const PutDeviceNameVlanInternalServerErrorCode int = 500 + +/* +PutDeviceNameVlanInternalServerError Failed + +swagger:response putDeviceNameVlanInternalServerError +*/ +type PutDeviceNameVlanInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameVlanInternalServerError creates PutDeviceNameVlanInternalServerError with default headers values +func NewPutDeviceNameVlanInternalServerError() *PutDeviceNameVlanInternalServerError { + + return &PutDeviceNameVlanInternalServerError{} +} + +// WithPayload adds the payload to the put device name vlan internal server error response +func (o *PutDeviceNameVlanInternalServerError) WithPayload(payload string) *PutDeviceNameVlanInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name vlan internal server error response +func (o *PutDeviceNameVlanInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameVlanInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_urlbuilder.go new file mode 100644 index 000000000..2892d676c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameVlanURL generates an URL for the put device name vlan operation +type PutDeviceNameVlanURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameVlanURL) WithBasePath(bp string) *PutDeviceNameVlanURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameVlanURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameVlanURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/vlan" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameVlanURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameVlanURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameVlanURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameVlanURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameVlanURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameVlanURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameVlanURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/dpvs_agent_api.go b/tools/dpvs-agent/restapi/operations/dpvs_agent_api.go new file mode 100644 index 000000000..5421e4aa7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/dpvs_agent_api.go @@ -0,0 +1,736 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "net/http" + "strings" + + "github.com/go-openapi/errors" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/security" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + + "github.com/dpvs-agent/restapi/operations/device" + "github.com/dpvs-agent/restapi/operations/virtualserver" +) + +// NewDpvsAgentAPI creates a new DpvsAgent instance +func NewDpvsAgentAPI(spec *loads.Document) *DpvsAgentAPI { + return &DpvsAgentAPI{ + handlers: make(map[string]map[string]http.Handler), + formats: strfmt.Default, + defaultConsumes: "application/json", + defaultProduces: "application/json", + customConsumers: make(map[string]runtime.Consumer), + customProducers: make(map[string]runtime.Producer), + PreServerShutdown: func() {}, + ServerShutdown: func() {}, + spec: spec, + useSwaggerUI: false, + ServeError: errors.ServeError, + BasicAuthenticator: security.BasicAuth, + APIKeyAuthenticator: security.APIKeyAuth, + BearerAuthenticator: security.BearerAuth, + + JSONConsumer: runtime.JSONConsumer(), + + JSONProducer: runtime.JSONProducer(), + + DeviceDeleteDeviceNameAddrHandler: device.DeleteDeviceNameAddrHandlerFunc(func(params device.DeleteDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameAddr has not yet been implemented") + }), + DeviceDeleteDeviceNameNetlinkHandler: device.DeleteDeviceNameNetlinkHandlerFunc(func(params device.DeleteDeviceNameNetlinkParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameNetlink has not yet been implemented") + }), + DeviceDeleteDeviceNameNetlinkAddrHandler: device.DeleteDeviceNameNetlinkAddrHandlerFunc(func(params device.DeleteDeviceNameNetlinkAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameNetlinkAddr has not yet been implemented") + }), + DeviceDeleteDeviceNameRouteHandler: device.DeleteDeviceNameRouteHandlerFunc(func(params device.DeleteDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameRoute has not yet been implemented") + }), + DeviceDeleteDeviceNameVlanHandler: device.DeleteDeviceNameVlanHandlerFunc(func(params device.DeleteDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameVlan has not yet been implemented") + }), + VirtualserverDeleteVsVipPortHandler: virtualserver.DeleteVsVipPortHandlerFunc(func(params virtualserver.DeleteVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPort has not yet been implemented") + }), + VirtualserverDeleteVsVipPortAllowHandler: virtualserver.DeleteVsVipPortAllowHandlerFunc(func(params virtualserver.DeleteVsVipPortAllowParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortAllow has not yet been implemented") + }), + VirtualserverDeleteVsVipPortDenyHandler: virtualserver.DeleteVsVipPortDenyHandlerFunc(func(params virtualserver.DeleteVsVipPortDenyParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortDeny has not yet been implemented") + }), + VirtualserverDeleteVsVipPortLaddrHandler: virtualserver.DeleteVsVipPortLaddrHandlerFunc(func(params virtualserver.DeleteVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortLaddr has not yet been implemented") + }), + VirtualserverDeleteVsVipPortRsHandler: virtualserver.DeleteVsVipPortRsHandlerFunc(func(params virtualserver.DeleteVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortRs has not yet been implemented") + }), + DeviceGetDeviceHandler: device.GetDeviceHandlerFunc(func(params device.GetDeviceParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDevice has not yet been implemented") + }), + DeviceGetDeviceNameAddrHandler: device.GetDeviceNameAddrHandlerFunc(func(params device.GetDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameAddr has not yet been implemented") + }), + DeviceGetDeviceNameNetlinkHandler: device.GetDeviceNameNetlinkHandlerFunc(func(params device.GetDeviceNameNetlinkParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameNetlink has not yet been implemented") + }), + DeviceGetDeviceNameNetlinkAddrHandler: device.GetDeviceNameNetlinkAddrHandlerFunc(func(params device.GetDeviceNameNetlinkAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameNetlinkAddr has not yet been implemented") + }), + DeviceGetDeviceNameNicHandler: device.GetDeviceNameNicHandlerFunc(func(params device.GetDeviceNameNicParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameNic has not yet been implemented") + }), + DeviceGetDeviceNameRouteHandler: device.GetDeviceNameRouteHandlerFunc(func(params device.GetDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameRoute has not yet been implemented") + }), + DeviceGetDeviceNameVlanHandler: device.GetDeviceNameVlanHandlerFunc(func(params device.GetDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameVlan has not yet been implemented") + }), + VirtualserverGetVsHandler: virtualserver.GetVsHandlerFunc(func(params virtualserver.GetVsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVs has not yet been implemented") + }), + VirtualserverGetVsVipPortHandler: virtualserver.GetVsVipPortHandlerFunc(func(params virtualserver.GetVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPort has not yet been implemented") + }), + VirtualserverGetVsVipPortAllowHandler: virtualserver.GetVsVipPortAllowHandlerFunc(func(params virtualserver.GetVsVipPortAllowParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortAllow has not yet been implemented") + }), + VirtualserverGetVsVipPortDenyHandler: virtualserver.GetVsVipPortDenyHandlerFunc(func(params virtualserver.GetVsVipPortDenyParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortDeny has not yet been implemented") + }), + VirtualserverGetVsVipPortLaddrHandler: virtualserver.GetVsVipPortLaddrHandlerFunc(func(params virtualserver.GetVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortLaddr has not yet been implemented") + }), + VirtualserverGetVsVipPortRsHandler: virtualserver.GetVsVipPortRsHandlerFunc(func(params virtualserver.GetVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortRs has not yet been implemented") + }), + VirtualserverPostVsVipPortAllowHandler: virtualserver.PostVsVipPortAllowHandlerFunc(func(params virtualserver.PostVsVipPortAllowParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PostVsVipPortAllow has not yet been implemented") + }), + VirtualserverPostVsVipPortDenyHandler: virtualserver.PostVsVipPortDenyHandlerFunc(func(params virtualserver.PostVsVipPortDenyParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PostVsVipPortDeny has not yet been implemented") + }), + VirtualserverPostVsVipPortRsHandler: virtualserver.PostVsVipPortRsHandlerFunc(func(params virtualserver.PostVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PostVsVipPortRs has not yet been implemented") + }), + DevicePutDeviceNameAddrHandler: device.PutDeviceNameAddrHandlerFunc(func(params device.PutDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameAddr has not yet been implemented") + }), + DevicePutDeviceNameNetlinkHandler: device.PutDeviceNameNetlinkHandlerFunc(func(params device.PutDeviceNameNetlinkParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameNetlink has not yet been implemented") + }), + DevicePutDeviceNameNetlinkAddrHandler: device.PutDeviceNameNetlinkAddrHandlerFunc(func(params device.PutDeviceNameNetlinkAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameNetlinkAddr has not yet been implemented") + }), + DevicePutDeviceNameNicHandler: device.PutDeviceNameNicHandlerFunc(func(params device.PutDeviceNameNicParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameNic has not yet been implemented") + }), + DevicePutDeviceNameRouteHandler: device.PutDeviceNameRouteHandlerFunc(func(params device.PutDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameRoute has not yet been implemented") + }), + DevicePutDeviceNameVlanHandler: device.PutDeviceNameVlanHandlerFunc(func(params device.PutDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameVlan has not yet been implemented") + }), + VirtualserverPutVsVipPortHandler: virtualserver.PutVsVipPortHandlerFunc(func(params virtualserver.PutVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPort has not yet been implemented") + }), + VirtualserverPutVsVipPortAllowHandler: virtualserver.PutVsVipPortAllowHandlerFunc(func(params virtualserver.PutVsVipPortAllowParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortAllow has not yet been implemented") + }), + VirtualserverPutVsVipPortDenyHandler: virtualserver.PutVsVipPortDenyHandlerFunc(func(params virtualserver.PutVsVipPortDenyParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortDeny has not yet been implemented") + }), + VirtualserverPutVsVipPortLaddrHandler: virtualserver.PutVsVipPortLaddrHandlerFunc(func(params virtualserver.PutVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortLaddr has not yet been implemented") + }), + VirtualserverPutVsVipPortRsHandler: virtualserver.PutVsVipPortRsHandlerFunc(func(params virtualserver.PutVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortRs has not yet been implemented") + }), + } +} + +/*DpvsAgentAPI dpvs agent api */ +type DpvsAgentAPI struct { + spec *loads.Document + context *middleware.Context + handlers map[string]map[string]http.Handler + formats strfmt.Registry + customConsumers map[string]runtime.Consumer + customProducers map[string]runtime.Producer + defaultConsumes string + defaultProduces string + Middleware func(middleware.Builder) http.Handler + useSwaggerUI bool + + // BasicAuthenticator generates a runtime.Authenticator from the supplied basic auth function. + // It has a default implementation in the security package, however you can replace it for your particular usage. + BasicAuthenticator func(security.UserPassAuthentication) runtime.Authenticator + + // APIKeyAuthenticator generates a runtime.Authenticator from the supplied token auth function. + // It has a default implementation in the security package, however you can replace it for your particular usage. + APIKeyAuthenticator func(string, string, security.TokenAuthentication) runtime.Authenticator + + // BearerAuthenticator generates a runtime.Authenticator from the supplied bearer token auth function. + // It has a default implementation in the security package, however you can replace it for your particular usage. + BearerAuthenticator func(string, security.ScopedTokenAuthentication) runtime.Authenticator + + // JSONConsumer registers a consumer for the following mime types: + // - application/json + JSONConsumer runtime.Consumer + + // JSONProducer registers a producer for the following mime types: + // - application/json + JSONProducer runtime.Producer + + // DeviceDeleteDeviceNameAddrHandler sets the operation handler for the delete device name addr operation + DeviceDeleteDeviceNameAddrHandler device.DeleteDeviceNameAddrHandler + // DeviceDeleteDeviceNameNetlinkHandler sets the operation handler for the delete device name netlink operation + DeviceDeleteDeviceNameNetlinkHandler device.DeleteDeviceNameNetlinkHandler + // DeviceDeleteDeviceNameNetlinkAddrHandler sets the operation handler for the delete device name netlink addr operation + DeviceDeleteDeviceNameNetlinkAddrHandler device.DeleteDeviceNameNetlinkAddrHandler + // DeviceDeleteDeviceNameRouteHandler sets the operation handler for the delete device name route operation + DeviceDeleteDeviceNameRouteHandler device.DeleteDeviceNameRouteHandler + // DeviceDeleteDeviceNameVlanHandler sets the operation handler for the delete device name vlan operation + DeviceDeleteDeviceNameVlanHandler device.DeleteDeviceNameVlanHandler + // VirtualserverDeleteVsVipPortHandler sets the operation handler for the delete vs vip port operation + VirtualserverDeleteVsVipPortHandler virtualserver.DeleteVsVipPortHandler + // VirtualserverDeleteVsVipPortAllowHandler sets the operation handler for the delete vs vip port allow operation + VirtualserverDeleteVsVipPortAllowHandler virtualserver.DeleteVsVipPortAllowHandler + // VirtualserverDeleteVsVipPortDenyHandler sets the operation handler for the delete vs vip port deny operation + VirtualserverDeleteVsVipPortDenyHandler virtualserver.DeleteVsVipPortDenyHandler + // VirtualserverDeleteVsVipPortLaddrHandler sets the operation handler for the delete vs vip port laddr operation + VirtualserverDeleteVsVipPortLaddrHandler virtualserver.DeleteVsVipPortLaddrHandler + // VirtualserverDeleteVsVipPortRsHandler sets the operation handler for the delete vs vip port rs operation + VirtualserverDeleteVsVipPortRsHandler virtualserver.DeleteVsVipPortRsHandler + // DeviceGetDeviceHandler sets the operation handler for the get device operation + DeviceGetDeviceHandler device.GetDeviceHandler + // DeviceGetDeviceNameAddrHandler sets the operation handler for the get device name addr operation + DeviceGetDeviceNameAddrHandler device.GetDeviceNameAddrHandler + // DeviceGetDeviceNameNetlinkHandler sets the operation handler for the get device name netlink operation + DeviceGetDeviceNameNetlinkHandler device.GetDeviceNameNetlinkHandler + // DeviceGetDeviceNameNetlinkAddrHandler sets the operation handler for the get device name netlink addr operation + DeviceGetDeviceNameNetlinkAddrHandler device.GetDeviceNameNetlinkAddrHandler + // DeviceGetDeviceNameNicHandler sets the operation handler for the get device name nic operation + DeviceGetDeviceNameNicHandler device.GetDeviceNameNicHandler + // DeviceGetDeviceNameRouteHandler sets the operation handler for the get device name route operation + DeviceGetDeviceNameRouteHandler device.GetDeviceNameRouteHandler + // DeviceGetDeviceNameVlanHandler sets the operation handler for the get device name vlan operation + DeviceGetDeviceNameVlanHandler device.GetDeviceNameVlanHandler + // VirtualserverGetVsHandler sets the operation handler for the get vs operation + VirtualserverGetVsHandler virtualserver.GetVsHandler + // VirtualserverGetVsVipPortHandler sets the operation handler for the get vs vip port operation + VirtualserverGetVsVipPortHandler virtualserver.GetVsVipPortHandler + // VirtualserverGetVsVipPortAllowHandler sets the operation handler for the get vs vip port allow operation + VirtualserverGetVsVipPortAllowHandler virtualserver.GetVsVipPortAllowHandler + // VirtualserverGetVsVipPortDenyHandler sets the operation handler for the get vs vip port deny operation + VirtualserverGetVsVipPortDenyHandler virtualserver.GetVsVipPortDenyHandler + // VirtualserverGetVsVipPortLaddrHandler sets the operation handler for the get vs vip port laddr operation + VirtualserverGetVsVipPortLaddrHandler virtualserver.GetVsVipPortLaddrHandler + // VirtualserverGetVsVipPortRsHandler sets the operation handler for the get vs vip port rs operation + VirtualserverGetVsVipPortRsHandler virtualserver.GetVsVipPortRsHandler + // VirtualserverPostVsVipPortAllowHandler sets the operation handler for the post vs vip port allow operation + VirtualserverPostVsVipPortAllowHandler virtualserver.PostVsVipPortAllowHandler + // VirtualserverPostVsVipPortDenyHandler sets the operation handler for the post vs vip port deny operation + VirtualserverPostVsVipPortDenyHandler virtualserver.PostVsVipPortDenyHandler + // VirtualserverPostVsVipPortRsHandler sets the operation handler for the post vs vip port rs operation + VirtualserverPostVsVipPortRsHandler virtualserver.PostVsVipPortRsHandler + // DevicePutDeviceNameAddrHandler sets the operation handler for the put device name addr operation + DevicePutDeviceNameAddrHandler device.PutDeviceNameAddrHandler + // DevicePutDeviceNameNetlinkHandler sets the operation handler for the put device name netlink operation + DevicePutDeviceNameNetlinkHandler device.PutDeviceNameNetlinkHandler + // DevicePutDeviceNameNetlinkAddrHandler sets the operation handler for the put device name netlink addr operation + DevicePutDeviceNameNetlinkAddrHandler device.PutDeviceNameNetlinkAddrHandler + // DevicePutDeviceNameNicHandler sets the operation handler for the put device name nic operation + DevicePutDeviceNameNicHandler device.PutDeviceNameNicHandler + // DevicePutDeviceNameRouteHandler sets the operation handler for the put device name route operation + DevicePutDeviceNameRouteHandler device.PutDeviceNameRouteHandler + // DevicePutDeviceNameVlanHandler sets the operation handler for the put device name vlan operation + DevicePutDeviceNameVlanHandler device.PutDeviceNameVlanHandler + // VirtualserverPutVsVipPortHandler sets the operation handler for the put vs vip port operation + VirtualserverPutVsVipPortHandler virtualserver.PutVsVipPortHandler + // VirtualserverPutVsVipPortAllowHandler sets the operation handler for the put vs vip port allow operation + VirtualserverPutVsVipPortAllowHandler virtualserver.PutVsVipPortAllowHandler + // VirtualserverPutVsVipPortDenyHandler sets the operation handler for the put vs vip port deny operation + VirtualserverPutVsVipPortDenyHandler virtualserver.PutVsVipPortDenyHandler + // VirtualserverPutVsVipPortLaddrHandler sets the operation handler for the put vs vip port laddr operation + VirtualserverPutVsVipPortLaddrHandler virtualserver.PutVsVipPortLaddrHandler + // VirtualserverPutVsVipPortRsHandler sets the operation handler for the put vs vip port rs operation + VirtualserverPutVsVipPortRsHandler virtualserver.PutVsVipPortRsHandler + + // ServeError is called when an error is received, there is a default handler + // but you can set your own with this + ServeError func(http.ResponseWriter, *http.Request, error) + + // PreServerShutdown is called before the HTTP(S) server is shutdown + // This allows for custom functions to get executed before the HTTP(S) server stops accepting traffic + PreServerShutdown func() + + // ServerShutdown is called when the HTTP(S) server is shut down and done + // handling all active connections and does not accept connections any more + ServerShutdown func() + + // Custom command line argument groups with their descriptions + CommandLineOptionsGroups []swag.CommandLineOptionsGroup + + // User defined logger function. + Logger func(string, ...interface{}) +} + +// UseRedoc for documentation at /docs +func (o *DpvsAgentAPI) UseRedoc() { + o.useSwaggerUI = false +} + +// UseSwaggerUI for documentation at /docs +func (o *DpvsAgentAPI) UseSwaggerUI() { + o.useSwaggerUI = true +} + +// SetDefaultProduces sets the default produces media type +func (o *DpvsAgentAPI) SetDefaultProduces(mediaType string) { + o.defaultProduces = mediaType +} + +// SetDefaultConsumes returns the default consumes media type +func (o *DpvsAgentAPI) SetDefaultConsumes(mediaType string) { + o.defaultConsumes = mediaType +} + +// SetSpec sets a spec that will be served for the clients. +func (o *DpvsAgentAPI) SetSpec(spec *loads.Document) { + o.spec = spec +} + +// DefaultProduces returns the default produces media type +func (o *DpvsAgentAPI) DefaultProduces() string { + return o.defaultProduces +} + +// DefaultConsumes returns the default consumes media type +func (o *DpvsAgentAPI) DefaultConsumes() string { + return o.defaultConsumes +} + +// Formats returns the registered string formats +func (o *DpvsAgentAPI) Formats() strfmt.Registry { + return o.formats +} + +// RegisterFormat registers a custom format validator +func (o *DpvsAgentAPI) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) { + o.formats.Add(name, format, validator) +} + +// Validate validates the registrations in the DpvsAgentAPI +func (o *DpvsAgentAPI) Validate() error { + var unregistered []string + + if o.JSONConsumer == nil { + unregistered = append(unregistered, "JSONConsumer") + } + + if o.JSONProducer == nil { + unregistered = append(unregistered, "JSONProducer") + } + + if o.DeviceDeleteDeviceNameAddrHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameAddrHandler") + } + if o.DeviceDeleteDeviceNameNetlinkHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameNetlinkHandler") + } + if o.DeviceDeleteDeviceNameNetlinkAddrHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameNetlinkAddrHandler") + } + if o.DeviceDeleteDeviceNameRouteHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameRouteHandler") + } + if o.DeviceDeleteDeviceNameVlanHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameVlanHandler") + } + if o.VirtualserverDeleteVsVipPortHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortHandler") + } + if o.VirtualserverDeleteVsVipPortAllowHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortAllowHandler") + } + if o.VirtualserverDeleteVsVipPortDenyHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortDenyHandler") + } + if o.VirtualserverDeleteVsVipPortLaddrHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortLaddrHandler") + } + if o.VirtualserverDeleteVsVipPortRsHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortRsHandler") + } + if o.DeviceGetDeviceHandler == nil { + unregistered = append(unregistered, "device.GetDeviceHandler") + } + if o.DeviceGetDeviceNameAddrHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameAddrHandler") + } + if o.DeviceGetDeviceNameNetlinkHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameNetlinkHandler") + } + if o.DeviceGetDeviceNameNetlinkAddrHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameNetlinkAddrHandler") + } + if o.DeviceGetDeviceNameNicHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameNicHandler") + } + if o.DeviceGetDeviceNameRouteHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameRouteHandler") + } + if o.DeviceGetDeviceNameVlanHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameVlanHandler") + } + if o.VirtualserverGetVsHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsHandler") + } + if o.VirtualserverGetVsVipPortHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortHandler") + } + if o.VirtualserverGetVsVipPortAllowHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortAllowHandler") + } + if o.VirtualserverGetVsVipPortDenyHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortDenyHandler") + } + if o.VirtualserverGetVsVipPortLaddrHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortLaddrHandler") + } + if o.VirtualserverGetVsVipPortRsHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortRsHandler") + } + if o.VirtualserverPostVsVipPortAllowHandler == nil { + unregistered = append(unregistered, "virtualserver.PostVsVipPortAllowHandler") + } + if o.VirtualserverPostVsVipPortDenyHandler == nil { + unregistered = append(unregistered, "virtualserver.PostVsVipPortDenyHandler") + } + if o.VirtualserverPostVsVipPortRsHandler == nil { + unregistered = append(unregistered, "virtualserver.PostVsVipPortRsHandler") + } + if o.DevicePutDeviceNameAddrHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameAddrHandler") + } + if o.DevicePutDeviceNameNetlinkHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameNetlinkHandler") + } + if o.DevicePutDeviceNameNetlinkAddrHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameNetlinkAddrHandler") + } + if o.DevicePutDeviceNameNicHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameNicHandler") + } + if o.DevicePutDeviceNameRouteHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameRouteHandler") + } + if o.DevicePutDeviceNameVlanHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameVlanHandler") + } + if o.VirtualserverPutVsVipPortHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortHandler") + } + if o.VirtualserverPutVsVipPortAllowHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortAllowHandler") + } + if o.VirtualserverPutVsVipPortDenyHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortDenyHandler") + } + if o.VirtualserverPutVsVipPortLaddrHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortLaddrHandler") + } + if o.VirtualserverPutVsVipPortRsHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortRsHandler") + } + + if len(unregistered) > 0 { + return fmt.Errorf("missing registration: %s", strings.Join(unregistered, ", ")) + } + + return nil +} + +// ServeErrorFor gets a error handler for a given operation id +func (o *DpvsAgentAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) { + return o.ServeError +} + +// AuthenticatorsFor gets the authenticators for the specified security schemes +func (o *DpvsAgentAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator { + return nil +} + +// Authorizer returns the registered authorizer +func (o *DpvsAgentAPI) Authorizer() runtime.Authorizer { + return nil +} + +// ConsumersFor gets the consumers for the specified media types. +// MIME type parameters are ignored here. +func (o *DpvsAgentAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer { + result := make(map[string]runtime.Consumer, len(mediaTypes)) + for _, mt := range mediaTypes { + switch mt { + case "application/json": + result["application/json"] = o.JSONConsumer + } + + if c, ok := o.customConsumers[mt]; ok { + result[mt] = c + } + } + return result +} + +// ProducersFor gets the producers for the specified media types. +// MIME type parameters are ignored here. +func (o *DpvsAgentAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer { + result := make(map[string]runtime.Producer, len(mediaTypes)) + for _, mt := range mediaTypes { + switch mt { + case "application/json": + result["application/json"] = o.JSONProducer + } + + if p, ok := o.customProducers[mt]; ok { + result[mt] = p + } + } + return result +} + +// HandlerFor gets a http.Handler for the provided operation method and path +func (o *DpvsAgentAPI) HandlerFor(method, path string) (http.Handler, bool) { + if o.handlers == nil { + return nil, false + } + um := strings.ToUpper(method) + if _, ok := o.handlers[um]; !ok { + return nil, false + } + if path == "/" { + path = "" + } + h, ok := o.handlers[um][path] + return h, ok +} + +// Context returns the middleware context for the dpvs agent API +func (o *DpvsAgentAPI) Context() *middleware.Context { + if o.context == nil { + o.context = middleware.NewRoutableContext(o.spec, o, nil) + } + + return o.context +} + +func (o *DpvsAgentAPI) initHandlerCache() { + o.Context() // don't care about the result, just that the initialization happened + if o.handlers == nil { + o.handlers = make(map[string]map[string]http.Handler) + } + + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/addr"] = device.NewDeleteDeviceNameAddr(o.context, o.DeviceDeleteDeviceNameAddrHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/netlink"] = device.NewDeleteDeviceNameNetlink(o.context, o.DeviceDeleteDeviceNameNetlinkHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/netlink/addr"] = device.NewDeleteDeviceNameNetlinkAddr(o.context, o.DeviceDeleteDeviceNameNetlinkAddrHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/route"] = device.NewDeleteDeviceNameRoute(o.context, o.DeviceDeleteDeviceNameRouteHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/vlan"] = device.NewDeleteDeviceNameVlan(o.context, o.DeviceDeleteDeviceNameVlanHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}"] = virtualserver.NewDeleteVsVipPort(o.context, o.VirtualserverDeleteVsVipPortHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}/allow"] = virtualserver.NewDeleteVsVipPortAllow(o.context, o.VirtualserverDeleteVsVipPortAllowHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}/deny"] = virtualserver.NewDeleteVsVipPortDeny(o.context, o.VirtualserverDeleteVsVipPortDenyHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}/laddr"] = virtualserver.NewDeleteVsVipPortLaddr(o.context, o.VirtualserverDeleteVsVipPortLaddrHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}/rs"] = virtualserver.NewDeleteVsVipPortRs(o.context, o.VirtualserverDeleteVsVipPortRsHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device"] = device.NewGetDevice(o.context, o.DeviceGetDeviceHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/addr"] = device.NewGetDeviceNameAddr(o.context, o.DeviceGetDeviceNameAddrHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/netlink"] = device.NewGetDeviceNameNetlink(o.context, o.DeviceGetDeviceNameNetlinkHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/netlink/addr"] = device.NewGetDeviceNameNetlinkAddr(o.context, o.DeviceGetDeviceNameNetlinkAddrHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/nic"] = device.NewGetDeviceNameNic(o.context, o.DeviceGetDeviceNameNicHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/route"] = device.NewGetDeviceNameRoute(o.context, o.DeviceGetDeviceNameRouteHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/vlan"] = device.NewGetDeviceNameVlan(o.context, o.DeviceGetDeviceNameVlanHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs"] = virtualserver.NewGetVs(o.context, o.VirtualserverGetVsHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}"] = virtualserver.NewGetVsVipPort(o.context, o.VirtualserverGetVsVipPortHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}/allow"] = virtualserver.NewGetVsVipPortAllow(o.context, o.VirtualserverGetVsVipPortAllowHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}/deny"] = virtualserver.NewGetVsVipPortDeny(o.context, o.VirtualserverGetVsVipPortDenyHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}/laddr"] = virtualserver.NewGetVsVipPortLaddr(o.context, o.VirtualserverGetVsVipPortLaddrHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}/rs"] = virtualserver.NewGetVsVipPortRs(o.context, o.VirtualserverGetVsVipPortRsHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/vs/{VipPort}/allow"] = virtualserver.NewPostVsVipPortAllow(o.context, o.VirtualserverPostVsVipPortAllowHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/vs/{VipPort}/deny"] = virtualserver.NewPostVsVipPortDeny(o.context, o.VirtualserverPostVsVipPortDenyHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/vs/{VipPort}/rs"] = virtualserver.NewPostVsVipPortRs(o.context, o.VirtualserverPostVsVipPortRsHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/addr"] = device.NewPutDeviceNameAddr(o.context, o.DevicePutDeviceNameAddrHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/netlink"] = device.NewPutDeviceNameNetlink(o.context, o.DevicePutDeviceNameNetlinkHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/netlink/addr"] = device.NewPutDeviceNameNetlinkAddr(o.context, o.DevicePutDeviceNameNetlinkAddrHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/nic"] = device.NewPutDeviceNameNic(o.context, o.DevicePutDeviceNameNicHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/route"] = device.NewPutDeviceNameRoute(o.context, o.DevicePutDeviceNameRouteHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/vlan"] = device.NewPutDeviceNameVlan(o.context, o.DevicePutDeviceNameVlanHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}"] = virtualserver.NewPutVsVipPort(o.context, o.VirtualserverPutVsVipPortHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}/allow"] = virtualserver.NewPutVsVipPortAllow(o.context, o.VirtualserverPutVsVipPortAllowHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}/deny"] = virtualserver.NewPutVsVipPortDeny(o.context, o.VirtualserverPutVsVipPortDenyHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}/laddr"] = virtualserver.NewPutVsVipPortLaddr(o.context, o.VirtualserverPutVsVipPortLaddrHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}/rs"] = virtualserver.NewPutVsVipPortRs(o.context, o.VirtualserverPutVsVipPortRsHandler) +} + +// Serve creates a http handler to serve the API over HTTP +// can be used directly in http.ListenAndServe(":8000", api.Serve(nil)) +func (o *DpvsAgentAPI) Serve(builder middleware.Builder) http.Handler { + o.Init() + + if o.Middleware != nil { + return o.Middleware(builder) + } + if o.useSwaggerUI { + return o.context.APIHandlerSwaggerUI(builder) + } + return o.context.APIHandler(builder) +} + +// Init allows you to just initialize the handler cache, you can then recompose the middleware as you see fit +func (o *DpvsAgentAPI) Init() { + if len(o.handlers) == 0 { + o.initHandlerCache() + } +} + +// RegisterConsumer allows you to add (or override) a consumer for a media type. +func (o *DpvsAgentAPI) RegisterConsumer(mediaType string, consumer runtime.Consumer) { + o.customConsumers[mediaType] = consumer +} + +// RegisterProducer allows you to add (or override) a producer for a media type. +func (o *DpvsAgentAPI) RegisterProducer(mediaType string, producer runtime.Producer) { + o.customProducers[mediaType] = producer +} + +// AddMiddlewareFor adds a http middleware to existing handler +func (o *DpvsAgentAPI) AddMiddlewareFor(method, path string, builder middleware.Builder) { + um := strings.ToUpper(method) + if path == "/" { + path = "" + } + o.Init() + if h, ok := o.handlers[um][path]; ok { + o.handlers[method][path] = builder(h) + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port.go new file mode 100644 index 000000000..14d8bbebd --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortHandlerFunc turns a function with the right signature into a delete vs vip port handler +type DeleteVsVipPortHandlerFunc func(DeleteVsVipPortParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortHandlerFunc) Handle(params DeleteVsVipPortParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortHandler interface for that can handle valid delete vs vip port params +type DeleteVsVipPortHandler interface { + Handle(DeleteVsVipPortParams) middleware.Responder +} + +// NewDeleteVsVipPort creates a new http.Handler for the delete vs vip port operation +func NewDeleteVsVipPort(ctx *middleware.Context, handler DeleteVsVipPortHandler) *DeleteVsVipPort { + return &DeleteVsVipPort{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPort swagger:route DELETE /vs/{VipPort} virtualserver deleteVsVipPort + +Delete a vip:port:proto +*/ +type DeleteVsVipPort struct { + Context *middleware.Context + Handler DeleteVsVipPortHandler +} + +func (o *DeleteVsVipPort) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow.go new file mode 100644 index 000000000..1aee746da --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortAllowHandlerFunc turns a function with the right signature into a delete vs vip port allow handler +type DeleteVsVipPortAllowHandlerFunc func(DeleteVsVipPortAllowParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortAllowHandlerFunc) Handle(params DeleteVsVipPortAllowParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortAllowHandler interface for that can handle valid delete vs vip port allow params +type DeleteVsVipPortAllowHandler interface { + Handle(DeleteVsVipPortAllowParams) middleware.Responder +} + +// NewDeleteVsVipPortAllow creates a new http.Handler for the delete vs vip port allow operation +func NewDeleteVsVipPortAllow(ctx *middleware.Context, handler DeleteVsVipPortAllowHandler) *DeleteVsVipPortAllow { + return &DeleteVsVipPortAllow{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPortAllow swagger:route DELETE /vs/{VipPort}/allow virtualserver deleteVsVipPortAllow + +Delete a set of ip form white list to vip:port:proto +*/ +type DeleteVsVipPortAllow struct { + Context *middleware.Context + Handler DeleteVsVipPortAllowHandler +} + +func (o *DeleteVsVipPortAllow) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortAllowParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_parameters.go new file mode 100644 index 000000000..532017c51 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteVsVipPortAllowParams creates a new DeleteVsVipPortAllowParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortAllowParams() DeleteVsVipPortAllowParams { + + return DeleteVsVipPortAllowParams{} +} + +// DeleteVsVipPortAllowParams contains all the bound params for the delete vs vip port allow operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPortAllow +type DeleteVsVipPortAllowParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortAllowParams() beforehand. +func (o *DeleteVsVipPortAllowParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortAllowParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_responses.go new file mode 100644 index 000000000..03337c63d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_responses.go @@ -0,0 +1,211 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortAllowOKCode is the HTTP code returned for type DeleteVsVipPortAllowOK +const DeleteVsVipPortAllowOKCode int = 200 + +/* +DeleteVsVipPortAllowOK Success + +swagger:response deleteVsVipPortAllowOK +*/ +type DeleteVsVipPortAllowOK struct { +} + +// NewDeleteVsVipPortAllowOK creates DeleteVsVipPortAllowOK with default headers values +func NewDeleteVsVipPortAllowOK() *DeleteVsVipPortAllowOK { + + return &DeleteVsVipPortAllowOK{} +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +// DeleteVsVipPortAllowNotFoundCode is the HTTP code returned for type DeleteVsVipPortAllowNotFound +const DeleteVsVipPortAllowNotFoundCode int = 404 + +/* +DeleteVsVipPortAllowNotFound Service not found + +swagger:response deleteVsVipPortAllowNotFound +*/ +type DeleteVsVipPortAllowNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortAllowNotFound creates DeleteVsVipPortAllowNotFound with default headers values +func NewDeleteVsVipPortAllowNotFound() *DeleteVsVipPortAllowNotFound { + + return &DeleteVsVipPortAllowNotFound{} +} + +// WithPayload adds the payload to the delete vs vip port allow not found response +func (o *DeleteVsVipPortAllowNotFound) WithPayload(payload string) *DeleteVsVipPortAllowNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port allow not found response +func (o *DeleteVsVipPortAllowNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortAllowInvalidFrontendCode is the HTTP code returned for type DeleteVsVipPortAllowInvalidFrontend +const DeleteVsVipPortAllowInvalidFrontendCode int = 460 + +/* +DeleteVsVipPortAllowInvalidFrontend Invalid frontend in service configuration + +swagger:response deleteVsVipPortAllowInvalidFrontend +*/ +type DeleteVsVipPortAllowInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortAllowInvalidFrontend creates DeleteVsVipPortAllowInvalidFrontend with default headers values +func NewDeleteVsVipPortAllowInvalidFrontend() *DeleteVsVipPortAllowInvalidFrontend { + + return &DeleteVsVipPortAllowInvalidFrontend{} +} + +// WithPayload adds the payload to the delete vs vip port allow invalid frontend response +func (o *DeleteVsVipPortAllowInvalidFrontend) WithPayload(payload models.Error) *DeleteVsVipPortAllowInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port allow invalid frontend response +func (o *DeleteVsVipPortAllowInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortAllowInvalidBackendCode is the HTTP code returned for type DeleteVsVipPortAllowInvalidBackend +const DeleteVsVipPortAllowInvalidBackendCode int = 461 + +/* +DeleteVsVipPortAllowInvalidBackend Invalid backend in service configuration + +swagger:response deleteVsVipPortAllowInvalidBackend +*/ +type DeleteVsVipPortAllowInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortAllowInvalidBackend creates DeleteVsVipPortAllowInvalidBackend with default headers values +func NewDeleteVsVipPortAllowInvalidBackend() *DeleteVsVipPortAllowInvalidBackend { + + return &DeleteVsVipPortAllowInvalidBackend{} +} + +// WithPayload adds the payload to the delete vs vip port allow invalid backend response +func (o *DeleteVsVipPortAllowInvalidBackend) WithPayload(payload models.Error) *DeleteVsVipPortAllowInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port allow invalid backend response +func (o *DeleteVsVipPortAllowInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortAllowFailureCode is the HTTP code returned for type DeleteVsVipPortAllowFailure +const DeleteVsVipPortAllowFailureCode int = 500 + +/* +DeleteVsVipPortAllowFailure Service deletion failed + +swagger:response deleteVsVipPortAllowFailure +*/ +type DeleteVsVipPortAllowFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortAllowFailure creates DeleteVsVipPortAllowFailure with default headers values +func NewDeleteVsVipPortAllowFailure() *DeleteVsVipPortAllowFailure { + + return &DeleteVsVipPortAllowFailure{} +} + +// WithPayload adds the payload to the delete vs vip port allow failure response +func (o *DeleteVsVipPortAllowFailure) WithPayload(payload models.Error) *DeleteVsVipPortAllowFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port allow failure response +func (o *DeleteVsVipPortAllowFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_urlbuilder.go new file mode 100644 index 000000000..bb48d3228 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortAllowURL generates an URL for the delete vs vip port allow operation +type DeleteVsVipPortAllowURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortAllowURL) WithBasePath(bp string) *DeleteVsVipPortAllowURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortAllowURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortAllowURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/allow" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortAllowURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortAllowURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortAllowURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortAllowURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortAllowURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortAllowURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortAllowURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny.go new file mode 100644 index 000000000..93c81f5b4 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortDenyHandlerFunc turns a function with the right signature into a delete vs vip port deny handler +type DeleteVsVipPortDenyHandlerFunc func(DeleteVsVipPortDenyParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortDenyHandlerFunc) Handle(params DeleteVsVipPortDenyParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortDenyHandler interface for that can handle valid delete vs vip port deny params +type DeleteVsVipPortDenyHandler interface { + Handle(DeleteVsVipPortDenyParams) middleware.Responder +} + +// NewDeleteVsVipPortDeny creates a new http.Handler for the delete vs vip port deny operation +func NewDeleteVsVipPortDeny(ctx *middleware.Context, handler DeleteVsVipPortDenyHandler) *DeleteVsVipPortDeny { + return &DeleteVsVipPortDeny{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPortDeny swagger:route DELETE /vs/{VipPort}/deny virtualserver deleteVsVipPortDeny + +Delete a set of ip form black list to vip:port:proto +*/ +type DeleteVsVipPortDeny struct { + Context *middleware.Context + Handler DeleteVsVipPortDenyHandler +} + +func (o *DeleteVsVipPortDeny) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortDenyParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_parameters.go new file mode 100644 index 000000000..b01bc07e9 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteVsVipPortDenyParams creates a new DeleteVsVipPortDenyParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortDenyParams() DeleteVsVipPortDenyParams { + + return DeleteVsVipPortDenyParams{} +} + +// DeleteVsVipPortDenyParams contains all the bound params for the delete vs vip port deny operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPortDeny +type DeleteVsVipPortDenyParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortDenyParams() beforehand. +func (o *DeleteVsVipPortDenyParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortDenyParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_responses.go new file mode 100644 index 000000000..05c87233f --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_responses.go @@ -0,0 +1,211 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortDenyOKCode is the HTTP code returned for type DeleteVsVipPortDenyOK +const DeleteVsVipPortDenyOKCode int = 200 + +/* +DeleteVsVipPortDenyOK Success + +swagger:response deleteVsVipPortDenyOK +*/ +type DeleteVsVipPortDenyOK struct { +} + +// NewDeleteVsVipPortDenyOK creates DeleteVsVipPortDenyOK with default headers values +func NewDeleteVsVipPortDenyOK() *DeleteVsVipPortDenyOK { + + return &DeleteVsVipPortDenyOK{} +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +// DeleteVsVipPortDenyNotFoundCode is the HTTP code returned for type DeleteVsVipPortDenyNotFound +const DeleteVsVipPortDenyNotFoundCode int = 404 + +/* +DeleteVsVipPortDenyNotFound Service not found + +swagger:response deleteVsVipPortDenyNotFound +*/ +type DeleteVsVipPortDenyNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortDenyNotFound creates DeleteVsVipPortDenyNotFound with default headers values +func NewDeleteVsVipPortDenyNotFound() *DeleteVsVipPortDenyNotFound { + + return &DeleteVsVipPortDenyNotFound{} +} + +// WithPayload adds the payload to the delete vs vip port deny not found response +func (o *DeleteVsVipPortDenyNotFound) WithPayload(payload string) *DeleteVsVipPortDenyNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port deny not found response +func (o *DeleteVsVipPortDenyNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortDenyInvalidFrontendCode is the HTTP code returned for type DeleteVsVipPortDenyInvalidFrontend +const DeleteVsVipPortDenyInvalidFrontendCode int = 460 + +/* +DeleteVsVipPortDenyInvalidFrontend Invalid frontend in service configuration + +swagger:response deleteVsVipPortDenyInvalidFrontend +*/ +type DeleteVsVipPortDenyInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortDenyInvalidFrontend creates DeleteVsVipPortDenyInvalidFrontend with default headers values +func NewDeleteVsVipPortDenyInvalidFrontend() *DeleteVsVipPortDenyInvalidFrontend { + + return &DeleteVsVipPortDenyInvalidFrontend{} +} + +// WithPayload adds the payload to the delete vs vip port deny invalid frontend response +func (o *DeleteVsVipPortDenyInvalidFrontend) WithPayload(payload models.Error) *DeleteVsVipPortDenyInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port deny invalid frontend response +func (o *DeleteVsVipPortDenyInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortDenyInvalidBackendCode is the HTTP code returned for type DeleteVsVipPortDenyInvalidBackend +const DeleteVsVipPortDenyInvalidBackendCode int = 461 + +/* +DeleteVsVipPortDenyInvalidBackend Invalid backend in service configuration + +swagger:response deleteVsVipPortDenyInvalidBackend +*/ +type DeleteVsVipPortDenyInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortDenyInvalidBackend creates DeleteVsVipPortDenyInvalidBackend with default headers values +func NewDeleteVsVipPortDenyInvalidBackend() *DeleteVsVipPortDenyInvalidBackend { + + return &DeleteVsVipPortDenyInvalidBackend{} +} + +// WithPayload adds the payload to the delete vs vip port deny invalid backend response +func (o *DeleteVsVipPortDenyInvalidBackend) WithPayload(payload models.Error) *DeleteVsVipPortDenyInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port deny invalid backend response +func (o *DeleteVsVipPortDenyInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortDenyFailureCode is the HTTP code returned for type DeleteVsVipPortDenyFailure +const DeleteVsVipPortDenyFailureCode int = 500 + +/* +DeleteVsVipPortDenyFailure Service deletion failed + +swagger:response deleteVsVipPortDenyFailure +*/ +type DeleteVsVipPortDenyFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortDenyFailure creates DeleteVsVipPortDenyFailure with default headers values +func NewDeleteVsVipPortDenyFailure() *DeleteVsVipPortDenyFailure { + + return &DeleteVsVipPortDenyFailure{} +} + +// WithPayload adds the payload to the delete vs vip port deny failure response +func (o *DeleteVsVipPortDenyFailure) WithPayload(payload models.Error) *DeleteVsVipPortDenyFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port deny failure response +func (o *DeleteVsVipPortDenyFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_urlbuilder.go new file mode 100644 index 000000000..3254ab8a7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortDenyURL generates an URL for the delete vs vip port deny operation +type DeleteVsVipPortDenyURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortDenyURL) WithBasePath(bp string) *DeleteVsVipPortDenyURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortDenyURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortDenyURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/deny" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortDenyURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortDenyURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortDenyURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortDenyURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortDenyURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortDenyURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortDenyURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr.go new file mode 100644 index 000000000..d29b0e7c4 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortLaddrHandlerFunc turns a function with the right signature into a delete vs vip port laddr handler +type DeleteVsVipPortLaddrHandlerFunc func(DeleteVsVipPortLaddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortLaddrHandlerFunc) Handle(params DeleteVsVipPortLaddrParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortLaddrHandler interface for that can handle valid delete vs vip port laddr params +type DeleteVsVipPortLaddrHandler interface { + Handle(DeleteVsVipPortLaddrParams) middleware.Responder +} + +// NewDeleteVsVipPortLaddr creates a new http.Handler for the delete vs vip port laddr operation +func NewDeleteVsVipPortLaddr(ctx *middleware.Context, handler DeleteVsVipPortLaddrHandler) *DeleteVsVipPortLaddr { + return &DeleteVsVipPortLaddr{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPortLaddr swagger:route DELETE /vs/{VipPort}/laddr virtualserver deleteVsVipPortLaddr + +DeleteVsVipPortLaddr delete vs vip port laddr API +*/ +type DeleteVsVipPortLaddr struct { + Context *middleware.Context + Handler DeleteVsVipPortLaddrHandler +} + +func (o *DeleteVsVipPortLaddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortLaddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_parameters.go new file mode 100644 index 000000000..33498eedc --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteVsVipPortLaddrParams creates a new DeleteVsVipPortLaddrParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortLaddrParams() DeleteVsVipPortLaddrParams { + + return DeleteVsVipPortLaddrParams{} +} + +// DeleteVsVipPortLaddrParams contains all the bound params for the delete vs vip port laddr operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPortLaddr +type DeleteVsVipPortLaddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Spec *models.LocalAddressSpecTiny +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortLaddrParams() beforehand. +func (o *DeleteVsVipPortLaddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.LocalAddressSpecTiny + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortLaddrParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_responses.go new file mode 100644 index 000000000..7b474dc5a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_responses.go @@ -0,0 +1,186 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortLaddrOKCode is the HTTP code returned for type DeleteVsVipPortLaddrOK +const DeleteVsVipPortLaddrOKCode int = 200 + +/* +DeleteVsVipPortLaddrOK Success + +swagger:response deleteVsVipPortLaddrOK +*/ +type DeleteVsVipPortLaddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortLaddrOK creates DeleteVsVipPortLaddrOK with default headers values +func NewDeleteVsVipPortLaddrOK() *DeleteVsVipPortLaddrOK { + + return &DeleteVsVipPortLaddrOK{} +} + +// WithPayload adds the payload to the delete vs vip port laddr o k response +func (o *DeleteVsVipPortLaddrOK) WithPayload(payload string) *DeleteVsVipPortLaddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port laddr o k response +func (o *DeleteVsVipPortLaddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortLaddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortLaddrInvalidFrontendCode is the HTTP code returned for type DeleteVsVipPortLaddrInvalidFrontend +const DeleteVsVipPortLaddrInvalidFrontendCode int = 460 + +/* +DeleteVsVipPortLaddrInvalidFrontend Invalid frontend in service configuration + +swagger:response deleteVsVipPortLaddrInvalidFrontend +*/ +type DeleteVsVipPortLaddrInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortLaddrInvalidFrontend creates DeleteVsVipPortLaddrInvalidFrontend with default headers values +func NewDeleteVsVipPortLaddrInvalidFrontend() *DeleteVsVipPortLaddrInvalidFrontend { + + return &DeleteVsVipPortLaddrInvalidFrontend{} +} + +// WithPayload adds the payload to the delete vs vip port laddr invalid frontend response +func (o *DeleteVsVipPortLaddrInvalidFrontend) WithPayload(payload models.Error) *DeleteVsVipPortLaddrInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port laddr invalid frontend response +func (o *DeleteVsVipPortLaddrInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortLaddrInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortLaddrInvalidBackendCode is the HTTP code returned for type DeleteVsVipPortLaddrInvalidBackend +const DeleteVsVipPortLaddrInvalidBackendCode int = 461 + +/* +DeleteVsVipPortLaddrInvalidBackend Invalid backend in service configuration + +swagger:response deleteVsVipPortLaddrInvalidBackend +*/ +type DeleteVsVipPortLaddrInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortLaddrInvalidBackend creates DeleteVsVipPortLaddrInvalidBackend with default headers values +func NewDeleteVsVipPortLaddrInvalidBackend() *DeleteVsVipPortLaddrInvalidBackend { + + return &DeleteVsVipPortLaddrInvalidBackend{} +} + +// WithPayload adds the payload to the delete vs vip port laddr invalid backend response +func (o *DeleteVsVipPortLaddrInvalidBackend) WithPayload(payload models.Error) *DeleteVsVipPortLaddrInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port laddr invalid backend response +func (o *DeleteVsVipPortLaddrInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortLaddrInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortLaddrFailureCode is the HTTP code returned for type DeleteVsVipPortLaddrFailure +const DeleteVsVipPortLaddrFailureCode int = 500 + +/* +DeleteVsVipPortLaddrFailure Error while creating virtual server + +swagger:response deleteVsVipPortLaddrFailure +*/ +type DeleteVsVipPortLaddrFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortLaddrFailure creates DeleteVsVipPortLaddrFailure with default headers values +func NewDeleteVsVipPortLaddrFailure() *DeleteVsVipPortLaddrFailure { + + return &DeleteVsVipPortLaddrFailure{} +} + +// WithPayload adds the payload to the delete vs vip port laddr failure response +func (o *DeleteVsVipPortLaddrFailure) WithPayload(payload models.Error) *DeleteVsVipPortLaddrFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port laddr failure response +func (o *DeleteVsVipPortLaddrFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortLaddrFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_urlbuilder.go new file mode 100644 index 000000000..4926a3d0c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortLaddrURL generates an URL for the delete vs vip port laddr operation +type DeleteVsVipPortLaddrURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortLaddrURL) WithBasePath(bp string) *DeleteVsVipPortLaddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortLaddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortLaddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/laddr" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortLaddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortLaddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortLaddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortLaddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortLaddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortLaddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortLaddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_parameters.go new file mode 100644 index 000000000..d8e528348 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewDeleteVsVipPortParams creates a new DeleteVsVipPortParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortParams() DeleteVsVipPortParams { + + return DeleteVsVipPortParams{} +} + +// DeleteVsVipPortParams contains all the bound params for the delete vs vip port operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPort +type DeleteVsVipPortParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortParams() beforehand. +func (o *DeleteVsVipPortParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_responses.go new file mode 100644 index 000000000..f423fd023 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_responses.go @@ -0,0 +1,143 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortOKCode is the HTTP code returned for type DeleteVsVipPortOK +const DeleteVsVipPortOKCode int = 200 + +/* +DeleteVsVipPortOK Success + +swagger:response deleteVsVipPortOK +*/ +type DeleteVsVipPortOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortOK creates DeleteVsVipPortOK with default headers values +func NewDeleteVsVipPortOK() *DeleteVsVipPortOK { + + return &DeleteVsVipPortOK{} +} + +// WithPayload adds the payload to the delete vs vip port o k response +func (o *DeleteVsVipPortOK) WithPayload(payload string) *DeleteVsVipPortOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port o k response +func (o *DeleteVsVipPortOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortNotFoundCode is the HTTP code returned for type DeleteVsVipPortNotFound +const DeleteVsVipPortNotFoundCode int = 404 + +/* +DeleteVsVipPortNotFound Service not found + +swagger:response deleteVsVipPortNotFound +*/ +type DeleteVsVipPortNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortNotFound creates DeleteVsVipPortNotFound with default headers values +func NewDeleteVsVipPortNotFound() *DeleteVsVipPortNotFound { + + return &DeleteVsVipPortNotFound{} +} + +// WithPayload adds the payload to the delete vs vip port not found response +func (o *DeleteVsVipPortNotFound) WithPayload(payload string) *DeleteVsVipPortNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port not found response +func (o *DeleteVsVipPortNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortFailureCode is the HTTP code returned for type DeleteVsVipPortFailure +const DeleteVsVipPortFailureCode int = 500 + +/* +DeleteVsVipPortFailure Service deletion failed + +swagger:response deleteVsVipPortFailure +*/ +type DeleteVsVipPortFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortFailure creates DeleteVsVipPortFailure with default headers values +func NewDeleteVsVipPortFailure() *DeleteVsVipPortFailure { + + return &DeleteVsVipPortFailure{} +} + +// WithPayload adds the payload to the delete vs vip port failure response +func (o *DeleteVsVipPortFailure) WithPayload(payload models.Error) *DeleteVsVipPortFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port failure response +func (o *DeleteVsVipPortFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs.go new file mode 100644 index 000000000..1598ebfbf --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortRsHandlerFunc turns a function with the right signature into a delete vs vip port rs handler +type DeleteVsVipPortRsHandlerFunc func(DeleteVsVipPortRsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortRsHandlerFunc) Handle(params DeleteVsVipPortRsParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortRsHandler interface for that can handle valid delete vs vip port rs params +type DeleteVsVipPortRsHandler interface { + Handle(DeleteVsVipPortRsParams) middleware.Responder +} + +// NewDeleteVsVipPortRs creates a new http.Handler for the delete vs vip port rs operation +func NewDeleteVsVipPortRs(ctx *middleware.Context, handler DeleteVsVipPortRsHandler) *DeleteVsVipPortRs { + return &DeleteVsVipPortRs{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPortRs swagger:route DELETE /vs/{VipPort}/rs virtualserver deleteVsVipPortRs + +Delete a set of real server from vip:port:proto +*/ +type DeleteVsVipPortRs struct { + Context *middleware.Context + Handler DeleteVsVipPortRsHandler +} + +func (o *DeleteVsVipPortRs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortRsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_parameters.go new file mode 100644 index 000000000..f643ff30e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteVsVipPortRsParams creates a new DeleteVsVipPortRsParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortRsParams() DeleteVsVipPortRsParams { + + return DeleteVsVipPortRsParams{} +} + +// DeleteVsVipPortRsParams contains all the bound params for the delete vs vip port rs operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPortRs +type DeleteVsVipPortRsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Rss *models.RealServerTinyList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortRsParams() beforehand. +func (o *DeleteVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RealServerTinyList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("rss", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Rss = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_responses.go new file mode 100644 index 000000000..e51843937 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_responses.go @@ -0,0 +1,211 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortRsOKCode is the HTTP code returned for type DeleteVsVipPortRsOK +const DeleteVsVipPortRsOKCode int = 200 + +/* +DeleteVsVipPortRsOK Success + +swagger:response deleteVsVipPortRsOK +*/ +type DeleteVsVipPortRsOK struct { +} + +// NewDeleteVsVipPortRsOK creates DeleteVsVipPortRsOK with default headers values +func NewDeleteVsVipPortRsOK() *DeleteVsVipPortRsOK { + + return &DeleteVsVipPortRsOK{} +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +// DeleteVsVipPortRsNotFoundCode is the HTTP code returned for type DeleteVsVipPortRsNotFound +const DeleteVsVipPortRsNotFoundCode int = 404 + +/* +DeleteVsVipPortRsNotFound Service not found + +swagger:response deleteVsVipPortRsNotFound +*/ +type DeleteVsVipPortRsNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortRsNotFound creates DeleteVsVipPortRsNotFound with default headers values +func NewDeleteVsVipPortRsNotFound() *DeleteVsVipPortRsNotFound { + + return &DeleteVsVipPortRsNotFound{} +} + +// WithPayload adds the payload to the delete vs vip port rs not found response +func (o *DeleteVsVipPortRsNotFound) WithPayload(payload string) *DeleteVsVipPortRsNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port rs not found response +func (o *DeleteVsVipPortRsNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortRsInvalidFrontendCode is the HTTP code returned for type DeleteVsVipPortRsInvalidFrontend +const DeleteVsVipPortRsInvalidFrontendCode int = 460 + +/* +DeleteVsVipPortRsInvalidFrontend Invalid frontend in service configuration + +swagger:response deleteVsVipPortRsInvalidFrontend +*/ +type DeleteVsVipPortRsInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortRsInvalidFrontend creates DeleteVsVipPortRsInvalidFrontend with default headers values +func NewDeleteVsVipPortRsInvalidFrontend() *DeleteVsVipPortRsInvalidFrontend { + + return &DeleteVsVipPortRsInvalidFrontend{} +} + +// WithPayload adds the payload to the delete vs vip port rs invalid frontend response +func (o *DeleteVsVipPortRsInvalidFrontend) WithPayload(payload models.Error) *DeleteVsVipPortRsInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port rs invalid frontend response +func (o *DeleteVsVipPortRsInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortRsInvalidBackendCode is the HTTP code returned for type DeleteVsVipPortRsInvalidBackend +const DeleteVsVipPortRsInvalidBackendCode int = 461 + +/* +DeleteVsVipPortRsInvalidBackend Invalid backend in service configuration + +swagger:response deleteVsVipPortRsInvalidBackend +*/ +type DeleteVsVipPortRsInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortRsInvalidBackend creates DeleteVsVipPortRsInvalidBackend with default headers values +func NewDeleteVsVipPortRsInvalidBackend() *DeleteVsVipPortRsInvalidBackend { + + return &DeleteVsVipPortRsInvalidBackend{} +} + +// WithPayload adds the payload to the delete vs vip port rs invalid backend response +func (o *DeleteVsVipPortRsInvalidBackend) WithPayload(payload models.Error) *DeleteVsVipPortRsInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port rs invalid backend response +func (o *DeleteVsVipPortRsInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortRsFailureCode is the HTTP code returned for type DeleteVsVipPortRsFailure +const DeleteVsVipPortRsFailureCode int = 500 + +/* +DeleteVsVipPortRsFailure Service deletion failed + +swagger:response deleteVsVipPortRsFailure +*/ +type DeleteVsVipPortRsFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortRsFailure creates DeleteVsVipPortRsFailure with default headers values +func NewDeleteVsVipPortRsFailure() *DeleteVsVipPortRsFailure { + + return &DeleteVsVipPortRsFailure{} +} + +// WithPayload adds the payload to the delete vs vip port rs failure response +func (o *DeleteVsVipPortRsFailure) WithPayload(payload models.Error) *DeleteVsVipPortRsFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port rs failure response +func (o *DeleteVsVipPortRsFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_urlbuilder.go new file mode 100644 index 000000000..074cd0068 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortRsURL generates an URL for the delete vs vip port rs operation +type DeleteVsVipPortRsURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortRsURL) WithBasePath(bp string) *DeleteVsVipPortRsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortRsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortRsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/rs" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortRsURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortRsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortRsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortRsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortRsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortRsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortRsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_urlbuilder.go new file mode 100644 index 000000000..44d932d71 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortURL generates an URL for the delete vs vip port operation +type DeleteVsVipPortURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortURL) WithBasePath(bp string) *DeleteVsVipPortURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs.go new file mode 100644 index 000000000..1e82546f7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsHandlerFunc turns a function with the right signature into a get vs handler +type GetVsHandlerFunc func(GetVsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsHandlerFunc) Handle(params GetVsParams) middleware.Responder { + return fn(params) +} + +// GetVsHandler interface for that can handle valid get vs params +type GetVsHandler interface { + Handle(GetVsParams) middleware.Responder +} + +// NewGetVs creates a new http.Handler for the get vs operation +func NewGetVs(ctx *middleware.Context, handler GetVsHandler) *GetVs { + return &GetVs{Context: ctx, Handler: handler} +} + +/* + GetVs swagger:route GET /vs virtualserver getVs + +display all vip:port:proto and rsip:port list +*/ +type GetVs struct { + Context *middleware.Context + Handler GetVsHandler +} + +func (o *GetVs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_parameters.go new file mode 100644 index 000000000..ac28ba465 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_parameters.go @@ -0,0 +1,92 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetVsParams creates a new GetVsParams object +// with the default values initialized. +func NewGetVsParams() GetVsParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetVsParams{ + Stats: &statsDefault, + } +} + +// GetVsParams contains all the bound params for the get vs operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVs +type GetVsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsParams() beforehand. +func (o *GetVsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetVsParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetVsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_responses.go new file mode 100644 index 000000000..c67eec7a7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_responses.go @@ -0,0 +1,59 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// GetVsOKCode is the HTTP code returned for type GetVsOK +const GetVsOKCode int = 200 + +/* +GetVsOK Success + +swagger:response getVsOK +*/ +type GetVsOK struct { + + /* + In: Body + */ + Payload *models.VirtualServerList `json:"body,omitempty"` +} + +// NewGetVsOK creates GetVsOK with default headers values +func NewGetVsOK() *GetVsOK { + + return &GetVsOK{} +} + +// WithPayload adds the payload to the get vs o k response +func (o *GetVsOK) WithPayload(payload *models.VirtualServerList) *GetVsOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs o k response +func (o *GetVsOK) SetPayload(payload *models.VirtualServerList) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_urlbuilder.go new file mode 100644 index 000000000..917308dcf --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_urlbuilder.go @@ -0,0 +1,105 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + + "github.com/go-openapi/swag" +) + +// GetVsURL generates an URL for the get vs operation +type GetVsURL struct { + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsURL) WithBasePath(bp string) *GetVsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port.go new file mode 100644 index 000000000..f7e02c0d4 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortHandlerFunc turns a function with the right signature into a get vs vip port handler +type GetVsVipPortHandlerFunc func(GetVsVipPortParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortHandlerFunc) Handle(params GetVsVipPortParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortHandler interface for that can handle valid get vs vip port params +type GetVsVipPortHandler interface { + Handle(GetVsVipPortParams) middleware.Responder +} + +// NewGetVsVipPort creates a new http.Handler for the get vs vip port operation +func NewGetVsVipPort(ctx *middleware.Context, handler GetVsVipPortHandler) *GetVsVipPort { + return &GetVsVipPort{Context: ctx, Handler: handler} +} + +/* + GetVsVipPort swagger:route GET /vs/{VipPort} virtualserver getVsVipPort + +get a specific virtual server +*/ +type GetVsVipPort struct { + Context *middleware.Context + Handler GetVsVipPortHandler +} + +func (o *GetVsVipPort) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow.go new file mode 100644 index 000000000..267a01e25 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortAllowHandlerFunc turns a function with the right signature into a get vs vip port allow handler +type GetVsVipPortAllowHandlerFunc func(GetVsVipPortAllowParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortAllowHandlerFunc) Handle(params GetVsVipPortAllowParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortAllowHandler interface for that can handle valid get vs vip port allow params +type GetVsVipPortAllowHandler interface { + Handle(GetVsVipPortAllowParams) middleware.Responder +} + +// NewGetVsVipPortAllow creates a new http.Handler for the get vs vip port allow operation +func NewGetVsVipPortAllow(ctx *middleware.Context, handler GetVsVipPortAllowHandler) *GetVsVipPortAllow { + return &GetVsVipPortAllow{Context: ctx, Handler: handler} +} + +/* + GetVsVipPortAllow swagger:route GET /vs/{VipPort}/allow virtualserver getVsVipPortAllow + +GetVsVipPortAllow get vs vip port allow API +*/ +type GetVsVipPortAllow struct { + Context *middleware.Context + Handler GetVsVipPortAllowHandler +} + +func (o *GetVsVipPortAllow) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortAllowParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_parameters.go new file mode 100644 index 000000000..df1e98ae2 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewGetVsVipPortAllowParams creates a new GetVsVipPortAllowParams object +// +// There are no default values defined in the spec. +func NewGetVsVipPortAllowParams() GetVsVipPortAllowParams { + + return GetVsVipPortAllowParams{} +} + +// GetVsVipPortAllowParams contains all the bound params for the get vs vip port allow operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPortAllow +type GetVsVipPortAllowParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortAllowParams() beforehand. +func (o *GetVsVipPortAllowParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortAllowParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_responses.go new file mode 100644 index 000000000..21f2eb892 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetVsVipPortAllowOKCode is the HTTP code returned for type GetVsVipPortAllowOK +const GetVsVipPortAllowOKCode int = 200 + +/* +GetVsVipPortAllowOK Success + +swagger:response getVsVipPortAllowOK +*/ +type GetVsVipPortAllowOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortAllowOK creates GetVsVipPortAllowOK with default headers values +func NewGetVsVipPortAllowOK() *GetVsVipPortAllowOK { + + return &GetVsVipPortAllowOK{} +} + +// WithPayload adds the payload to the get vs vip port allow o k response +func (o *GetVsVipPortAllowOK) WithPayload(payload string) *GetVsVipPortAllowOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port allow o k response +func (o *GetVsVipPortAllowOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortAllowOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetVsVipPortAllowNotFoundCode is the HTTP code returned for type GetVsVipPortAllowNotFound +const GetVsVipPortAllowNotFoundCode int = 404 + +/* +GetVsVipPortAllowNotFound Service not found + +swagger:response getVsVipPortAllowNotFound +*/ +type GetVsVipPortAllowNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortAllowNotFound creates GetVsVipPortAllowNotFound with default headers values +func NewGetVsVipPortAllowNotFound() *GetVsVipPortAllowNotFound { + + return &GetVsVipPortAllowNotFound{} +} + +// WithPayload adds the payload to the get vs vip port allow not found response +func (o *GetVsVipPortAllowNotFound) WithPayload(payload string) *GetVsVipPortAllowNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port allow not found response +func (o *GetVsVipPortAllowNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortAllowNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_urlbuilder.go new file mode 100644 index 000000000..9f00c3d27 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// GetVsVipPortAllowURL generates an URL for the get vs vip port allow operation +type GetVsVipPortAllowURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortAllowURL) WithBasePath(bp string) *GetVsVipPortAllowURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortAllowURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortAllowURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/allow" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortAllowURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortAllowURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortAllowURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortAllowURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortAllowURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortAllowURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortAllowURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny.go new file mode 100644 index 000000000..92631c107 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortDenyHandlerFunc turns a function with the right signature into a get vs vip port deny handler +type GetVsVipPortDenyHandlerFunc func(GetVsVipPortDenyParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortDenyHandlerFunc) Handle(params GetVsVipPortDenyParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortDenyHandler interface for that can handle valid get vs vip port deny params +type GetVsVipPortDenyHandler interface { + Handle(GetVsVipPortDenyParams) middleware.Responder +} + +// NewGetVsVipPortDeny creates a new http.Handler for the get vs vip port deny operation +func NewGetVsVipPortDeny(ctx *middleware.Context, handler GetVsVipPortDenyHandler) *GetVsVipPortDeny { + return &GetVsVipPortDeny{Context: ctx, Handler: handler} +} + +/* + GetVsVipPortDeny swagger:route GET /vs/{VipPort}/deny virtualserver getVsVipPortDeny + +GetVsVipPortDeny get vs vip port deny API +*/ +type GetVsVipPortDeny struct { + Context *middleware.Context + Handler GetVsVipPortDenyHandler +} + +func (o *GetVsVipPortDeny) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortDenyParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_parameters.go new file mode 100644 index 000000000..3e8046c1e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewGetVsVipPortDenyParams creates a new GetVsVipPortDenyParams object +// +// There are no default values defined in the spec. +func NewGetVsVipPortDenyParams() GetVsVipPortDenyParams { + + return GetVsVipPortDenyParams{} +} + +// GetVsVipPortDenyParams contains all the bound params for the get vs vip port deny operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPortDeny +type GetVsVipPortDenyParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortDenyParams() beforehand. +func (o *GetVsVipPortDenyParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortDenyParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_responses.go new file mode 100644 index 000000000..38dca5634 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetVsVipPortDenyOKCode is the HTTP code returned for type GetVsVipPortDenyOK +const GetVsVipPortDenyOKCode int = 200 + +/* +GetVsVipPortDenyOK Success + +swagger:response getVsVipPortDenyOK +*/ +type GetVsVipPortDenyOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortDenyOK creates GetVsVipPortDenyOK with default headers values +func NewGetVsVipPortDenyOK() *GetVsVipPortDenyOK { + + return &GetVsVipPortDenyOK{} +} + +// WithPayload adds the payload to the get vs vip port deny o k response +func (o *GetVsVipPortDenyOK) WithPayload(payload string) *GetVsVipPortDenyOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port deny o k response +func (o *GetVsVipPortDenyOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortDenyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetVsVipPortDenyNotFoundCode is the HTTP code returned for type GetVsVipPortDenyNotFound +const GetVsVipPortDenyNotFoundCode int = 404 + +/* +GetVsVipPortDenyNotFound Service not found + +swagger:response getVsVipPortDenyNotFound +*/ +type GetVsVipPortDenyNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortDenyNotFound creates GetVsVipPortDenyNotFound with default headers values +func NewGetVsVipPortDenyNotFound() *GetVsVipPortDenyNotFound { + + return &GetVsVipPortDenyNotFound{} +} + +// WithPayload adds the payload to the get vs vip port deny not found response +func (o *GetVsVipPortDenyNotFound) WithPayload(payload string) *GetVsVipPortDenyNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port deny not found response +func (o *GetVsVipPortDenyNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortDenyNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_urlbuilder.go new file mode 100644 index 000000000..4cbbbbc4e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// GetVsVipPortDenyURL generates an URL for the get vs vip port deny operation +type GetVsVipPortDenyURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortDenyURL) WithBasePath(bp string) *GetVsVipPortDenyURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortDenyURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortDenyURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/deny" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortDenyURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortDenyURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortDenyURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortDenyURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortDenyURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortDenyURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortDenyURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr.go new file mode 100644 index 000000000..32e70086c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortLaddrHandlerFunc turns a function with the right signature into a get vs vip port laddr handler +type GetVsVipPortLaddrHandlerFunc func(GetVsVipPortLaddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortLaddrHandlerFunc) Handle(params GetVsVipPortLaddrParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortLaddrHandler interface for that can handle valid get vs vip port laddr params +type GetVsVipPortLaddrHandler interface { + Handle(GetVsVipPortLaddrParams) middleware.Responder +} + +// NewGetVsVipPortLaddr creates a new http.Handler for the get vs vip port laddr operation +func NewGetVsVipPortLaddr(ctx *middleware.Context, handler GetVsVipPortLaddrHandler) *GetVsVipPortLaddr { + return &GetVsVipPortLaddr{Context: ctx, Handler: handler} +} + +/* + GetVsVipPortLaddr swagger:route GET /vs/{VipPort}/laddr virtualserver getVsVipPortLaddr + +GetVsVipPortLaddr get vs vip port laddr API +*/ +type GetVsVipPortLaddr struct { + Context *middleware.Context + Handler GetVsVipPortLaddrHandler +} + +func (o *GetVsVipPortLaddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortLaddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_parameters.go new file mode 100644 index 000000000..0fb9cf281 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetVsVipPortLaddrParams creates a new GetVsVipPortLaddrParams object +// with the default values initialized. +func NewGetVsVipPortLaddrParams() GetVsVipPortLaddrParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetVsVipPortLaddrParams{ + Stats: &statsDefault, + } +} + +// GetVsVipPortLaddrParams contains all the bound params for the get vs vip port laddr operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPortLaddr +type GetVsVipPortLaddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortLaddrParams() beforehand. +func (o *GetVsVipPortLaddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortLaddrParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetVsVipPortLaddrParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetVsVipPortLaddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_responses.go new file mode 100644 index 000000000..5ba73eeb0 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_responses.go @@ -0,0 +1,102 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// GetVsVipPortLaddrOKCode is the HTTP code returned for type GetVsVipPortLaddrOK +const GetVsVipPortLaddrOKCode int = 200 + +/* +GetVsVipPortLaddrOK Success + +swagger:response getVsVipPortLaddrOK +*/ +type GetVsVipPortLaddrOK struct { + + /* + In: Body + */ + Payload *models.LocalAddressExpandList `json:"body,omitempty"` +} + +// NewGetVsVipPortLaddrOK creates GetVsVipPortLaddrOK with default headers values +func NewGetVsVipPortLaddrOK() *GetVsVipPortLaddrOK { + + return &GetVsVipPortLaddrOK{} +} + +// WithPayload adds the payload to the get vs vip port laddr o k response +func (o *GetVsVipPortLaddrOK) WithPayload(payload *models.LocalAddressExpandList) *GetVsVipPortLaddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port laddr o k response +func (o *GetVsVipPortLaddrOK) SetPayload(payload *models.LocalAddressExpandList) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortLaddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetVsVipPortLaddrNotFoundCode is the HTTP code returned for type GetVsVipPortLaddrNotFound +const GetVsVipPortLaddrNotFoundCode int = 404 + +/* +GetVsVipPortLaddrNotFound Service not found + +swagger:response getVsVipPortLaddrNotFound +*/ +type GetVsVipPortLaddrNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortLaddrNotFound creates GetVsVipPortLaddrNotFound with default headers values +func NewGetVsVipPortLaddrNotFound() *GetVsVipPortLaddrNotFound { + + return &GetVsVipPortLaddrNotFound{} +} + +// WithPayload adds the payload to the get vs vip port laddr not found response +func (o *GetVsVipPortLaddrNotFound) WithPayload(payload string) *GetVsVipPortLaddrNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port laddr not found response +func (o *GetVsVipPortLaddrNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortLaddrNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_urlbuilder.go new file mode 100644 index 000000000..053283e75 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetVsVipPortLaddrURL generates an URL for the get vs vip port laddr operation +type GetVsVipPortLaddrURL struct { + VipPort string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortLaddrURL) WithBasePath(bp string) *GetVsVipPortLaddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortLaddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortLaddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/laddr" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortLaddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortLaddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortLaddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortLaddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortLaddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortLaddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortLaddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_parameters.go new file mode 100644 index 000000000..a917c108a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetVsVipPortParams creates a new GetVsVipPortParams object +// with the default values initialized. +func NewGetVsVipPortParams() GetVsVipPortParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetVsVipPortParams{ + Stats: &statsDefault, + } +} + +// GetVsVipPortParams contains all the bound params for the get vs vip port operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPort +type GetVsVipPortParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortParams() beforehand. +func (o *GetVsVipPortParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetVsVipPortParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetVsVipPortParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_responses.go new file mode 100644 index 000000000..83d209125 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_responses.go @@ -0,0 +1,102 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// GetVsVipPortOKCode is the HTTP code returned for type GetVsVipPortOK +const GetVsVipPortOKCode int = 200 + +/* +GetVsVipPortOK Success + +swagger:response getVsVipPortOK +*/ +type GetVsVipPortOK struct { + + /* + In: Body + */ + Payload *models.VirtualServerList `json:"body,omitempty"` +} + +// NewGetVsVipPortOK creates GetVsVipPortOK with default headers values +func NewGetVsVipPortOK() *GetVsVipPortOK { + + return &GetVsVipPortOK{} +} + +// WithPayload adds the payload to the get vs vip port o k response +func (o *GetVsVipPortOK) WithPayload(payload *models.VirtualServerList) *GetVsVipPortOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port o k response +func (o *GetVsVipPortOK) SetPayload(payload *models.VirtualServerList) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetVsVipPortNotFoundCode is the HTTP code returned for type GetVsVipPortNotFound +const GetVsVipPortNotFoundCode int = 404 + +/* +GetVsVipPortNotFound Service not found + +swagger:response getVsVipPortNotFound +*/ +type GetVsVipPortNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortNotFound creates GetVsVipPortNotFound with default headers values +func NewGetVsVipPortNotFound() *GetVsVipPortNotFound { + + return &GetVsVipPortNotFound{} +} + +// WithPayload adds the payload to the get vs vip port not found response +func (o *GetVsVipPortNotFound) WithPayload(payload string) *GetVsVipPortNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port not found response +func (o *GetVsVipPortNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs.go new file mode 100644 index 000000000..05692a9ba --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortRsHandlerFunc turns a function with the right signature into a get vs vip port rs handler +type GetVsVipPortRsHandlerFunc func(GetVsVipPortRsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortRsHandlerFunc) Handle(params GetVsVipPortRsParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortRsHandler interface for that can handle valid get vs vip port rs params +type GetVsVipPortRsHandler interface { + Handle(GetVsVipPortRsParams) middleware.Responder +} + +// NewGetVsVipPortRs creates a new http.Handler for the get vs vip port rs operation +func NewGetVsVipPortRs(ctx *middleware.Context, handler GetVsVipPortRsHandler) *GetVsVipPortRs { + return &GetVsVipPortRs{Context: ctx, Handler: handler} +} + +/* + GetVsVipPortRs swagger:route GET /vs/{VipPort}/rs virtualserver getVsVipPortRs + +GetVsVipPortRs get vs vip port rs API +*/ +type GetVsVipPortRs struct { + Context *middleware.Context + Handler GetVsVipPortRsHandler +} + +func (o *GetVsVipPortRs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortRsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_parameters.go new file mode 100644 index 000000000..422d711e1 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetVsVipPortRsParams creates a new GetVsVipPortRsParams object +// with the default values initialized. +func NewGetVsVipPortRsParams() GetVsVipPortRsParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetVsVipPortRsParams{ + Stats: &statsDefault, + } +} + +// GetVsVipPortRsParams contains all the bound params for the get vs vip port rs operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPortRs +type GetVsVipPortRsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortRsParams() beforehand. +func (o *GetVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetVsVipPortRsParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetVsVipPortRsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_responses.go new file mode 100644 index 000000000..54df068a5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetVsVipPortRsOKCode is the HTTP code returned for type GetVsVipPortRsOK +const GetVsVipPortRsOKCode int = 200 + +/* +GetVsVipPortRsOK Success + +swagger:response getVsVipPortRsOK +*/ +type GetVsVipPortRsOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortRsOK creates GetVsVipPortRsOK with default headers values +func NewGetVsVipPortRsOK() *GetVsVipPortRsOK { + + return &GetVsVipPortRsOK{} +} + +// WithPayload adds the payload to the get vs vip port rs o k response +func (o *GetVsVipPortRsOK) WithPayload(payload string) *GetVsVipPortRsOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port rs o k response +func (o *GetVsVipPortRsOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortRsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetVsVipPortRsNotFoundCode is the HTTP code returned for type GetVsVipPortRsNotFound +const GetVsVipPortRsNotFoundCode int = 404 + +/* +GetVsVipPortRsNotFound Service not found + +swagger:response getVsVipPortRsNotFound +*/ +type GetVsVipPortRsNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortRsNotFound creates GetVsVipPortRsNotFound with default headers values +func NewGetVsVipPortRsNotFound() *GetVsVipPortRsNotFound { + + return &GetVsVipPortRsNotFound{} +} + +// WithPayload adds the payload to the get vs vip port rs not found response +func (o *GetVsVipPortRsNotFound) WithPayload(payload string) *GetVsVipPortRsNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port rs not found response +func (o *GetVsVipPortRsNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortRsNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_urlbuilder.go new file mode 100644 index 000000000..f97a471ed --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetVsVipPortRsURL generates an URL for the get vs vip port rs operation +type GetVsVipPortRsURL struct { + VipPort string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortRsURL) WithBasePath(bp string) *GetVsVipPortRsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortRsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortRsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/rs" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortRsURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortRsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortRsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortRsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortRsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortRsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortRsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_urlbuilder.go new file mode 100644 index 000000000..699572745 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetVsVipPortURL generates an URL for the get vs vip port operation +type GetVsVipPortURL struct { + VipPort string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortURL) WithBasePath(bp string) *GetVsVipPortURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow.go new file mode 100644 index 000000000..d5d55cb5e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PostVsVipPortAllowHandlerFunc turns a function with the right signature into a post vs vip port allow handler +type PostVsVipPortAllowHandlerFunc func(PostVsVipPortAllowParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PostVsVipPortAllowHandlerFunc) Handle(params PostVsVipPortAllowParams) middleware.Responder { + return fn(params) +} + +// PostVsVipPortAllowHandler interface for that can handle valid post vs vip port allow params +type PostVsVipPortAllowHandler interface { + Handle(PostVsVipPortAllowParams) middleware.Responder +} + +// NewPostVsVipPortAllow creates a new http.Handler for the post vs vip port allow operation +func NewPostVsVipPortAllow(ctx *middleware.Context, handler PostVsVipPortAllowHandler) *PostVsVipPortAllow { + return &PostVsVipPortAllow{Context: ctx, Handler: handler} +} + +/* + PostVsVipPortAllow swagger:route POST /vs/{VipPort}/allow virtualserver postVsVipPortAllow + +Update a fully white ip list to vip:port:proto +*/ +type PostVsVipPortAllow struct { + Context *middleware.Context + Handler PostVsVipPortAllowHandler +} + +func (o *PostVsVipPortAllow) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPostVsVipPortAllowParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_parameters.go new file mode 100644 index 000000000..6b2511250 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPostVsVipPortAllowParams creates a new PostVsVipPortAllowParams object +// +// There are no default values defined in the spec. +func NewPostVsVipPortAllowParams() PostVsVipPortAllowParams { + + return PostVsVipPortAllowParams{} +} + +// PostVsVipPortAllowParams contains all the bound params for the post vs vip port allow operation +// typically these are obtained from a http.Request +// +// swagger:parameters PostVsVipPortAllow +type PostVsVipPortAllowParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPostVsVipPortAllowParams() beforehand. +func (o *PostVsVipPortAllowParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PostVsVipPortAllowParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_responses.go new file mode 100644 index 000000000..b1d15b9c8 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PostVsVipPortAllowOKCode is the HTTP code returned for type PostVsVipPortAllowOK +const PostVsVipPortAllowOKCode int = 200 + +/* +PostVsVipPortAllowOK Success + +swagger:response postVsVipPortAllowOK +*/ +type PostVsVipPortAllowOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowOK creates PostVsVipPortAllowOK with default headers values +func NewPostVsVipPortAllowOK() *PostVsVipPortAllowOK { + + return &PostVsVipPortAllowOK{} +} + +// WithPayload adds the payload to the post vs vip port allow o k response +func (o *PostVsVipPortAllowOK) WithPayload(payload string) *PostVsVipPortAllowOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow o k response +func (o *PostVsVipPortAllowOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortAllowCreatedCode is the HTTP code returned for type PostVsVipPortAllowCreated +const PostVsVipPortAllowCreatedCode int = 201 + +/* +PostVsVipPortAllowCreated Created + +swagger:response postVsVipPortAllowCreated +*/ +type PostVsVipPortAllowCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowCreated creates PostVsVipPortAllowCreated with default headers values +func NewPostVsVipPortAllowCreated() *PostVsVipPortAllowCreated { + + return &PostVsVipPortAllowCreated{} +} + +// WithPayload adds the payload to the post vs vip port allow created response +func (o *PostVsVipPortAllowCreated) WithPayload(payload string) *PostVsVipPortAllowCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow created response +func (o *PostVsVipPortAllowCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortAllowInvalidFrontendCode is the HTTP code returned for type PostVsVipPortAllowInvalidFrontend +const PostVsVipPortAllowInvalidFrontendCode int = 460 + +/* +PostVsVipPortAllowInvalidFrontend Invalid frontend in service configuration + +swagger:response postVsVipPortAllowInvalidFrontend +*/ +type PostVsVipPortAllowInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowInvalidFrontend creates PostVsVipPortAllowInvalidFrontend with default headers values +func NewPostVsVipPortAllowInvalidFrontend() *PostVsVipPortAllowInvalidFrontend { + + return &PostVsVipPortAllowInvalidFrontend{} +} + +// WithPayload adds the payload to the post vs vip port allow invalid frontend response +func (o *PostVsVipPortAllowInvalidFrontend) WithPayload(payload models.Error) *PostVsVipPortAllowInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow invalid frontend response +func (o *PostVsVipPortAllowInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortAllowInvalidBackendCode is the HTTP code returned for type PostVsVipPortAllowInvalidBackend +const PostVsVipPortAllowInvalidBackendCode int = 461 + +/* +PostVsVipPortAllowInvalidBackend Invalid backend in service configuration + +swagger:response postVsVipPortAllowInvalidBackend +*/ +type PostVsVipPortAllowInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowInvalidBackend creates PostVsVipPortAllowInvalidBackend with default headers values +func NewPostVsVipPortAllowInvalidBackend() *PostVsVipPortAllowInvalidBackend { + + return &PostVsVipPortAllowInvalidBackend{} +} + +// WithPayload adds the payload to the post vs vip port allow invalid backend response +func (o *PostVsVipPortAllowInvalidBackend) WithPayload(payload models.Error) *PostVsVipPortAllowInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow invalid backend response +func (o *PostVsVipPortAllowInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortAllowFailureCode is the HTTP code returned for type PostVsVipPortAllowFailure +const PostVsVipPortAllowFailureCode int = 500 + +/* +PostVsVipPortAllowFailure Service deletion failed + +swagger:response postVsVipPortAllowFailure +*/ +type PostVsVipPortAllowFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowFailure creates PostVsVipPortAllowFailure with default headers values +func NewPostVsVipPortAllowFailure() *PostVsVipPortAllowFailure { + + return &PostVsVipPortAllowFailure{} +} + +// WithPayload adds the payload to the post vs vip port allow failure response +func (o *PostVsVipPortAllowFailure) WithPayload(payload models.Error) *PostVsVipPortAllowFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow failure response +func (o *PostVsVipPortAllowFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_urlbuilder.go new file mode 100644 index 000000000..c7edb0b96 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PostVsVipPortAllowURL generates an URL for the post vs vip port allow operation +type PostVsVipPortAllowURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortAllowURL) WithBasePath(bp string) *PostVsVipPortAllowURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortAllowURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PostVsVipPortAllowURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/allow" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PostVsVipPortAllowURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PostVsVipPortAllowURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PostVsVipPortAllowURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PostVsVipPortAllowURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PostVsVipPortAllowURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PostVsVipPortAllowURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PostVsVipPortAllowURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny.go new file mode 100644 index 000000000..d19eee50e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PostVsVipPortDenyHandlerFunc turns a function with the right signature into a post vs vip port deny handler +type PostVsVipPortDenyHandlerFunc func(PostVsVipPortDenyParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PostVsVipPortDenyHandlerFunc) Handle(params PostVsVipPortDenyParams) middleware.Responder { + return fn(params) +} + +// PostVsVipPortDenyHandler interface for that can handle valid post vs vip port deny params +type PostVsVipPortDenyHandler interface { + Handle(PostVsVipPortDenyParams) middleware.Responder +} + +// NewPostVsVipPortDeny creates a new http.Handler for the post vs vip port deny operation +func NewPostVsVipPortDeny(ctx *middleware.Context, handler PostVsVipPortDenyHandler) *PostVsVipPortDeny { + return &PostVsVipPortDeny{Context: ctx, Handler: handler} +} + +/* + PostVsVipPortDeny swagger:route POST /vs/{VipPort}/deny virtualserver postVsVipPortDeny + +Update a fully black ip list to vip:port:proto +*/ +type PostVsVipPortDeny struct { + Context *middleware.Context + Handler PostVsVipPortDenyHandler +} + +func (o *PostVsVipPortDeny) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPostVsVipPortDenyParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_parameters.go new file mode 100644 index 000000000..56f735df3 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPostVsVipPortDenyParams creates a new PostVsVipPortDenyParams object +// +// There are no default values defined in the spec. +func NewPostVsVipPortDenyParams() PostVsVipPortDenyParams { + + return PostVsVipPortDenyParams{} +} + +// PostVsVipPortDenyParams contains all the bound params for the post vs vip port deny operation +// typically these are obtained from a http.Request +// +// swagger:parameters PostVsVipPortDeny +type PostVsVipPortDenyParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPostVsVipPortDenyParams() beforehand. +func (o *PostVsVipPortDenyParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PostVsVipPortDenyParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_responses.go new file mode 100644 index 000000000..8e813626d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PostVsVipPortDenyOKCode is the HTTP code returned for type PostVsVipPortDenyOK +const PostVsVipPortDenyOKCode int = 200 + +/* +PostVsVipPortDenyOK Success + +swagger:response postVsVipPortDenyOK +*/ +type PostVsVipPortDenyOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyOK creates PostVsVipPortDenyOK with default headers values +func NewPostVsVipPortDenyOK() *PostVsVipPortDenyOK { + + return &PostVsVipPortDenyOK{} +} + +// WithPayload adds the payload to the post vs vip port deny o k response +func (o *PostVsVipPortDenyOK) WithPayload(payload string) *PostVsVipPortDenyOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny o k response +func (o *PostVsVipPortDenyOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortDenyCreatedCode is the HTTP code returned for type PostVsVipPortDenyCreated +const PostVsVipPortDenyCreatedCode int = 201 + +/* +PostVsVipPortDenyCreated Created + +swagger:response postVsVipPortDenyCreated +*/ +type PostVsVipPortDenyCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyCreated creates PostVsVipPortDenyCreated with default headers values +func NewPostVsVipPortDenyCreated() *PostVsVipPortDenyCreated { + + return &PostVsVipPortDenyCreated{} +} + +// WithPayload adds the payload to the post vs vip port deny created response +func (o *PostVsVipPortDenyCreated) WithPayload(payload string) *PostVsVipPortDenyCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny created response +func (o *PostVsVipPortDenyCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortDenyInvalidFrontendCode is the HTTP code returned for type PostVsVipPortDenyInvalidFrontend +const PostVsVipPortDenyInvalidFrontendCode int = 460 + +/* +PostVsVipPortDenyInvalidFrontend Invalid frontend in service configuration + +swagger:response postVsVipPortDenyInvalidFrontend +*/ +type PostVsVipPortDenyInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyInvalidFrontend creates PostVsVipPortDenyInvalidFrontend with default headers values +func NewPostVsVipPortDenyInvalidFrontend() *PostVsVipPortDenyInvalidFrontend { + + return &PostVsVipPortDenyInvalidFrontend{} +} + +// WithPayload adds the payload to the post vs vip port deny invalid frontend response +func (o *PostVsVipPortDenyInvalidFrontend) WithPayload(payload models.Error) *PostVsVipPortDenyInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny invalid frontend response +func (o *PostVsVipPortDenyInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortDenyInvalidBackendCode is the HTTP code returned for type PostVsVipPortDenyInvalidBackend +const PostVsVipPortDenyInvalidBackendCode int = 461 + +/* +PostVsVipPortDenyInvalidBackend Invalid backend in service configuration + +swagger:response postVsVipPortDenyInvalidBackend +*/ +type PostVsVipPortDenyInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyInvalidBackend creates PostVsVipPortDenyInvalidBackend with default headers values +func NewPostVsVipPortDenyInvalidBackend() *PostVsVipPortDenyInvalidBackend { + + return &PostVsVipPortDenyInvalidBackend{} +} + +// WithPayload adds the payload to the post vs vip port deny invalid backend response +func (o *PostVsVipPortDenyInvalidBackend) WithPayload(payload models.Error) *PostVsVipPortDenyInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny invalid backend response +func (o *PostVsVipPortDenyInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortDenyFailureCode is the HTTP code returned for type PostVsVipPortDenyFailure +const PostVsVipPortDenyFailureCode int = 500 + +/* +PostVsVipPortDenyFailure Service deletion failed + +swagger:response postVsVipPortDenyFailure +*/ +type PostVsVipPortDenyFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyFailure creates PostVsVipPortDenyFailure with default headers values +func NewPostVsVipPortDenyFailure() *PostVsVipPortDenyFailure { + + return &PostVsVipPortDenyFailure{} +} + +// WithPayload adds the payload to the post vs vip port deny failure response +func (o *PostVsVipPortDenyFailure) WithPayload(payload models.Error) *PostVsVipPortDenyFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny failure response +func (o *PostVsVipPortDenyFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_urlbuilder.go new file mode 100644 index 000000000..b63560b1d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PostVsVipPortDenyURL generates an URL for the post vs vip port deny operation +type PostVsVipPortDenyURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortDenyURL) WithBasePath(bp string) *PostVsVipPortDenyURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortDenyURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PostVsVipPortDenyURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/deny" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PostVsVipPortDenyURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PostVsVipPortDenyURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PostVsVipPortDenyURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PostVsVipPortDenyURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PostVsVipPortDenyURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PostVsVipPortDenyURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PostVsVipPortDenyURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs.go new file mode 100644 index 000000000..26ff3ea34 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PostVsVipPortRsHandlerFunc turns a function with the right signature into a post vs vip port rs handler +type PostVsVipPortRsHandlerFunc func(PostVsVipPortRsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PostVsVipPortRsHandlerFunc) Handle(params PostVsVipPortRsParams) middleware.Responder { + return fn(params) +} + +// PostVsVipPortRsHandler interface for that can handle valid post vs vip port rs params +type PostVsVipPortRsHandler interface { + Handle(PostVsVipPortRsParams) middleware.Responder +} + +// NewPostVsVipPortRs creates a new http.Handler for the post vs vip port rs operation +func NewPostVsVipPortRs(ctx *middleware.Context, handler PostVsVipPortRsHandler) *PostVsVipPortRs { + return &PostVsVipPortRs{Context: ctx, Handler: handler} +} + +/* + PostVsVipPortRs swagger:route POST /vs/{VipPort}/rs virtualserver postVsVipPortRs + +Update fully real server list to vip:port:proto +*/ +type PostVsVipPortRs struct { + Context *middleware.Context + Handler PostVsVipPortRsHandler +} + +func (o *PostVsVipPortRs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPostVsVipPortRsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go new file mode 100644 index 000000000..948a9f38b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPostVsVipPortRsParams creates a new PostVsVipPortRsParams object +// +// There are no default values defined in the spec. +func NewPostVsVipPortRsParams() PostVsVipPortRsParams { + + return PostVsVipPortRsParams{} +} + +// PostVsVipPortRsParams contains all the bound params for the post vs vip port rs operation +// typically these are obtained from a http.Request +// +// swagger:parameters PostVsVipPortRs +type PostVsVipPortRsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Rss *models.RealServerTinyList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPostVsVipPortRsParams() beforehand. +func (o *PostVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RealServerTinyList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("rss", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Rss = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PostVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_responses.go new file mode 100644 index 000000000..fd154d53e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PostVsVipPortRsOKCode is the HTTP code returned for type PostVsVipPortRsOK +const PostVsVipPortRsOKCode int = 200 + +/* +PostVsVipPortRsOK Success + +swagger:response postVsVipPortRsOK +*/ +type PostVsVipPortRsOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortRsOK creates PostVsVipPortRsOK with default headers values +func NewPostVsVipPortRsOK() *PostVsVipPortRsOK { + + return &PostVsVipPortRsOK{} +} + +// WithPayload adds the payload to the post vs vip port rs o k response +func (o *PostVsVipPortRsOK) WithPayload(payload string) *PostVsVipPortRsOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs o k response +func (o *PostVsVipPortRsOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortRsCreatedCode is the HTTP code returned for type PostVsVipPortRsCreated +const PostVsVipPortRsCreatedCode int = 201 + +/* +PostVsVipPortRsCreated Created + +swagger:response postVsVipPortRsCreated +*/ +type PostVsVipPortRsCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortRsCreated creates PostVsVipPortRsCreated with default headers values +func NewPostVsVipPortRsCreated() *PostVsVipPortRsCreated { + + return &PostVsVipPortRsCreated{} +} + +// WithPayload adds the payload to the post vs vip port rs created response +func (o *PostVsVipPortRsCreated) WithPayload(payload string) *PostVsVipPortRsCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs created response +func (o *PostVsVipPortRsCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortRsInvalidFrontendCode is the HTTP code returned for type PostVsVipPortRsInvalidFrontend +const PostVsVipPortRsInvalidFrontendCode int = 460 + +/* +PostVsVipPortRsInvalidFrontend Invalid frontend in service configuration + +swagger:response postVsVipPortRsInvalidFrontend +*/ +type PostVsVipPortRsInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortRsInvalidFrontend creates PostVsVipPortRsInvalidFrontend with default headers values +func NewPostVsVipPortRsInvalidFrontend() *PostVsVipPortRsInvalidFrontend { + + return &PostVsVipPortRsInvalidFrontend{} +} + +// WithPayload adds the payload to the post vs vip port rs invalid frontend response +func (o *PostVsVipPortRsInvalidFrontend) WithPayload(payload models.Error) *PostVsVipPortRsInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs invalid frontend response +func (o *PostVsVipPortRsInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortRsInvalidBackendCode is the HTTP code returned for type PostVsVipPortRsInvalidBackend +const PostVsVipPortRsInvalidBackendCode int = 461 + +/* +PostVsVipPortRsInvalidBackend Invalid backend in service configuration + +swagger:response postVsVipPortRsInvalidBackend +*/ +type PostVsVipPortRsInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortRsInvalidBackend creates PostVsVipPortRsInvalidBackend with default headers values +func NewPostVsVipPortRsInvalidBackend() *PostVsVipPortRsInvalidBackend { + + return &PostVsVipPortRsInvalidBackend{} +} + +// WithPayload adds the payload to the post vs vip port rs invalid backend response +func (o *PostVsVipPortRsInvalidBackend) WithPayload(payload models.Error) *PostVsVipPortRsInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs invalid backend response +func (o *PostVsVipPortRsInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortRsFailureCode is the HTTP code returned for type PostVsVipPortRsFailure +const PostVsVipPortRsFailureCode int = 500 + +/* +PostVsVipPortRsFailure Service deletion failed + +swagger:response postVsVipPortRsFailure +*/ +type PostVsVipPortRsFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortRsFailure creates PostVsVipPortRsFailure with default headers values +func NewPostVsVipPortRsFailure() *PostVsVipPortRsFailure { + + return &PostVsVipPortRsFailure{} +} + +// WithPayload adds the payload to the post vs vip port rs failure response +func (o *PostVsVipPortRsFailure) WithPayload(payload models.Error) *PostVsVipPortRsFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs failure response +func (o *PostVsVipPortRsFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go new file mode 100644 index 000000000..1c7f7b01e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PostVsVipPortRsURL generates an URL for the post vs vip port rs operation +type PostVsVipPortRsURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortRsURL) WithBasePath(bp string) *PostVsVipPortRsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortRsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PostVsVipPortRsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/rs" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PostVsVipPortRsURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PostVsVipPortRsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PostVsVipPortRsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PostVsVipPortRsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PostVsVipPortRsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PostVsVipPortRsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PostVsVipPortRsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port.go new file mode 100644 index 000000000..78b20e404 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortHandlerFunc turns a function with the right signature into a put vs vip port handler +type PutVsVipPortHandlerFunc func(PutVsVipPortParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortHandlerFunc) Handle(params PutVsVipPortParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortHandler interface for that can handle valid put vs vip port params +type PutVsVipPortHandler interface { + Handle(PutVsVipPortParams) middleware.Responder +} + +// NewPutVsVipPort creates a new http.Handler for the put vs vip port operation +func NewPutVsVipPort(ctx *middleware.Context, handler PutVsVipPortHandler) *PutVsVipPort { + return &PutVsVipPort{Context: ctx, Handler: handler} +} + +/* + PutVsVipPort swagger:route PUT /vs/{VipPort} virtualserver putVsVipPort + +create or update virtual server +*/ +type PutVsVipPort struct { + Context *middleware.Context + Handler PutVsVipPortHandler +} + +func (o *PutVsVipPort) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow.go new file mode 100644 index 000000000..d3fa4b93c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortAllowHandlerFunc turns a function with the right signature into a put vs vip port allow handler +type PutVsVipPortAllowHandlerFunc func(PutVsVipPortAllowParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortAllowHandlerFunc) Handle(params PutVsVipPortAllowParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortAllowHandler interface for that can handle valid put vs vip port allow params +type PutVsVipPortAllowHandler interface { + Handle(PutVsVipPortAllowParams) middleware.Responder +} + +// NewPutVsVipPortAllow creates a new http.Handler for the put vs vip port allow operation +func NewPutVsVipPortAllow(ctx *middleware.Context, handler PutVsVipPortAllowHandler) *PutVsVipPortAllow { + return &PutVsVipPortAllow{Context: ctx, Handler: handler} +} + +/* + PutVsVipPortAllow swagger:route PUT /vs/{VipPort}/allow virtualserver putVsVipPortAllow + +Add a set of ip from white list to vip:port:proto +*/ +type PutVsVipPortAllow struct { + Context *middleware.Context + Handler PutVsVipPortAllowHandler +} + +func (o *PutVsVipPortAllow) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortAllowParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_parameters.go new file mode 100644 index 000000000..dfb8da2e2 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortAllowParams creates a new PutVsVipPortAllowParams object +// +// There are no default values defined in the spec. +func NewPutVsVipPortAllowParams() PutVsVipPortAllowParams { + + return PutVsVipPortAllowParams{} +} + +// PutVsVipPortAllowParams contains all the bound params for the put vs vip port allow operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPortAllow +type PutVsVipPortAllowParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortAllowParams() beforehand. +func (o *PutVsVipPortAllowParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortAllowParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_responses.go new file mode 100644 index 000000000..38d69cf91 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortAllowOKCode is the HTTP code returned for type PutVsVipPortAllowOK +const PutVsVipPortAllowOKCode int = 200 + +/* +PutVsVipPortAllowOK Success + +swagger:response putVsVipPortAllowOK +*/ +type PutVsVipPortAllowOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowOK creates PutVsVipPortAllowOK with default headers values +func NewPutVsVipPortAllowOK() *PutVsVipPortAllowOK { + + return &PutVsVipPortAllowOK{} +} + +// WithPayload adds the payload to the put vs vip port allow o k response +func (o *PutVsVipPortAllowOK) WithPayload(payload string) *PutVsVipPortAllowOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow o k response +func (o *PutVsVipPortAllowOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortAllowCreatedCode is the HTTP code returned for type PutVsVipPortAllowCreated +const PutVsVipPortAllowCreatedCode int = 201 + +/* +PutVsVipPortAllowCreated Created + +swagger:response putVsVipPortAllowCreated +*/ +type PutVsVipPortAllowCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowCreated creates PutVsVipPortAllowCreated with default headers values +func NewPutVsVipPortAllowCreated() *PutVsVipPortAllowCreated { + + return &PutVsVipPortAllowCreated{} +} + +// WithPayload adds the payload to the put vs vip port allow created response +func (o *PutVsVipPortAllowCreated) WithPayload(payload string) *PutVsVipPortAllowCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow created response +func (o *PutVsVipPortAllowCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortAllowInvalidFrontendCode is the HTTP code returned for type PutVsVipPortAllowInvalidFrontend +const PutVsVipPortAllowInvalidFrontendCode int = 460 + +/* +PutVsVipPortAllowInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortAllowInvalidFrontend +*/ +type PutVsVipPortAllowInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowInvalidFrontend creates PutVsVipPortAllowInvalidFrontend with default headers values +func NewPutVsVipPortAllowInvalidFrontend() *PutVsVipPortAllowInvalidFrontend { + + return &PutVsVipPortAllowInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port allow invalid frontend response +func (o *PutVsVipPortAllowInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortAllowInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow invalid frontend response +func (o *PutVsVipPortAllowInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortAllowInvalidBackendCode is the HTTP code returned for type PutVsVipPortAllowInvalidBackend +const PutVsVipPortAllowInvalidBackendCode int = 461 + +/* +PutVsVipPortAllowInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortAllowInvalidBackend +*/ +type PutVsVipPortAllowInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowInvalidBackend creates PutVsVipPortAllowInvalidBackend with default headers values +func NewPutVsVipPortAllowInvalidBackend() *PutVsVipPortAllowInvalidBackend { + + return &PutVsVipPortAllowInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port allow invalid backend response +func (o *PutVsVipPortAllowInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortAllowInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow invalid backend response +func (o *PutVsVipPortAllowInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortAllowFailureCode is the HTTP code returned for type PutVsVipPortAllowFailure +const PutVsVipPortAllowFailureCode int = 500 + +/* +PutVsVipPortAllowFailure Service deletion failed + +swagger:response putVsVipPortAllowFailure +*/ +type PutVsVipPortAllowFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowFailure creates PutVsVipPortAllowFailure with default headers values +func NewPutVsVipPortAllowFailure() *PutVsVipPortAllowFailure { + + return &PutVsVipPortAllowFailure{} +} + +// WithPayload adds the payload to the put vs vip port allow failure response +func (o *PutVsVipPortAllowFailure) WithPayload(payload models.Error) *PutVsVipPortAllowFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow failure response +func (o *PutVsVipPortAllowFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_urlbuilder.go new file mode 100644 index 000000000..ba8719936 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutVsVipPortAllowURL generates an URL for the put vs vip port allow operation +type PutVsVipPortAllowURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortAllowURL) WithBasePath(bp string) *PutVsVipPortAllowURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortAllowURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortAllowURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/allow" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortAllowURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortAllowURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortAllowURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortAllowURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortAllowURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortAllowURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortAllowURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny.go new file mode 100644 index 000000000..180e1242b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortDenyHandlerFunc turns a function with the right signature into a put vs vip port deny handler +type PutVsVipPortDenyHandlerFunc func(PutVsVipPortDenyParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortDenyHandlerFunc) Handle(params PutVsVipPortDenyParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortDenyHandler interface for that can handle valid put vs vip port deny params +type PutVsVipPortDenyHandler interface { + Handle(PutVsVipPortDenyParams) middleware.Responder +} + +// NewPutVsVipPortDeny creates a new http.Handler for the put vs vip port deny operation +func NewPutVsVipPortDeny(ctx *middleware.Context, handler PutVsVipPortDenyHandler) *PutVsVipPortDeny { + return &PutVsVipPortDeny{Context: ctx, Handler: handler} +} + +/* + PutVsVipPortDeny swagger:route PUT /vs/{VipPort}/deny virtualserver putVsVipPortDeny + +Add a set of ip from black list to vip:port:proto +*/ +type PutVsVipPortDeny struct { + Context *middleware.Context + Handler PutVsVipPortDenyHandler +} + +func (o *PutVsVipPortDeny) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortDenyParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_parameters.go new file mode 100644 index 000000000..6d28ff26e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortDenyParams creates a new PutVsVipPortDenyParams object +// +// There are no default values defined in the spec. +func NewPutVsVipPortDenyParams() PutVsVipPortDenyParams { + + return PutVsVipPortDenyParams{} +} + +// PutVsVipPortDenyParams contains all the bound params for the put vs vip port deny operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPortDeny +type PutVsVipPortDenyParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortDenyParams() beforehand. +func (o *PutVsVipPortDenyParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortDenyParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_responses.go new file mode 100644 index 000000000..aae11334f --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortDenyOKCode is the HTTP code returned for type PutVsVipPortDenyOK +const PutVsVipPortDenyOKCode int = 200 + +/* +PutVsVipPortDenyOK Success + +swagger:response putVsVipPortDenyOK +*/ +type PutVsVipPortDenyOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyOK creates PutVsVipPortDenyOK with default headers values +func NewPutVsVipPortDenyOK() *PutVsVipPortDenyOK { + + return &PutVsVipPortDenyOK{} +} + +// WithPayload adds the payload to the put vs vip port deny o k response +func (o *PutVsVipPortDenyOK) WithPayload(payload string) *PutVsVipPortDenyOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny o k response +func (o *PutVsVipPortDenyOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortDenyCreatedCode is the HTTP code returned for type PutVsVipPortDenyCreated +const PutVsVipPortDenyCreatedCode int = 201 + +/* +PutVsVipPortDenyCreated Created + +swagger:response putVsVipPortDenyCreated +*/ +type PutVsVipPortDenyCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyCreated creates PutVsVipPortDenyCreated with default headers values +func NewPutVsVipPortDenyCreated() *PutVsVipPortDenyCreated { + + return &PutVsVipPortDenyCreated{} +} + +// WithPayload adds the payload to the put vs vip port deny created response +func (o *PutVsVipPortDenyCreated) WithPayload(payload string) *PutVsVipPortDenyCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny created response +func (o *PutVsVipPortDenyCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortDenyInvalidFrontendCode is the HTTP code returned for type PutVsVipPortDenyInvalidFrontend +const PutVsVipPortDenyInvalidFrontendCode int = 460 + +/* +PutVsVipPortDenyInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortDenyInvalidFrontend +*/ +type PutVsVipPortDenyInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyInvalidFrontend creates PutVsVipPortDenyInvalidFrontend with default headers values +func NewPutVsVipPortDenyInvalidFrontend() *PutVsVipPortDenyInvalidFrontend { + + return &PutVsVipPortDenyInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port deny invalid frontend response +func (o *PutVsVipPortDenyInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortDenyInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny invalid frontend response +func (o *PutVsVipPortDenyInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortDenyInvalidBackendCode is the HTTP code returned for type PutVsVipPortDenyInvalidBackend +const PutVsVipPortDenyInvalidBackendCode int = 461 + +/* +PutVsVipPortDenyInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortDenyInvalidBackend +*/ +type PutVsVipPortDenyInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyInvalidBackend creates PutVsVipPortDenyInvalidBackend with default headers values +func NewPutVsVipPortDenyInvalidBackend() *PutVsVipPortDenyInvalidBackend { + + return &PutVsVipPortDenyInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port deny invalid backend response +func (o *PutVsVipPortDenyInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortDenyInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny invalid backend response +func (o *PutVsVipPortDenyInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortDenyFailureCode is the HTTP code returned for type PutVsVipPortDenyFailure +const PutVsVipPortDenyFailureCode int = 500 + +/* +PutVsVipPortDenyFailure Service deletion failed + +swagger:response putVsVipPortDenyFailure +*/ +type PutVsVipPortDenyFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyFailure creates PutVsVipPortDenyFailure with default headers values +func NewPutVsVipPortDenyFailure() *PutVsVipPortDenyFailure { + + return &PutVsVipPortDenyFailure{} +} + +// WithPayload adds the payload to the put vs vip port deny failure response +func (o *PutVsVipPortDenyFailure) WithPayload(payload models.Error) *PutVsVipPortDenyFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny failure response +func (o *PutVsVipPortDenyFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_urlbuilder.go new file mode 100644 index 000000000..48450185b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutVsVipPortDenyURL generates an URL for the put vs vip port deny operation +type PutVsVipPortDenyURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortDenyURL) WithBasePath(bp string) *PutVsVipPortDenyURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortDenyURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortDenyURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/deny" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortDenyURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortDenyURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortDenyURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortDenyURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortDenyURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortDenyURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortDenyURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr.go new file mode 100644 index 000000000..a75db0dc4 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortLaddrHandlerFunc turns a function with the right signature into a put vs vip port laddr handler +type PutVsVipPortLaddrHandlerFunc func(PutVsVipPortLaddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortLaddrHandlerFunc) Handle(params PutVsVipPortLaddrParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortLaddrHandler interface for that can handle valid put vs vip port laddr params +type PutVsVipPortLaddrHandler interface { + Handle(PutVsVipPortLaddrParams) middleware.Responder +} + +// NewPutVsVipPortLaddr creates a new http.Handler for the put vs vip port laddr operation +func NewPutVsVipPortLaddr(ctx *middleware.Context, handler PutVsVipPortLaddrHandler) *PutVsVipPortLaddr { + return &PutVsVipPortLaddr{Context: ctx, Handler: handler} +} + +/* + PutVsVipPortLaddr swagger:route PUT /vs/{VipPort}/laddr virtualserver putVsVipPortLaddr + +PutVsVipPortLaddr put vs vip port laddr API +*/ +type PutVsVipPortLaddr struct { + Context *middleware.Context + Handler PutVsVipPortLaddrHandler +} + +func (o *PutVsVipPortLaddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortLaddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_parameters.go new file mode 100644 index 000000000..94c97a03a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortLaddrParams creates a new PutVsVipPortLaddrParams object +// +// There are no default values defined in the spec. +func NewPutVsVipPortLaddrParams() PutVsVipPortLaddrParams { + + return PutVsVipPortLaddrParams{} +} + +// PutVsVipPortLaddrParams contains all the bound params for the put vs vip port laddr operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPortLaddr +type PutVsVipPortLaddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Spec *models.LocalAddressSpecTiny +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortLaddrParams() beforehand. +func (o *PutVsVipPortLaddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.LocalAddressSpecTiny + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortLaddrParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_responses.go new file mode 100644 index 000000000..9d4f6bc00 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortLaddrOKCode is the HTTP code returned for type PutVsVipPortLaddrOK +const PutVsVipPortLaddrOKCode int = 200 + +/* +PutVsVipPortLaddrOK Success + +swagger:response putVsVipPortLaddrOK +*/ +type PutVsVipPortLaddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrOK creates PutVsVipPortLaddrOK with default headers values +func NewPutVsVipPortLaddrOK() *PutVsVipPortLaddrOK { + + return &PutVsVipPortLaddrOK{} +} + +// WithPayload adds the payload to the put vs vip port laddr o k response +func (o *PutVsVipPortLaddrOK) WithPayload(payload string) *PutVsVipPortLaddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr o k response +func (o *PutVsVipPortLaddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortLaddrCreatedCode is the HTTP code returned for type PutVsVipPortLaddrCreated +const PutVsVipPortLaddrCreatedCode int = 201 + +/* +PutVsVipPortLaddrCreated Created + +swagger:response putVsVipPortLaddrCreated +*/ +type PutVsVipPortLaddrCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrCreated creates PutVsVipPortLaddrCreated with default headers values +func NewPutVsVipPortLaddrCreated() *PutVsVipPortLaddrCreated { + + return &PutVsVipPortLaddrCreated{} +} + +// WithPayload adds the payload to the put vs vip port laddr created response +func (o *PutVsVipPortLaddrCreated) WithPayload(payload string) *PutVsVipPortLaddrCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr created response +func (o *PutVsVipPortLaddrCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortLaddrInvalidFrontendCode is the HTTP code returned for type PutVsVipPortLaddrInvalidFrontend +const PutVsVipPortLaddrInvalidFrontendCode int = 460 + +/* +PutVsVipPortLaddrInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortLaddrInvalidFrontend +*/ +type PutVsVipPortLaddrInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrInvalidFrontend creates PutVsVipPortLaddrInvalidFrontend with default headers values +func NewPutVsVipPortLaddrInvalidFrontend() *PutVsVipPortLaddrInvalidFrontend { + + return &PutVsVipPortLaddrInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port laddr invalid frontend response +func (o *PutVsVipPortLaddrInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortLaddrInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr invalid frontend response +func (o *PutVsVipPortLaddrInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortLaddrInvalidBackendCode is the HTTP code returned for type PutVsVipPortLaddrInvalidBackend +const PutVsVipPortLaddrInvalidBackendCode int = 461 + +/* +PutVsVipPortLaddrInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortLaddrInvalidBackend +*/ +type PutVsVipPortLaddrInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrInvalidBackend creates PutVsVipPortLaddrInvalidBackend with default headers values +func NewPutVsVipPortLaddrInvalidBackend() *PutVsVipPortLaddrInvalidBackend { + + return &PutVsVipPortLaddrInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port laddr invalid backend response +func (o *PutVsVipPortLaddrInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortLaddrInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr invalid backend response +func (o *PutVsVipPortLaddrInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortLaddrFailureCode is the HTTP code returned for type PutVsVipPortLaddrFailure +const PutVsVipPortLaddrFailureCode int = 500 + +/* +PutVsVipPortLaddrFailure Error while creating virtual server + +swagger:response putVsVipPortLaddrFailure +*/ +type PutVsVipPortLaddrFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrFailure creates PutVsVipPortLaddrFailure with default headers values +func NewPutVsVipPortLaddrFailure() *PutVsVipPortLaddrFailure { + + return &PutVsVipPortLaddrFailure{} +} + +// WithPayload adds the payload to the put vs vip port laddr failure response +func (o *PutVsVipPortLaddrFailure) WithPayload(payload models.Error) *PutVsVipPortLaddrFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr failure response +func (o *PutVsVipPortLaddrFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_urlbuilder.go new file mode 100644 index 000000000..c0dc2d7d5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutVsVipPortLaddrURL generates an URL for the put vs vip port laddr operation +type PutVsVipPortLaddrURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortLaddrURL) WithBasePath(bp string) *PutVsVipPortLaddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortLaddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortLaddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/laddr" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortLaddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortLaddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortLaddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortLaddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortLaddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortLaddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortLaddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go new file mode 100644 index 000000000..8dc0c2030 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortParams creates a new PutVsVipPortParams object +// +// There are no default values defined in the spec. +func NewPutVsVipPortParams() PutVsVipPortParams { + + return PutVsVipPortParams{} +} + +// PutVsVipPortParams contains all the bound params for the put vs vip port operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPort +type PutVsVipPortParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Spec *models.VirtualServerSpecTiny +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortParams() beforehand. +func (o *PutVsVipPortParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.VirtualServerSpecTiny + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_responses.go new file mode 100644 index 000000000..19946ac56 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortOKCode is the HTTP code returned for type PutVsVipPortOK +const PutVsVipPortOKCode int = 200 + +/* +PutVsVipPortOK Updated + +swagger:response putVsVipPortOK +*/ +type PutVsVipPortOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortOK creates PutVsVipPortOK with default headers values +func NewPutVsVipPortOK() *PutVsVipPortOK { + + return &PutVsVipPortOK{} +} + +// WithPayload adds the payload to the put vs vip port o k response +func (o *PutVsVipPortOK) WithPayload(payload string) *PutVsVipPortOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port o k response +func (o *PutVsVipPortOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortCreatedCode is the HTTP code returned for type PutVsVipPortCreated +const PutVsVipPortCreatedCode int = 201 + +/* +PutVsVipPortCreated Created + +swagger:response putVsVipPortCreated +*/ +type PutVsVipPortCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortCreated creates PutVsVipPortCreated with default headers values +func NewPutVsVipPortCreated() *PutVsVipPortCreated { + + return &PutVsVipPortCreated{} +} + +// WithPayload adds the payload to the put vs vip port created response +func (o *PutVsVipPortCreated) WithPayload(payload string) *PutVsVipPortCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port created response +func (o *PutVsVipPortCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortInvalidFrontendCode is the HTTP code returned for type PutVsVipPortInvalidFrontend +const PutVsVipPortInvalidFrontendCode int = 460 + +/* +PutVsVipPortInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortInvalidFrontend +*/ +type PutVsVipPortInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortInvalidFrontend creates PutVsVipPortInvalidFrontend with default headers values +func NewPutVsVipPortInvalidFrontend() *PutVsVipPortInvalidFrontend { + + return &PutVsVipPortInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port invalid frontend response +func (o *PutVsVipPortInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port invalid frontend response +func (o *PutVsVipPortInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortInvalidBackendCode is the HTTP code returned for type PutVsVipPortInvalidBackend +const PutVsVipPortInvalidBackendCode int = 461 + +/* +PutVsVipPortInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortInvalidBackend +*/ +type PutVsVipPortInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortInvalidBackend creates PutVsVipPortInvalidBackend with default headers values +func NewPutVsVipPortInvalidBackend() *PutVsVipPortInvalidBackend { + + return &PutVsVipPortInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port invalid backend response +func (o *PutVsVipPortInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port invalid backend response +func (o *PutVsVipPortInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortFailureCode is the HTTP code returned for type PutVsVipPortFailure +const PutVsVipPortFailureCode int = 500 + +/* +PutVsVipPortFailure Error while creating virtual server + +swagger:response putVsVipPortFailure +*/ +type PutVsVipPortFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortFailure creates PutVsVipPortFailure with default headers values +func NewPutVsVipPortFailure() *PutVsVipPortFailure { + + return &PutVsVipPortFailure{} +} + +// WithPayload adds the payload to the put vs vip port failure response +func (o *PutVsVipPortFailure) WithPayload(payload models.Error) *PutVsVipPortFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port failure response +func (o *PutVsVipPortFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs.go new file mode 100644 index 000000000..475833200 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortRsHandlerFunc turns a function with the right signature into a put vs vip port rs handler +type PutVsVipPortRsHandlerFunc func(PutVsVipPortRsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortRsHandlerFunc) Handle(params PutVsVipPortRsParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortRsHandler interface for that can handle valid put vs vip port rs params +type PutVsVipPortRsHandler interface { + Handle(PutVsVipPortRsParams) middleware.Responder +} + +// NewPutVsVipPortRs creates a new http.Handler for the put vs vip port rs operation +func NewPutVsVipPortRs(ctx *middleware.Context, handler PutVsVipPortRsHandler) *PutVsVipPortRs { + return &PutVsVipPortRs{Context: ctx, Handler: handler} +} + +/* + PutVsVipPortRs swagger:route PUT /vs/{VipPort}/rs virtualserver putVsVipPortRs + +Add a set of real server to vip:port:proto +*/ +type PutVsVipPortRs struct { + Context *middleware.Context + Handler PutVsVipPortRsHandler +} + +func (o *PutVsVipPortRs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortRsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_parameters.go new file mode 100644 index 000000000..0e36def24 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_parameters.go @@ -0,0 +1,145 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortRsParams creates a new PutVsVipPortRsParams object +// with the default values initialized. +func NewPutVsVipPortRsParams() PutVsVipPortRsParams { + + var ( + // initialize parameters with default values + + healthcheckDefault = bool(false) + ) + + return PutVsVipPortRsParams{ + Healthcheck: &healthcheckDefault, + } +} + +// PutVsVipPortRsParams contains all the bound params for the put vs vip port rs operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPortRs +type PutVsVipPortRsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: query + Default: false + */ + Healthcheck *bool + /* + In: body + */ + Rss *models.RealServerTinyList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortRsParams() beforehand. +func (o *PutVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + qHealthcheck, qhkHealthcheck, _ := qs.GetOK("healthcheck") + if err := o.bindHealthcheck(qHealthcheck, qhkHealthcheck, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RealServerTinyList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("rss", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Rss = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} + +// bindHealthcheck binds and validates parameter Healthcheck from query. +func (o *PutVsVipPortRsParams) bindHealthcheck(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutVsVipPortRsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("healthcheck", "query", "bool", raw) + } + o.Healthcheck = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_responses.go new file mode 100644 index 000000000..8dd6b9737 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortRsOKCode is the HTTP code returned for type PutVsVipPortRsOK +const PutVsVipPortRsOKCode int = 200 + +/* +PutVsVipPortRsOK Success + +swagger:response putVsVipPortRsOK +*/ +type PutVsVipPortRsOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortRsOK creates PutVsVipPortRsOK with default headers values +func NewPutVsVipPortRsOK() *PutVsVipPortRsOK { + + return &PutVsVipPortRsOK{} +} + +// WithPayload adds the payload to the put vs vip port rs o k response +func (o *PutVsVipPortRsOK) WithPayload(payload string) *PutVsVipPortRsOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs o k response +func (o *PutVsVipPortRsOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortRsCreatedCode is the HTTP code returned for type PutVsVipPortRsCreated +const PutVsVipPortRsCreatedCode int = 201 + +/* +PutVsVipPortRsCreated Created + +swagger:response putVsVipPortRsCreated +*/ +type PutVsVipPortRsCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortRsCreated creates PutVsVipPortRsCreated with default headers values +func NewPutVsVipPortRsCreated() *PutVsVipPortRsCreated { + + return &PutVsVipPortRsCreated{} +} + +// WithPayload adds the payload to the put vs vip port rs created response +func (o *PutVsVipPortRsCreated) WithPayload(payload string) *PutVsVipPortRsCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs created response +func (o *PutVsVipPortRsCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortRsInvalidFrontendCode is the HTTP code returned for type PutVsVipPortRsInvalidFrontend +const PutVsVipPortRsInvalidFrontendCode int = 460 + +/* +PutVsVipPortRsInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortRsInvalidFrontend +*/ +type PutVsVipPortRsInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortRsInvalidFrontend creates PutVsVipPortRsInvalidFrontend with default headers values +func NewPutVsVipPortRsInvalidFrontend() *PutVsVipPortRsInvalidFrontend { + + return &PutVsVipPortRsInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port rs invalid frontend response +func (o *PutVsVipPortRsInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortRsInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs invalid frontend response +func (o *PutVsVipPortRsInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortRsInvalidBackendCode is the HTTP code returned for type PutVsVipPortRsInvalidBackend +const PutVsVipPortRsInvalidBackendCode int = 461 + +/* +PutVsVipPortRsInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortRsInvalidBackend +*/ +type PutVsVipPortRsInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortRsInvalidBackend creates PutVsVipPortRsInvalidBackend with default headers values +func NewPutVsVipPortRsInvalidBackend() *PutVsVipPortRsInvalidBackend { + + return &PutVsVipPortRsInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port rs invalid backend response +func (o *PutVsVipPortRsInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortRsInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs invalid backend response +func (o *PutVsVipPortRsInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortRsFailureCode is the HTTP code returned for type PutVsVipPortRsFailure +const PutVsVipPortRsFailureCode int = 500 + +/* +PutVsVipPortRsFailure Service deletion failed + +swagger:response putVsVipPortRsFailure +*/ +type PutVsVipPortRsFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortRsFailure creates PutVsVipPortRsFailure with default headers values +func NewPutVsVipPortRsFailure() *PutVsVipPortRsFailure { + + return &PutVsVipPortRsFailure{} +} + +// WithPayload adds the payload to the put vs vip port rs failure response +func (o *PutVsVipPortRsFailure) WithPayload(payload models.Error) *PutVsVipPortRsFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs failure response +func (o *PutVsVipPortRsFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_urlbuilder.go new file mode 100644 index 000000000..d906fae36 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// PutVsVipPortRsURL generates an URL for the put vs vip port rs operation +type PutVsVipPortRsURL struct { + VipPort string + + Healthcheck *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortRsURL) WithBasePath(bp string) *PutVsVipPortRsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortRsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortRsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/rs" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortRsURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var healthcheckQ string + if o.Healthcheck != nil { + healthcheckQ = swag.FormatBool(*o.Healthcheck) + } + if healthcheckQ != "" { + qs.Set("healthcheck", healthcheckQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortRsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortRsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortRsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortRsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortRsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortRsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go new file mode 100644 index 000000000..01adfb16c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutVsVipPortURL generates an URL for the put vs vip port operation +type PutVsVipPortURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortURL) WithBasePath(bp string) *PutVsVipPortURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/server.go b/tools/dpvs-agent/restapi/server.go new file mode 100644 index 000000000..2c8225403 --- /dev/null +++ b/tools/dpvs-agent/restapi/server.go @@ -0,0 +1,507 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package restapi + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "log" + "net" + "net/http" + "os" + "os/signal" + "strconv" + "sync" + "sync/atomic" + "syscall" + "time" + + "github.com/go-openapi/runtime/flagext" + "github.com/go-openapi/swag" + flags "github.com/jessevdk/go-flags" + "golang.org/x/net/netutil" + + "github.com/dpvs-agent/restapi/operations" +) + +const ( + schemeHTTP = "http" + schemeHTTPS = "https" + schemeUnix = "unix" +) + +var defaultSchemes []string + +func init() { + defaultSchemes = []string{ + schemeHTTP, + } +} + +// NewServer creates a new api dpvs agent server but does not configure it +func NewServer(api *operations.DpvsAgentAPI) *Server { + s := new(Server) + + s.shutdown = make(chan struct{}) + s.api = api + s.interrupt = make(chan os.Signal, 1) + return s +} + +// ConfigureAPI configures the API and handlers. +func (s *Server) ConfigureAPI() { + if s.api != nil { + s.handler = configureAPI(s.api) + } +} + +// ConfigureFlags configures the additional flags defined by the handlers. Needs to be called before the parser.Parse +func (s *Server) ConfigureFlags() { + if s.api != nil { + configureFlags(s.api) + } +} + +// Server for the dpvs agent API +type Server struct { + EnabledListeners []string `long:"scheme" description:"the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec"` + CleanupTimeout time.Duration `long:"cleanup-timeout" description:"grace period for which to wait before killing idle connections" default:"10s"` + GracefulTimeout time.Duration `long:"graceful-timeout" description:"grace period for which to wait before shutting down the server" default:"15s"` + MaxHeaderSize flagext.ByteSize `long:"max-header-size" description:"controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body." default:"1MiB"` + + SocketPath flags.Filename `long:"socket-path" description:"the unix socket to listen on" default:"/var/run/dpvs-agent.sock"` + domainSocketL net.Listener + + Host string `long:"host" description:"the IP to listen on" default:"localhost" env:"HOST"` + Port int `long:"port" description:"the port to listen on for insecure connections, defaults to a random value" env:"PORT"` + ListenLimit int `long:"listen-limit" description:"limit the number of outstanding requests"` + KeepAlive time.Duration `long:"keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)" default:"3m"` + ReadTimeout time.Duration `long:"read-timeout" description:"maximum duration before timing out read of the request" default:"30s"` + WriteTimeout time.Duration `long:"write-timeout" description:"maximum duration before timing out write of the response" default:"60s"` + httpServerL net.Listener + + TLSHost string `long:"tls-host" description:"the IP to listen on for tls, when not specified it's the same as --host" env:"TLS_HOST"` + TLSPort int `long:"tls-port" description:"the port to listen on for secure connections, defaults to a random value" env:"TLS_PORT"` + TLSCertificate flags.Filename `long:"tls-certificate" description:"the certificate to use for secure connections" env:"TLS_CERTIFICATE"` + TLSCertificateKey flags.Filename `long:"tls-key" description:"the private key to use for secure connections" env:"TLS_PRIVATE_KEY"` + TLSCACertificate flags.Filename `long:"tls-ca" description:"the certificate authority file to be used with mutual tls auth" env:"TLS_CA_CERTIFICATE"` + TLSListenLimit int `long:"tls-listen-limit" description:"limit the number of outstanding requests"` + TLSKeepAlive time.Duration `long:"tls-keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)"` + TLSReadTimeout time.Duration `long:"tls-read-timeout" description:"maximum duration before timing out read of the request"` + TLSWriteTimeout time.Duration `long:"tls-write-timeout" description:"maximum duration before timing out write of the response"` + httpsServerL net.Listener + + api *operations.DpvsAgentAPI + handler http.Handler + hasListeners bool + shutdown chan struct{} + shuttingDown int32 + interrupted bool + interrupt chan os.Signal +} + +// Logf logs message either via defined user logger or via system one if no user logger is defined. +func (s *Server) Logf(f string, args ...interface{}) { + if s.api != nil && s.api.Logger != nil { + s.api.Logger(f, args...) + } else { + log.Printf(f, args...) + } +} + +// Fatalf logs message either via defined user logger or via system one if no user logger is defined. +// Exits with non-zero status after printing +func (s *Server) Fatalf(f string, args ...interface{}) { + if s.api != nil && s.api.Logger != nil { + s.api.Logger(f, args...) + os.Exit(1) + } else { + log.Fatalf(f, args...) + } +} + +// SetAPI configures the server with the specified API. Needs to be called before Serve +func (s *Server) SetAPI(api *operations.DpvsAgentAPI) { + if api == nil { + s.api = nil + s.handler = nil + return + } + + s.api = api + s.handler = configureAPI(api) +} + +func (s *Server) hasScheme(scheme string) bool { + schemes := s.EnabledListeners + if len(schemes) == 0 { + schemes = defaultSchemes + } + + for _, v := range schemes { + if v == scheme { + return true + } + } + return false +} + +// Serve the api +func (s *Server) Serve() (err error) { + if !s.hasListeners { + if err = s.Listen(); err != nil { + return err + } + } + + // set default handler, if none is set + if s.handler == nil { + if s.api == nil { + return errors.New("can't create the default handler, as no api is set") + } + + s.SetHandler(s.api.Serve(nil)) + } + + wg := new(sync.WaitGroup) + once := new(sync.Once) + signalNotify(s.interrupt) + go handleInterrupt(once, s) + + servers := []*http.Server{} + + if s.hasScheme(schemeUnix) { + domainSocket := new(http.Server) + domainSocket.MaxHeaderBytes = int(s.MaxHeaderSize) + domainSocket.Handler = s.handler + if int64(s.CleanupTimeout) > 0 { + domainSocket.IdleTimeout = s.CleanupTimeout + } + + configureServer(domainSocket, "unix", string(s.SocketPath)) + + servers = append(servers, domainSocket) + wg.Add(1) + s.Logf("Serving dpvs agent at unix://%s", s.SocketPath) + go func(l net.Listener) { + defer wg.Done() + if err := domainSocket.Serve(l); err != nil && err != http.ErrServerClosed { + s.Fatalf("%v", err) + } + s.Logf("Stopped serving dpvs agent at unix://%s", s.SocketPath) + }(s.domainSocketL) + } + + if s.hasScheme(schemeHTTP) { + httpServer := new(http.Server) + httpServer.MaxHeaderBytes = int(s.MaxHeaderSize) + httpServer.ReadTimeout = s.ReadTimeout + httpServer.WriteTimeout = s.WriteTimeout + httpServer.SetKeepAlivesEnabled(int64(s.KeepAlive) > 0) + if s.ListenLimit > 0 { + s.httpServerL = netutil.LimitListener(s.httpServerL, s.ListenLimit) + } + + if int64(s.CleanupTimeout) > 0 { + httpServer.IdleTimeout = s.CleanupTimeout + } + + httpServer.Handler = s.handler + + configureServer(httpServer, "http", s.httpServerL.Addr().String()) + + servers = append(servers, httpServer) + wg.Add(1) + s.Logf("Serving dpvs agent at http://%s", s.httpServerL.Addr()) + go func(l net.Listener) { + defer wg.Done() + if err := httpServer.Serve(l); err != nil && err != http.ErrServerClosed { + s.Fatalf("%v", err) + } + s.Logf("Stopped serving dpvs agent at http://%s", l.Addr()) + }(s.httpServerL) + } + + if s.hasScheme(schemeHTTPS) { + httpsServer := new(http.Server) + httpsServer.MaxHeaderBytes = int(s.MaxHeaderSize) + httpsServer.ReadTimeout = s.TLSReadTimeout + httpsServer.WriteTimeout = s.TLSWriteTimeout + httpsServer.SetKeepAlivesEnabled(int64(s.TLSKeepAlive) > 0) + if s.TLSListenLimit > 0 { + s.httpsServerL = netutil.LimitListener(s.httpsServerL, s.TLSListenLimit) + } + if int64(s.CleanupTimeout) > 0 { + httpsServer.IdleTimeout = s.CleanupTimeout + } + httpsServer.Handler = s.handler + + // Inspired by https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go + httpsServer.TLSConfig = &tls.Config{ + // Causes servers to use Go's default ciphersuite preferences, + // which are tuned to avoid attacks. Does nothing on clients. + PreferServerCipherSuites: true, + // Only use curves which have assembly implementations + // https://github.com/golang/go/tree/master/src/crypto/elliptic + CurvePreferences: []tls.CurveID{tls.CurveP256}, + // Use modern tls mode https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility + NextProtos: []string{"h2", "http/1.1"}, + // https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols + MinVersion: tls.VersionTLS12, + // These ciphersuites support Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy + CipherSuites: []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + } + + // build standard config from server options + if s.TLSCertificate != "" && s.TLSCertificateKey != "" { + httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1) + httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(string(s.TLSCertificate), string(s.TLSCertificateKey)) + if err != nil { + return err + } + } + + if s.TLSCACertificate != "" { + // include specified CA certificate + caCert, caCertErr := os.ReadFile(string(s.TLSCACertificate)) + if caCertErr != nil { + return caCertErr + } + caCertPool := x509.NewCertPool() + ok := caCertPool.AppendCertsFromPEM(caCert) + if !ok { + return fmt.Errorf("cannot parse CA certificate") + } + httpsServer.TLSConfig.ClientCAs = caCertPool + httpsServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert + } + + // call custom TLS configurator + configureTLS(httpsServer.TLSConfig) + + if len(httpsServer.TLSConfig.Certificates) == 0 && httpsServer.TLSConfig.GetCertificate == nil { + // after standard and custom config are passed, this ends up with no certificate + if s.TLSCertificate == "" { + if s.TLSCertificateKey == "" { + s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified") + } + s.Fatalf("the required flag `--tls-certificate` was not specified") + } + if s.TLSCertificateKey == "" { + s.Fatalf("the required flag `--tls-key` was not specified") + } + // this happens with a wrong custom TLS configurator + s.Fatalf("no certificate was configured for TLS") + } + + configureServer(httpsServer, "https", s.httpsServerL.Addr().String()) + + servers = append(servers, httpsServer) + wg.Add(1) + s.Logf("Serving dpvs agent at https://%s", s.httpsServerL.Addr()) + go func(l net.Listener) { + defer wg.Done() + if err := httpsServer.Serve(l); err != nil && err != http.ErrServerClosed { + s.Fatalf("%v", err) + } + s.Logf("Stopped serving dpvs agent at https://%s", l.Addr()) + }(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig)) + } + + wg.Add(1) + go s.handleShutdown(wg, &servers) + + wg.Wait() + return nil +} + +// Listen creates the listeners for the server +func (s *Server) Listen() error { + if s.hasListeners { // already done this + return nil + } + + if s.hasScheme(schemeHTTPS) { + // Use http host if https host wasn't defined + if s.TLSHost == "" { + s.TLSHost = s.Host + } + // Use http listen limit if https listen limit wasn't defined + if s.TLSListenLimit == 0 { + s.TLSListenLimit = s.ListenLimit + } + // Use http tcp keep alive if https tcp keep alive wasn't defined + if int64(s.TLSKeepAlive) == 0 { + s.TLSKeepAlive = s.KeepAlive + } + // Use http read timeout if https read timeout wasn't defined + if int64(s.TLSReadTimeout) == 0 { + s.TLSReadTimeout = s.ReadTimeout + } + // Use http write timeout if https write timeout wasn't defined + if int64(s.TLSWriteTimeout) == 0 { + s.TLSWriteTimeout = s.WriteTimeout + } + } + + if s.hasScheme(schemeUnix) { + domSockListener, err := net.Listen("unix", string(s.SocketPath)) + if err != nil { + return err + } + s.domainSocketL = domSockListener + } + + if s.hasScheme(schemeHTTP) { + listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port))) + if err != nil { + return err + } + + h, p, err := swag.SplitHostPort(listener.Addr().String()) + if err != nil { + return err + } + s.Host = h + s.Port = p + s.httpServerL = listener + } + + if s.hasScheme(schemeHTTPS) { + tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.TLSHost, strconv.Itoa(s.TLSPort))) + if err != nil { + return err + } + + sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String()) + if err != nil { + return err + } + s.TLSHost = sh + s.TLSPort = sp + s.httpsServerL = tlsListener + } + + s.hasListeners = true + return nil +} + +// Shutdown server and clean up resources +func (s *Server) Shutdown() error { + if atomic.CompareAndSwapInt32(&s.shuttingDown, 0, 1) { + close(s.shutdown) + } + return nil +} + +func (s *Server) handleShutdown(wg *sync.WaitGroup, serversPtr *[]*http.Server) { + // wg.Done must occur last, after s.api.ServerShutdown() + // (to preserve old behaviour) + defer wg.Done() + + <-s.shutdown + + servers := *serversPtr + + ctx, cancel := context.WithTimeout(context.TODO(), s.GracefulTimeout) + defer cancel() + + // first execute the pre-shutdown hook + s.api.PreServerShutdown() + + shutdownChan := make(chan bool) + for i := range servers { + server := servers[i] + go func() { + var success bool + defer func() { + shutdownChan <- success + }() + if err := server.Shutdown(ctx); err != nil { + // Error from closing listeners, or context timeout: + s.Logf("HTTP server Shutdown: %v", err) + } else { + success = true + } + }() + } + + // Wait until all listeners have successfully shut down before calling ServerShutdown + success := true + for range servers { + success = success && <-shutdownChan + } + if success { + s.api.ServerShutdown() + } +} + +// GetHandler returns a handler useful for testing +func (s *Server) GetHandler() http.Handler { + return s.handler +} + +// SetHandler allows for setting a http handler on this server +func (s *Server) SetHandler(handler http.Handler) { + s.handler = handler +} + +// UnixListener returns the domain socket listener +func (s *Server) UnixListener() (net.Listener, error) { + if !s.hasListeners { + if err := s.Listen(); err != nil { + return nil, err + } + } + return s.domainSocketL, nil +} + +// HTTPListener returns the http listener +func (s *Server) HTTPListener() (net.Listener, error) { + if !s.hasListeners { + if err := s.Listen(); err != nil { + return nil, err + } + } + return s.httpServerL, nil +} + +// TLSListener returns the https listener +func (s *Server) TLSListener() (net.Listener, error) { + if !s.hasListeners { + if err := s.Listen(); err != nil { + return nil, err + } + } + return s.httpsServerL, nil +} + +func handleInterrupt(once *sync.Once, s *Server) { + once.Do(func() { + for range s.interrupt { + if s.interrupted { + s.Logf("Server already shutting down") + continue + } + s.interrupted = true + s.Logf("Shutting down... ") + if err := s.Shutdown(); err != nil { + s.Logf("HTTP server Shutdown: %v", err) + } + } + }) +} + +func signalNotify(interrupt chan<- os.Signal) { + signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) +} From 6652d7e94914e49abf30c45fecb2846a851a1a69 Mon Sep 17 00:00:00 2001 From: wencyu Date: Mon, 10 Jul 2023 19:03:44 +0800 Subject: [PATCH 043/105] keepalived: fix vs protocol config change doesn't take effect problem introduced by last commit --- tools/keepalived/keepalived/check/ipwrapper.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/keepalived/keepalived/check/ipwrapper.c b/tools/keepalived/keepalived/check/ipwrapper.c index 0a3ff916d..ea6c80b17 100755 --- a/tools/keepalived/keepalived/check/ipwrapper.c +++ b/tools/keepalived/keepalived/check/ipwrapper.c @@ -47,7 +47,8 @@ vs_iseq(const virtual_server_t *vs_a, const virtual_server_t *vs_b) /* Should we check the vsg entries match? */ if (inet_sockaddrport(&vs_a->addr) != inet_sockaddrport(&vs_b->addr)) return false; - + if (vs_a->service_type != vs_b->service_type) + return false; return !strcmp(vs_a->vsgname, vs_b->vsgname); } else if (vs_a->af != vs_b->af) return false; @@ -1613,4 +1614,4 @@ clear_tunnels(void) LIST_FOREACH(check_data->tunnel_group, group, e) { clear_tunnel_group(group); } -} \ No newline at end of file +} From c199d06b0903d45ebdefd4a63b9197d0e875fdd6 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Tue, 11 Jul 2023 11:39:14 +0800 Subject: [PATCH 044/105] building dpvs-agent --- tools/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/Makefile b/tools/Makefile index 832a568d1..72bffcc75 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -22,6 +22,7 @@ SUBDIRS = keepalived ipvsadm dpip ifeq ($(CONFIG_DPVS_AGENT), y) SUBDIRS += healthcheck +SUBDIRS += dpvs-agent endif all: config @@ -48,4 +49,5 @@ install: install -m 744 dpip/build/dpip $(INSDIR)/dpip ifeq ($(CONFIG_DPVS_AGENT), y) install -m 744 healthcheck/healthcheck $(INSDIR)/healthcheck + install -m 744 dpvs-agent/cmd/dpvs-agent-server/dpvs-agent $(INSDIR)/dpvs-agent endif From a06f9bc1832bd07d3454c9fec1a8346ad957cee4 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Tue, 11 Jul 2023 13:36:03 +0800 Subject: [PATCH 045/105] add license --- tools/dpvs-agent/Makefile | 1 + .../cmd/device/delete_device_name_addr.go | 14 + .../cmd/device/delete_device_name_netlink.go | 14 + .../device/delete_device_name_netlink_addr.go | 14 + .../cmd/device/delete_device_name_route.go | 14 + .../cmd/device/delete_device_name_vlan.go | 14 + .../cmd/device/get_device_name_nic.go | 14 + tools/dpvs-agent/cmd/device/ioctl.go | 14 + .../cmd/device/put_device_name_addr.go | 14 + .../cmd/device/put_device_name_netlink.go | 14 + .../device/put_device_name_netlink_addr.go | 14 + .../cmd/device/put_device_name_nic.go | 14 + .../cmd/device/put_device_name_route.go | 14 + .../cmd/device/put_device_name_vlan.go | 14 + .../device/todo_delete_device_name_linux.go | 14 + .../todo_delete_device_name_linux_addr.go | 14 + .../dpvs-agent/cmd/device/todo_get_device.go | 14 + .../cmd/device/todo_get_device_name_addr.go | 14 + .../cmd/device/todo_get_device_name_linux.go | 14 + .../device/todo_get_device_name_linux_addr.go | 14 + .../cmd/device/todo_get_device_name_route.go | 14 + .../cmd/device/todo_get_device_name_vlan.go | 14 + .../cmd/device/todo_put_device_name_linux.go | 14 + .../device/todo_put_device_name_linux_addr.go | 14 + .../cmd/dpvs-agent-server/api_init.go | 14 + .../dpvs-agent/cmd/ipvs/delete_vs_vip_port.go | 14 + .../cmd/ipvs/delete_vs_vip_port_allow.go | 14 + .../cmd/ipvs/delete_vs_vip_port_deny.go | 14 + .../cmd/ipvs/delete_vs_vip_port_laddr.go | 14 + .../cmd/ipvs/delete_vs_vip_port_rs.go | 14 + tools/dpvs-agent/cmd/ipvs/get_vs.go | 14 + tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go | 14 + .../cmd/ipvs/get_vs_vip_port_laddr.go | 14 + .../cmd/ipvs/post_vs_vip_port_rs.go | 14 + tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go | 14 + .../cmd/ipvs/put_vs_vip_port_allow.go | 14 + .../cmd/ipvs/put_vs_vip_port_deny.go | 14 + .../cmd/ipvs/put_vs_vip_port_laddr.go | 14 + .../dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go | 14 + .../cmd/ipvs/todo_get_vs_vip_port_rs.go | 14 + tools/dpvs-agent/dpvs-agent-api.yaml | 14 + tools/dpvs-agent/license.txt | 13 + tools/dpvs-agent/pkg/ipc/pool/conn.go | 14 + tools/dpvs-agent/pkg/ipc/pool/pool.go | 14 + tools/dpvs-agent/pkg/ipc/pool/util.go | 14 + tools/dpvs-agent/pkg/ipc/proto/reader.go | 283 +----------------- tools/dpvs-agent/pkg/ipc/proto/writer.go | 14 + tools/dpvs-agent/pkg/ipc/types/certificate.go | 14 + tools/dpvs-agent/pkg/ipc/types/const.go | 14 + tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go | 14 + tools/dpvs-agent/pkg/ipc/types/dpvsstats.go | 14 + tools/dpvs-agent/pkg/ipc/types/getmodel.go | 14 + tools/dpvs-agent/pkg/ipc/types/inetaddr.go | 14 + tools/dpvs-agent/pkg/ipc/types/iprange.go | 14 + tools/dpvs-agent/pkg/ipc/types/kni.go | 14 + tools/dpvs-agent/pkg/ipc/types/laddr.go | 14 + tools/dpvs-agent/pkg/ipc/types/method.go | 14 + tools/dpvs-agent/pkg/ipc/types/netif.go | 14 + tools/dpvs-agent/pkg/ipc/types/realserver.go | 14 + tools/dpvs-agent/pkg/ipc/types/route.go | 14 + tools/dpvs-agent/pkg/ipc/types/sockmsg.go | 14 + tools/dpvs-agent/pkg/ipc/types/utility.go | 14 + .../dpvs-agent/pkg/ipc/types/virtualserver.go | 14 + tools/dpvs-agent/pkg/ipc/types/vlan.go | 14 + .../restapi/configure_dpvs_agent.go | 14 + 65 files changed, 896 insertions(+), 269 deletions(-) create mode 100644 tools/dpvs-agent/license.txt diff --git a/tools/dpvs-agent/Makefile b/tools/dpvs-agent/Makefile index fb8e5ff18..e6d192824 100644 --- a/tools/dpvs-agent/Makefile +++ b/tools/dpvs-agent/Makefile @@ -30,3 +30,4 @@ ifeq ($(shell addlicense 2>&1|grep Usage),) $(error "`addlicense` command not found. You can install it with `go install github.com/google/addlicense`") endif @addlicense -check -c "IQiYi Inc." -l apache -ignore dpvs/** . || /bin/true + -addlicense -f license.txt -v . diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_addr.go b/tools/dpvs-agent/cmd/device/delete_device_name_addr.go index 68635af05..716d47718 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_addr.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go b/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go index d4fd6ba54..0bc24ef08 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go b/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go index 0ed8b943e..35eb17ef7 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_route.go b/tools/dpvs-agent/cmd/device/delete_device_name_route.go index eabc0f976..74d5b5254 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_route.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_route.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go b/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go index abd2e5620..0144c0ea9 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/get_device_name_nic.go b/tools/dpvs-agent/cmd/device/get_device_name_nic.go index 2cedd92a2..6d35e45cd 100644 --- a/tools/dpvs-agent/cmd/device/get_device_name_nic.go +++ b/tools/dpvs-agent/cmd/device/get_device_name_nic.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/ioctl.go b/tools/dpvs-agent/cmd/device/ioctl.go index ab3297857..5511c47ba 100644 --- a/tools/dpvs-agent/cmd/device/ioctl.go +++ b/tools/dpvs-agent/cmd/device/ioctl.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_addr.go b/tools/dpvs-agent/cmd/device/put_device_name_addr.go index 03cd75c82..275e33100 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_addr.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_netlink.go b/tools/dpvs-agent/cmd/device/put_device_name_netlink.go index 1a643647c..be683f8db 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_netlink.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_netlink.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go b/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go index a114ba8fe..1b093b431 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_nic.go b/tools/dpvs-agent/cmd/device/put_device_name_nic.go index 419026058..695381a91 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_nic.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_nic.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_route.go b/tools/dpvs-agent/cmd/device/put_device_name_route.go index d9ddea942..14bbb92d3 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_route.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_route.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_vlan.go b/tools/dpvs-agent/cmd/device/put_device_name_vlan.go index 4ec011bd7..c3d8098e5 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_vlan.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_vlan.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go index 9e8771521..6032a7945 100644 --- a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go +++ b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device /* diff --git a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go index ce1c644e4..bc1ff5230 100644 --- a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go +++ b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device /* diff --git a/tools/dpvs-agent/cmd/device/todo_get_device.go b/tools/dpvs-agent/cmd/device/todo_get_device.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go index a1f95a889..34972bb0c 100644 --- a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go +++ b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device // http://blog.pytool.com/language/clang/socket/linux-socket-ifreq/ diff --git a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go index b56f455b6..976e708c9 100644 --- a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go +++ b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device /* diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go index f4d5393e9..c9b885685 100644 --- a/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go index f9c4a645c..280827cee 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go index 0d8678f2b..f1e068e5d 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go index 1352386d8..54d2bb9d2 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go index 4780c7424..ec1cb9bd8 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go index 222635645..8870fdd7f 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs.go b/tools/dpvs-agent/cmd/ipvs/get_vs.go index a6d8c1025..700931f75 100644 --- a/tools/dpvs-agent/cmd/ipvs/get_vs.go +++ b/tools/dpvs-agent/cmd/ipvs/get_vs.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go index 873e6d533..c9f907876 100644 --- a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go index adac60936..b8754eb84 100644 --- a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go +++ b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go index 4f577cca0..76520bc12 100644 --- a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go index c6c09f285..1b3fc1997 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go index dabcc000b..a5ff5753a 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go index 984dff17a..632b563f6 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go index 6551abea3..d8765ba6d 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go index 05380108c..a472be1e7 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go index 91ce6808a..2a5d23eaf 100644 --- a/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml index 230751c80..ac8487bef 100644 --- a/tools/dpvs-agent/dpvs-agent-api.yaml +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 IQiYi Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + swagger: "2.0" info: description: "dpvs agent api" diff --git a/tools/dpvs-agent/license.txt b/tools/dpvs-agent/license.txt new file mode 100644 index 000000000..d61a47c47 --- /dev/null +++ b/tools/dpvs-agent/license.txt @@ -0,0 +1,13 @@ +Copyright 2023 IQiYi Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/tools/dpvs-agent/pkg/ipc/pool/conn.go b/tools/dpvs-agent/pkg/ipc/pool/conn.go index 6f7034653..721eb113c 100644 --- a/tools/dpvs-agent/pkg/ipc/pool/conn.go +++ b/tools/dpvs-agent/pkg/ipc/pool/conn.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pool import ( diff --git a/tools/dpvs-agent/pkg/ipc/pool/pool.go b/tools/dpvs-agent/pkg/ipc/pool/pool.go index c88d9d82d..0f19b4bed 100644 --- a/tools/dpvs-agent/pkg/ipc/pool/pool.go +++ b/tools/dpvs-agent/pkg/ipc/pool/pool.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pool import ( diff --git a/tools/dpvs-agent/pkg/ipc/pool/util.go b/tools/dpvs-agent/pkg/ipc/pool/util.go index 3bd67fbed..9b0e4f08c 100644 --- a/tools/dpvs-agent/pkg/ipc/pool/util.go +++ b/tools/dpvs-agent/pkg/ipc/pool/util.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pool import ( diff --git a/tools/dpvs-agent/pkg/ipc/proto/reader.go b/tools/dpvs-agent/pkg/ipc/proto/reader.go index b77dee8d1..6fd670115 100644 --- a/tools/dpvs-agent/pkg/ipc/proto/reader.go +++ b/tools/dpvs-agent/pkg/ipc/proto/reader.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package proto import ( @@ -62,274 +76,5 @@ func (r *Reader) buf(n int) []byte { } func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) { - /* - line, err := r.ReadLine() - - if err != nil { - return nil, err - } - - switch line[0] { - case ErrorReply: - return nil, ParseErrorReply(line) - case StatusReply: - return string(line[1:]), nil - case IntReply: - return util.ParseInt(line[1:], 10, 64) - case StringReply: - return r.readStringReply(line) - case ArrayReply: - n, err := parseArrayLen(line) - if err != nil { - return nil, err - } - if m == nil { - err := fmt.Errorf("dpvs: got %.100q, but multi bulk parser is nil", line) - return nil, err - } - return m(r, n) - } - */ return nil, fmt.Errorf("dpvs read failed") } - -/* -func (r *Reader) ReadLine() ([]byte, error) { - line, err := r.readLine() - if err != nil { - return nil, err - } - if isNilReply(line) { - return nil, Nil - } - return line, nil -} - -// readLine that returns an error if: -// - there is a pending read error; -// - or line does not end with \r\n. -func (r *Reader) readLine() ([]byte, error) { - b, err := r.rd.ReadSlice('\n') - if err != nil { - if err != bufio.ErrBufferFull { - return nil, err - } - - full := make([]byte, len(b)) - copy(full, b) - - b, err = r.rd.ReadBytes('\n') - if err != nil { - return nil, err - } - - full = append(full, b...) - b = full - } - if len(b) <= 2 || b[len(b)-1] != '\n' || b[len(b)-2] != '\r' { - return nil, fmt.Errorf("dpvs: invalid reply: %q", b) - } - return b[:len(b)-2], nil -} - -func (r *Reader) ReadIntReply() (int64, error) { - line, err := r.ReadLine() - if err != nil { - return 0, err - } - switch line[0] { - case ErrorReply: - return 0, ParseErrorReply(line) - case IntReply: - return util.ParseInt(line[1:], 10, 64) - default: - return 0, fmt.Errorf("dpvs: can't parse int reply: %.100q", line) - } -} - -func (r *Reader) ReadString() (string, error) { - line, err := r.ReadLine() - if err != nil { - return "", err - } - switch line[0] { - case ErrorReply: - return "", ParseErrorReply(line) - case StringReply: - return r.readStringReply(line) - case StatusReply: - return string(line[1:]), nil - case IntReply: - return string(line[1:]), nil - default: - return "", fmt.Errorf("dpvs: can't parse reply=%.100q reading string", line) - } -} - -func (r *Reader) readStringReply(line []byte) (string, error) { - if isNilReply(line) { - return "", Nil - } - - replyLen, err := util.Atoi(line[1:]) - if err != nil { - return "", err - } - - b := make([]byte, replyLen+2) - _, err = io.ReadFull(r.rd, b) - if err != nil { - return "", err - } - - return util.BytesToString(b[:replyLen]), nil -} - -func (r *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) { - line, err := r.ReadLine() - if err != nil { - return nil, err - } - switch line[0] { - case ErrorReply: - return nil, ParseErrorReply(line) - case ArrayReply: - n, err := parseArrayLen(line) - if err != nil { - return nil, err - } - return m(r, n) - default: - return nil, fmt.Errorf("dpvs: can't parse array reply: %.100q", line) - } -} - -func (r *Reader) ReadArrayLen() (int, error) { - line, err := r.ReadLine() - if err != nil { - return 0, err - } - switch line[0] { - case ErrorReply: - return 0, ParseErrorReply(line) - case ArrayReply: - n, err := parseArrayLen(line) - if err != nil { - return 0, err - } - return int(n), nil - default: - return 0, fmt.Errorf("dpvs: can't parse array reply: %.100q", line) - } -} -func (r *Reader) ReadScanReply() ([]string, uint64, error) { - n, err := r.ReadArrayLen() - if err != nil { - return nil, 0, err - } - if n != 2 { - return nil, 0, fmt.Errorf("dpvs: got %d elements in scan reply, expected 2", n) - } - - cursor, err := r.ReadUint() - if err != nil { - return nil, 0, err - } - - n, err = r.ReadArrayLen() - if err != nil { - return nil, 0, err - } - - keys := make([]string, n) - - for i := 0; i < n; i++ { - key, err := r.ReadString() - if err != nil { - return nil, 0, err - } - keys[i] = key - } - - return keys, cursor, err -} -*/ -/* -func (r *Reader) ReadInt() (int64, error) { - b, err := r.readTmpBytesReply() - if err != nil { - return 0, err - } - return util.ParseInt(b, 10, 64) -} - -func (r *Reader) ReadUint() (uint64, error) { - b, err := r.readTmpBytesReply() - if err != nil { - return 0, err - } - return util.ParseUint(b, 10, 64) -} - -func (r *Reader) ReadFloatReply() (float64, error) { - b, err := r.readTmpBytesReply() - if err != nil { - return 0, err - } - return util.ParseFloat(b, 64) -} - -func (r *Reader) readTmpBytesReply() ([]byte, error) { - line, err := r.ReadLine() - if err != nil { - return nil, err - } - switch line[0] { - case ErrorReply: - return nil, ParseErrorReply(line) - case StringReply: - return r._readTmpBytesReply(line) - case StatusReply: - return line[1:], nil - default: - return nil, fmt.Errorf("dpvs: can't parse string reply: %.100q", line) - } -} - -func (r *Reader) _readTmpBytesReply(line []byte) ([]byte, error) { - if isNilReply(line) { - return nil, Nil - } - - replyLen, err := util.Atoi(line[1:]) - if err != nil { - return nil, err - } - - buf := r.buf(replyLen + 2) - _, err = io.ReadFull(r.rd, buf) - if err != nil { - return nil, err - } - - return buf[:replyLen], nil -} -*/ -/* -func isNilReply(b []byte) bool { - return len(b) == 3 && - (b[0] == StringReply || b[0] == ArrayReply) && - b[1] == '-' && b[2] == '1' -} - -func ParseErrorReply(line []byte) error { - return DpvsError(string(line[1:])) -} - -func parseArrayLen(line []byte) (int64, error) { - if isNilReply(line) { - return 0, Nil - } - return util.ParseInt(line[1:], 10, 64) -} -*/ diff --git a/tools/dpvs-agent/pkg/ipc/proto/writer.go b/tools/dpvs-agent/pkg/ipc/proto/writer.go index a4aced90d..09dfde88e 100644 --- a/tools/dpvs-agent/pkg/ipc/proto/writer.go +++ b/tools/dpvs-agent/pkg/ipc/proto/writer.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package proto import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/certificate.go b/tools/dpvs-agent/pkg/ipc/types/certificate.go index b0b7b74a4..5f8ea82a5 100644 --- a/tools/dpvs-agent/pkg/ipc/types/certificate.go +++ b/tools/dpvs-agent/pkg/ipc/types/certificate.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/const.go b/tools/dpvs-agent/pkg/ipc/types/const.go index 9cbc3d49a..d210cf83e 100644 --- a/tools/dpvs-agent/pkg/ipc/types/const.go +++ b/tools/dpvs-agent/pkg/ipc/types/const.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go b/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go index 97c180ce7..80d37e20a 100644 --- a/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go +++ b/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types type dpvsMatch struct { diff --git a/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go b/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go index dfd02c1e0..f9c16e3ee 100644 --- a/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go +++ b/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types type dpvsStats struct { diff --git a/tools/dpvs-agent/pkg/ipc/types/getmodel.go b/tools/dpvs-agent/pkg/ipc/types/getmodel.go index 6196594b2..673e4c8ee 100644 --- a/tools/dpvs-agent/pkg/ipc/types/getmodel.go +++ b/tools/dpvs-agent/pkg/ipc/types/getmodel.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/inetaddr.go b/tools/dpvs-agent/pkg/ipc/types/inetaddr.go index 661c31f09..0efb71f9e 100644 --- a/tools/dpvs-agent/pkg/ipc/types/inetaddr.go +++ b/tools/dpvs-agent/pkg/ipc/types/inetaddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/iprange.go b/tools/dpvs-agent/pkg/ipc/types/iprange.go index d35182498..5006f3424 100644 --- a/tools/dpvs-agent/pkg/ipc/types/iprange.go +++ b/tools/dpvs-agent/pkg/ipc/types/iprange.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types type ipRange struct { diff --git a/tools/dpvs-agent/pkg/ipc/types/kni.go b/tools/dpvs-agent/pkg/ipc/types/kni.go index afa2d0cff..2107464be 100644 --- a/tools/dpvs-agent/pkg/ipc/types/kni.go +++ b/tools/dpvs-agent/pkg/ipc/types/kni.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/laddr.go b/tools/dpvs-agent/pkg/ipc/types/laddr.go index 7e16f8763..ed26f5069 100644 --- a/tools/dpvs-agent/pkg/ipc/types/laddr.go +++ b/tools/dpvs-agent/pkg/ipc/types/laddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/method.go b/tools/dpvs-agent/pkg/ipc/types/method.go index ab1254f4c..2a73a0973 100644 --- a/tools/dpvs-agent/pkg/ipc/types/method.go +++ b/tools/dpvs-agent/pkg/ipc/types/method.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types diff --git a/tools/dpvs-agent/pkg/ipc/types/netif.go b/tools/dpvs-agent/pkg/ipc/types/netif.go index f403ebb03..4e7cccbac 100644 --- a/tools/dpvs-agent/pkg/ipc/types/netif.go +++ b/tools/dpvs-agent/pkg/ipc/types/netif.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/realserver.go b/tools/dpvs-agent/pkg/ipc/types/realserver.go index bd56a7eb6..1f7a36839 100644 --- a/tools/dpvs-agent/pkg/ipc/types/realserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/realserver.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/route.go b/tools/dpvs-agent/pkg/ipc/types/route.go index e428ff621..052df52c8 100644 --- a/tools/dpvs-agent/pkg/ipc/types/route.go +++ b/tools/dpvs-agent/pkg/ipc/types/route.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/sockmsg.go b/tools/dpvs-agent/pkg/ipc/types/sockmsg.go index 3db2543e5..8e889e0e9 100644 --- a/tools/dpvs-agent/pkg/ipc/types/sockmsg.go +++ b/tools/dpvs-agent/pkg/ipc/types/sockmsg.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/utility.go b/tools/dpvs-agent/pkg/ipc/types/utility.go index d887d9a19..d034883e5 100644 --- a/tools/dpvs-agent/pkg/ipc/types/utility.go +++ b/tools/dpvs-agent/pkg/ipc/types/utility.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import "strings" diff --git a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go index bb7cc409d..ca4e28e21 100644 --- a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/vlan.go b/tools/dpvs-agent/pkg/ipc/types/vlan.go index ece83c0ef..47a0417e9 100644 --- a/tools/dpvs-agent/pkg/ipc/types/vlan.go +++ b/tools/dpvs-agent/pkg/ipc/types/vlan.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/restapi/configure_dpvs_agent.go b/tools/dpvs-agent/restapi/configure_dpvs_agent.go index f37abf18a..6875fef90 100644 --- a/tools/dpvs-agent/restapi/configure_dpvs_agent.go +++ b/tools/dpvs-agent/restapi/configure_dpvs_agent.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // This file is safe to edit. Once it exists it will not be overwritten package restapi From 9e6ee30f8cde22780d41d92dc7a85b769bd6e09e Mon Sep 17 00:00:00 2001 From: huangyichen Date: Wed, 12 Jul 2023 20:48:18 +0800 Subject: [PATCH 046/105] update readme --- tools/dpvs-agent/README.md | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/tools/dpvs-agent/README.md b/tools/dpvs-agent/README.md index 0c25a01d1..23439e0a1 100644 --- a/tools/dpvs-agent/README.md +++ b/tools/dpvs-agent/README.md @@ -1,4 +1,38 @@ -#build +##setup a dpvs virtual service + +- set dpdk device (dpip vlan add dpdk0.102 link dpdk0 id 102) ``` -swagger generate server -A dpvs-agent -f ./dpvs-agent-api.yaml +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/vlan" -H "Content-type:application/json" -d "{\"device\":\"dpdk0\", \"id\":\"102\"}" +``` + +- set linux device up (ip link set dpdk0.102.kni up) +``` +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink" +``` +- add virtual service (ipvsadm -At 192.168.177.130:80 -s wrr) +``` +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp" -H "Content-type:application/json" -d "{\"SchedName\":\"wrr\"}" +``` + +- add vip to dpdk device (dpip addr add 192.168.77.130 dev dpdk0.102) +``` +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.177.130\"}" +``` + +- add vip to kni device (ip addr add 192.168.177.130 dev dpdk0.102.kni) +``` +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.177.130\"}" + +- set laddr of service (ipvsadm --add-laddr -z 192.168.188.247 -t 192.168.177.130:80 -F dpdk0.102) +``` +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.188.247\"}" +``` +- set laddr to device (dpip addr add 192.168.188.247/32 dev dpdk0.102) +``` +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.188.247\"}" +``` + +- add rss to service (ipvsadm -at 192.168.177.130:80 -r 192.168.188.101:80 -b) +``` +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"192.168.188.101\", \"port\":80, \"weight\":101}]}" ``` From d31fbabf4ba16024a43a0132c22ab29a7028ad47 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Wed, 12 Jul 2023 20:49:18 +0800 Subject: [PATCH 047/105] standardization logfmt --- tools/dpvs-agent/pkg/ipc/types/realserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dpvs-agent/pkg/ipc/types/realserver.go b/tools/dpvs-agent/pkg/ipc/types/realserver.go index 1f7a36839..3ecb8a4a1 100644 --- a/tools/dpvs-agent/pkg/ipc/types/realserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/realserver.go @@ -642,6 +642,6 @@ func (front *RealServerFront) Update(rss []*RealServerSpec, cp *pool.ConnPool, p errCode := front.Del(unreserved, cp, logger) result := errCode.String() - logger.Info("Set", "rss", rss, "Done", "result", result) + logger.Info("Set real servers done", "rss", rss, "result", result) return errCode } From 7f5b69e44ae40932dbb459ad2ffb7c9b7eee2a3d Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 27 Jun 2023 18:51:56 +0800 Subject: [PATCH 048/105] tools: add healthcheck tool and config.mk Signed-off-by: ywc689 --- .github/workflows/build.yaml | 4 +- Makefile | 6 + config.mk | 33 +++ doc/Worker-Performance-Tuning.md | 2 +- doc/tutorial.md | 2 +- scripts/dpvs_log_rotate.sh | 138 ++++++++++ src/Makefile | 4 +- src/config.mk | 128 ++++++--- tools/Makefile | 7 + tools/healthcheck/.gitignore | 3 + tools/healthcheck/Makefile | 22 ++ tools/healthcheck/go.mod | 10 + tools/healthcheck/go.sum | 6 + tools/healthcheck/license.txt | 13 + tools/healthcheck/main.go | 103 +++++++ tools/healthcheck/pkg/helthcheck/checker.go | 252 ++++++++++++++++++ tools/healthcheck/pkg/helthcheck/configs.go | 94 +++++++ .../pkg/helthcheck/ping_checker.go | 203 ++++++++++++++ .../pkg/helthcheck/ping_checker_test.go | 45 ++++ tools/healthcheck/pkg/helthcheck/server.go | 248 +++++++++++++++++ .../healthcheck/pkg/helthcheck/tcp_checker.go | 122 +++++++++ .../pkg/helthcheck/test/tcp_checker.go | 130 +++++++++ .../pkg/helthcheck/test/udp_checker.go | 119 +++++++++ tools/healthcheck/pkg/helthcheck/types.go | 225 ++++++++++++++++ .../healthcheck/pkg/helthcheck/udp_checker.go | 108 ++++++++ tools/healthcheck/pkg/lb/dpvs_agent.go | 228 ++++++++++++++++ tools/healthcheck/pkg/lb/dpvs_agent_test.go | 49 ++++ tools/healthcheck/pkg/lb/types.go | 65 +++++ tools/healthcheck/pkg/server/server.go | 72 +++++ tools/healthcheck/pkg/utils/net.go | 124 +++++++++ tools/healthcheck/test/README.md | 238 +++++++++++++++++ tools/healthcheck/test/dpvs-agent-api.sh | 31 +++ tools/healthcheck/test/stress-test.sh | 67 +++++ 33 files changed, 2859 insertions(+), 42 deletions(-) create mode 100644 config.mk create mode 100755 scripts/dpvs_log_rotate.sh create mode 100644 tools/healthcheck/.gitignore create mode 100644 tools/healthcheck/Makefile create mode 100644 tools/healthcheck/go.mod create mode 100644 tools/healthcheck/go.sum create mode 100644 tools/healthcheck/license.txt create mode 100644 tools/healthcheck/main.go create mode 100644 tools/healthcheck/pkg/helthcheck/checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/configs.go create mode 100644 tools/healthcheck/pkg/helthcheck/ping_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/ping_checker_test.go create mode 100644 tools/healthcheck/pkg/helthcheck/server.go create mode 100644 tools/healthcheck/pkg/helthcheck/tcp_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/test/tcp_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/test/udp_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/types.go create mode 100644 tools/healthcheck/pkg/helthcheck/udp_checker.go create mode 100644 tools/healthcheck/pkg/lb/dpvs_agent.go create mode 100644 tools/healthcheck/pkg/lb/dpvs_agent_test.go create mode 100644 tools/healthcheck/pkg/lb/types.go create mode 100644 tools/healthcheck/pkg/server/server.go create mode 100644 tools/healthcheck/pkg/utils/net.go create mode 100644 tools/healthcheck/test/README.md create mode 100755 tools/healthcheck/test/dpvs-agent-api.sh create mode 100755 tools/healthcheck/test/stress-test.sh diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 1ac36e39f..360635bb4 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -22,13 +22,13 @@ jobs: - name: make run: make -j - build-debug: + build-all: runs-on: self-hosted env: PKG_CONFIG_PATH: /data/dpdk/dpdklib/lib64/pkgconfig steps: - uses: actions/checkout@v2 - name: config - run: sed -i 's/#CFLAGS +=/CFLAGS +=/' src/config.mk && sed -i 's/^#DEBUG := 1/DEBUG := 1/' src/Makefile + run: sed -i 's/=n$/=y/' config.mk - name: make run: make -j diff --git a/Makefile b/Makefile index 3172b2981..44f214765 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ MAKE = make CC = gcc LD = ld +RM = rm SUBDIRS = src tools @@ -29,6 +30,8 @@ export INSDIR export KERNEL = $(shell /bin/uname -r) +include $(CURDIR)/config.mk + all: for i in $(SUBDIRS); do $(MAKE) -C $$i || exit 1; done @@ -43,3 +46,6 @@ distclean: install:all -mkdir -p $(INSDIR) for i in $(SUBDIRS); do $(MAKE) -C $$i install || exit 1; done + +uninstall: + -$(RM) -f $(TARGET) $(INSDIR)/* diff --git a/config.mk b/config.mk new file mode 100644 index 000000000..5d8648f12 --- /dev/null +++ b/config.mk @@ -0,0 +1,33 @@ +# configs +export CONFIG_DPVS_MAX_SOCKET=2 +export CONFIG_DPVS_MAX_LCORE=64 + +## modules +export CONFIG_DPVS_AGENT=n +export CONFIG_IXGEB_PMD=y +export CONFIG_DPVS_LOG=y +export CONFIG_PDUMP=y +export CONFIG_ICMP_REDIRECT_CORE=n + +# debugging and logging +export CONFIG_DEBUG=n +export CONFIG_DPVS_NEIGH_DEBUG=n +export CONFIG_RECORD_BIG_LOOP=n +export CONFIG_DPVS_SAPOOL_DEBUG=n +export CONFIG_DPVS_IPVS_DEBUG=n +export CONFIG_DPVS_SERVICE_DEBUG=n +export CONFIG_SYNPROXY_DEBUG=n +export CONFIG_TIMER_MEASURE=n +export CONFIG_TIMER_DEBUG=n +export DPVS_CFG_PARSER_DEBUG=n +export NETIF_BONDING_DEBUG=n +export CONFIG_TC_DEBUG=n +export CONFIG_DPVS_IPVS_STATS_DEBUG=n +export CONFIG_DPVS_IP_HEADER_DEBUG=n +export CONFIG_DPVS_MBUF_DEBUG=n +export CONFIG_DPVS_IPSET_DEBUG=n +export CONFIG_NDISC_DEBUG=n +export CONFIG_MSG_DEBUG=n +export CONFIG_DPVS_MP_DEBUG=n +export CONFIG_DPVS_NETIF_DEBUG=n +export CONFIG_DPVS_ICMP_DEBUG=n diff --git a/doc/Worker-Performance-Tuning.md b/doc/Worker-Performance-Tuning.md index 8616e2bf8..acbf892d6 100644 --- a/doc/Worker-Performance-Tuning.md +++ b/doc/Worker-Performance-Tuning.md @@ -30,7 +30,7 @@ In case of the following situations, you should consider this performance tuning * There exists big worker loops. - > To observe worker loop time, you should uncomment the macro "CONFIG_RECORD_BIG_LOOP" in src/config.mk,recompile DPVS program and run it. + > To observe worker loop time, you should set "CONFIG_RECORD_BIG_LOOP=y" in `config.mk`,recompile DPVS program and run it. > > Besides, macros "BIG_LOOP_THRESH_SLAVE" and "BIG_LOOP_THRESH_MASTER" define the threshold time of worker loop. Modify them if needed. diff --git a/doc/tutorial.md b/doc/tutorial.md index 9d5e89323..8ea24dea3 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -1326,7 +1326,7 @@ Firstly, DPVS runs with `WARNING` log level by default. You can change it in `/e Use low level log such as "INFO" or "DEBUG" may help find more clues to your problem. -Secondly, some modules support more detailed debug log only if you enable it when compile DPVS. The supported flags are defined but commented in [src/config.mk](../src/config.mk), some of which are listed below. Uncomment it and recompile DPVS if you need to debug the corresponding module. +Secondly, some modules support more detailed debug log only if you enable it when compile DPVS. The modular debug options are available in [config.mk](../config.mk), some of which are listed below. Change the value to "y" and recompile DPVS if you want to debug a module. ``` - CONFIG_DPVS_IPVS_DEBUG # for ipvs forwarding debug diff --git a/scripts/dpvs_log_rotate.sh b/scripts/dpvs_log_rotate.sh new file mode 100755 index 000000000..6bb38a84e --- /dev/null +++ b/scripts/dpvs_log_rotate.sh @@ -0,0 +1,138 @@ +#!/bin/env bash + +# Set target directory for cleaning +TARGET_DIR="/var/log/healthcheck" + +# Set log file name pattern +LOG_FILENAME_PATTERN="*\.log\.*" + +# Set the maximum usage percentage and the target usage percentage +MAX_USAGE=80 +TARGET_USAGE=40 + +# Set the minimum number of log files to keep +MIN_FILES=12 + +# Set the maximum number of files to delete in one run +MAX_DELETE=10000 + +OPTS=`getopt -o d:p:u:l:K:D:h --long \ +log-directory:,filename-pattern:,disk-usage-high:,\ +disk-usage-low:,min-files-kept:,max-deletions:,help,\ + -n "$0" -- "$@"` +eval set -- "$OPTS" +while true +do + case "$1" in + -d|--log-directory) + TARGET_DIR="$2" + shift 2 + ;; + -p|--filename-pattern) + LOG_FILENAME_PATTERN="$2" + shift 2 + ;; + -u|--disk-usage-high) + MAX_USAGE="$2" + shift 2 + ;; + -l|--disk-usage-low) + TARGET_USAGE="$2" + shift 2 + ;; + -K|--min-files-kept) + MIN_FILES="$2" + shift 2 + ;; + -D|--max-deletions) + MAX_DELETE="$2" + shift 2 + ;; + -h|--help) + echo "[usage] $0 [ OPTS ]" + echo "OPTS:" + echo " -d|--log-directory DIRECTORY" + echo " -p|--filename-pattern REGEXPR" + echo " -u|--disk-usage-high 0-100" + echo " -l|--disk-usage-low 0-100" + echo " -K|--min-files-kept NUM" + echo " -D|--max-deletions NUM" + echo " -h|--help" + exit 0 + ;; + --) + shift + break + ;; + *) + echo "Param Error!" + exit 1 + ;; + esac +done + +NotRecognized=$(for arg do printf "$arg " ; done) +[ ! -z "$NotRecognized" ] && echo "Unrecognized Opts: ${NotRecognized}" && exit 1 + +echo "CONFIGS:" +echo " log-directory: ${TARGET_DIR}" +echo " filename-pattern: ${LOG_FILENAME_PATTERN}" +echo " disk-usage-high: ${MAX_USAGE}" +echo " disk-usage-low: ${TARGET_USAGE}" +echo " min-files-kept: ${MIN_FILES}" +echo " max-deletions: ${MAX_DELETE}" + +[ ! -d ${TARGET_DIR} ] && echo "invalid --log-directory \"${TARGET_DIR}\", not found!" && exit 1 +echo ${MAX_USAGE} | egrep ^[0-9]+$ >/dev/null; [ $? -ne 0 ] && echo "invalid --disk-usage-high" && exit 1 +echo ${TARGET_USAGE} | egrep ^[0-9]+$ >/dev/null; [ $? -ne 0 ] && echo "invalid --disk-usage-low" && exit 1 +echo ${MIN_FILES} | egrep ^[0-9]+$ >/dev/null; [ $? -ne 0 ] && echo "invalid --min-files-kept" && exit 1 +echo ${MAX_DELETE} | egrep ^[0-9]+$ >/dev/null; [ $? -ne 0 ] && echo "invalid --max-deletions" && exit 1 +res=$(echo "${MAX_USAGE} < 100" | bc); [ "$res" -ne 1 ] && echo "--disk-usage-high must less than 100" && exit 1 +res=$(echo "${MAX_USAGE} > ${TARGET_USAGE}" | bc); [ "$res" -ne 1 ] && echo "--disk-usage-high must greater than --disk-usage-low" && exit 1 + +# Get the current disk usage +CURRENT_USAGE=$(df -P ${TARGET_DIR} | awk 'NR==2 {printf "%d", $5}') + +# Initialize a counter for deleted files +DELETED_FILES=0 + +# Start the cleaning process if the disk usage is higher than the defined MAX_USAGE +if [ "${CURRENT_USAGE}" -gt "${MAX_USAGE}" ]; then + echo "Disk usage is ${CURRENT_USAGE}%, starting cleaning process." + + # Find and delete logs until disk usage reaches TARGET_USAGE or MAX_DELETE files are deleted + while [ "${CURRENT_USAGE}" -gt "${TARGET_USAGE}" ] && [ "${DELETED_FILES}" -lt "${MAX_DELETE}" ]; do + # Check the number of log files + NUM_FILES=$(find ${TARGET_DIR} -type f -name ${LOG_FILENAME_PATTERN} | wc -l) + + # Ensure that at least MIN_FILES log files remain + if [ "${NUM_FILES}" -le "${MIN_FILES}" ]; then + echo "Reached minimum number of log files (${MIN_FILES}), aborting." + exit 1 + fi + + # Find the oldest log file + OLDEST_LOG=$(find ${TARGET_DIR} -type f -name ${LOG_FILENAME_PATTERN} -printf '%T+ %p\n' | sort | head -n1 | cut -d' ' -f2) + + echo "Deleting ${OLDEST_LOG}..." + rm -f "${OLDEST_LOG}" + DELETED_FILES=$((DELETED_FILES+1)) + + # Update current disk usage + CURRENT_USAGE=$(df -P ${TARGET_DIR} | awk 'NR==2 {printf "%d", $5}') + done + + if [ "${DELETED_FILES}" -eq "${MAX_DELETE}" ]; then + echo "Reached the maximum number of deletions (${MAX_DELETE}), aborting." + else + echo "Cleaning process completed. Disk usage is now ${CURRENT_USAGE}%." + fi + +else + echo "Disk usage is ${CURRENT_USAGE}%, no cleaning needed." +fi + +echo "Remaining Files in ${TARGET_DIR} (only show 30 entries):" +ls -lh ${TARGET_DIR} | head -n 30 + +exit 0 diff --git a/src/Makefile b/src/Makefile index b546a0d67..82e75030d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,8 +19,6 @@ # Makefile for dpvs (DPVS main program). # -#DEBUG := 1 # enable for debug - TARGET := dpvs ifneq ("$(wildcard VERSION)","") @@ -59,7 +57,7 @@ ifeq ($(shell test $(GCC_VERSION) -ge 70 && echo 1), 1) CFLAGS += -Wstringop-overflow=0 endif -ifeq ($(DEBUG),) +ifneq ($(CONFIG_DEBUG), y) CFLAGS += -O3 else CFLAGS += -g -O0 -D DEBUG diff --git a/src/config.mk b/src/config.mk index 78fb68ba4..2a1ef13dc 100644 --- a/src/config.mk +++ b/src/config.mk @@ -15,52 +15,110 @@ # GNU General Public License for more details. # -# -# enable as needed. -# -# TODO: use standard way to define compile flags. -# - -CONFIG_IXGEB_PMD=y -CONFIG_PDUMP=y +CFLAGS += -D DPVS_MAX_SOCKET=$(CONFIG_DPVS_MAX_SOCKET) +CFLAGS += -D DPVS_MAX_LCORE=$(CONFIG_DPVS_MAX_LCORE) -CFLAGS += -D DPVS_MAX_SOCKET=2 -CFLAGS += -D DPVS_MAX_LCORE=64 - -CFLAGS += -D CONFIG_DPVS_LOG -#CFLAGS += -D CONFIG_ICMP_REDIRECT_CORE -#CFLAGS += -D CONFIG_DPVS_AGENT - -#CFLAGS += -D CONFIG_DPVS_NEIGH_DEBUG -#CFLAGS += -D CONFIG_RECORD_BIG_LOOP -#CFLAGS += -D CONFIG_DPVS_SAPOOL_DEBUG -#CFLAGS += -D CONFIG_DPVS_IPVS_DEBUG -#CFLAGS += -D CONFIG_DPVS_SERVICE_DEBUG -#CFLAGS += -D CONFIG_SYNPROXY_DEBUG -#CFLAGS += -D CONFIG_TIMER_MEASURE -#CFLAGS += -D CONFIG_TIMER_DEBUG -#CFLAGS += -D DPVS_CFG_PARSER_DEBUG -#CFLAGS += -D NETIF_BONDING_DEBUG -#CFLAGS += -D CONFIG_TC_DEBUG -#CFLAGS += -D CONFIG_DPVS_IPVS_STATS_DEBUG -#CFLAGS += -D CONFIG_DPVS_IP_HEADER_DEBUG -#CFLAGS += -D CONFIG_DPVS_MBUF_DEBUG -#CFLAGS += -D CONFIG_DPVS_IPSET_DEBUG -#CFLAGS += -D CONFIG_NDISC_DEBUG -#CFLAGS += -D CONFIG_MSG_DEBUG -#CFLAGS += -D CONFIG_DPVS_MP_DEBUG -#CFLAGS += -D CONFIG_DPVS_NETIF_DEBUG -#CFLAGS += -D CONFIG_DPVS_ICMP_DEBUG +ifeq ($(CONFIG_DPVS_AGENT), y) +CFLAGS += -D CONFIG_DPVS_AGENT +endif # for ixgbe nic ifeq ($(CONFIG_IXGEB_PMD), y) CFLAGS += -D CONFIG_DPVS_FDIR endif +ifeq ($(CONFIG_DPVS_LOG), y) +CFLAGS += -D CONFIG_DPVS_LOG +endif + ifeq ($(CONFIG_PDUMP), y) CFLAGS += -D CONFIG_DPVS_PDUMP endif +ifeq ($(CONFIG_ICMP_REDIRECT_CORE), y) +CFLAGS += -D CONFIG_ICMP_REDIRECT_CORE +endif + +ifeq ($(CONFIG_DPVS_NEIGH_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_NEIGH_DEBUG +endif + +ifeq ($(CONFIG_RECORD_BIG_LOOP), y) +CFLAGS += -D CONFIG_RECORD_BIG_LOOP +endif + +ifeq ($(CONFIG_DPVS_SAPOOL_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_SAPOOL_DEBUG +endif + +ifeq ($(CONFIG_DPVS_IPVS_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_IPVS_DEBUG +endif + +ifeq ($(CONFIG_DPVS_SERVICE_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_SERVICE_DEBUG +endif + +ifeq ($(CONFIG_SYNPROXY_DEBUG), y) +CFLAGS += -D CONFIG_SYNPROXY_DEBUG +endif + +ifeq ($(CONFIG_TIMER_MEASURE), y) +CFLAGS += -D CONFIG_TIMER_MEASURE +endif + +ifeq ($(CONFIG_TIMER_DEBUG), y) +CFLAGS += -D CONFIG_TIMER_DEBUG +endif + +ifeq ($(DPVS_CFG_PARSER_DEBUG), y) +CFLAGS += -D DPVS_CFG_PARSER_DEBUG +endif + +ifeq ($(NETIF_BONDING_DEBUG), y) +CFLAGS += -D NETIF_BONDING_DEBUG +endif + +ifeq ($(CONFIG_TC_DEBUG), y) +CFLAGS += -D CONFIG_TC_DEBUG +endif + +ifeq ($(CONFIG_DPVS_IPVS_STATS_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_IPVS_STATS_DEBUG +endif + +ifeq ($(CONFIG_DPVS_IP_HEADER_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_IP_HEADER_DEBUG +endif + +ifeq ($(CONFIG_DPVS_MBUF_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_MBUF_DEBUG +endif + +ifeq ($(CONFIG_DPVS_IPSET_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_IPSET_DEBUG +endif + +ifeq ($(CONFIG_NDISC_DEBUG), y) +CFLAGS += -D CONFIG_NDISC_DEBUG +endif + +ifeq ($(CONFIG_MSG_DEBUG), y) +CFLAGS += -D CONFIG_MSG_DEBUG +endif + +ifeq ($(CONFIG_DPVS_MP_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_MP_DEBUG +endif + +ifeq ($(CONFIG_DPVS_NETIF_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_NETIF_DEBUG +endif + +ifeq ($(CONFIG_DPVS_ICMP_DEBUG), y) +CFLAGS += -D CONFIG_DPVS_ICMP_DEBUG +endif + GCC_MAJOR = $(shell echo __GNUC__ | $(CC) -E -x c - | tail -n 1) GCC_MINOR = $(shell echo __GNUC_MINOR__ | $(CC) -E -x c - | tail -n 1) GCC_VERSION = $(GCC_MAJOR)$(GCC_MINOR) diff --git a/tools/Makefile b/tools/Makefile index 064670c31..832a568d1 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -20,6 +20,10 @@ # SUBDIRS = keepalived ipvsadm dpip +ifeq ($(CONFIG_DPVS_AGENT), y) +SUBDIRS += healthcheck +endif + all: config for i in $(SUBDIRS); do $(MAKE) -C $$i || exit 1; done @@ -42,3 +46,6 @@ install: install -m 744 keepalived/bin/keepalived $(INSDIR)/keepalived install -m 744 ipvsadm/ipvsadm $(INSDIR)/ipvsadm install -m 744 dpip/build/dpip $(INSDIR)/dpip +ifeq ($(CONFIG_DPVS_AGENT), y) + install -m 744 healthcheck/healthcheck $(INSDIR)/healthcheck +endif diff --git a/tools/healthcheck/.gitignore b/tools/healthcheck/.gitignore new file mode 100644 index 000000000..a8763e2d1 --- /dev/null +++ b/tools/healthcheck/.gitignore @@ -0,0 +1,3 @@ +healthcheck +*.log +log/* diff --git a/tools/healthcheck/Makefile b/tools/healthcheck/Makefile new file mode 100644 index 000000000..27e506bba --- /dev/null +++ b/tools/healthcheck/Makefile @@ -0,0 +1,22 @@ +TARGET := healthcheck + +GO ?= go +GO_BUILD = CGO_ENABLED=0 $(GO) build +GO_CLEAN = $(GO) clean + +.PHONY: all $(TARGET) clean + +all: $(TARGET) + +$(TARGET): + -$(GO) mod tidy + $(GO_BUILD) -o $@ + +clean: + $(GO_CLEAN) + +license: license.txt +ifeq ($(shell addlicense 2>&1|grep Usage),) + $(error "`addlicense` command not found. You can install it with `go install github.com/google/addlicense`") +endif + -addlicense -f license.txt -v . diff --git a/tools/healthcheck/go.mod b/tools/healthcheck/go.mod new file mode 100644 index 000000000..7c97f9d58 --- /dev/null +++ b/tools/healthcheck/go.mod @@ -0,0 +1,10 @@ +module github.com/iqiyi/dpvs/tools/healthcheck + +go 1.20 + +require ( + github.com/golang/glog v1.1.1 + github.com/google/gops v0.3.27 +) + +require golang.org/x/sys v0.8.0 // indirect diff --git a/tools/healthcheck/go.sum b/tools/healthcheck/go.sum new file mode 100644 index 000000000..dc5c3cfbf --- /dev/null +++ b/tools/healthcheck/go.sum @@ -0,0 +1,6 @@ +github.com/golang/glog v1.1.1 h1:jxpi2eWoU84wbX9iIEyAeeoac3FLuifZpY9tcNUD9kw= +github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/google/gops v0.3.27 h1:BDdWfedShsBbeatZ820oA4DbVOC8yJ4NI8xAlDFWfgI= +github.com/google/gops v0.3.27/go.mod h1:lYqabmfnq4Q6UumWNx96Hjup5BDAVc8zmfIy0SkNCSk= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/tools/healthcheck/license.txt b/tools/healthcheck/license.txt new file mode 100644 index 000000000..d61a47c47 --- /dev/null +++ b/tools/healthcheck/license.txt @@ -0,0 +1,13 @@ +Copyright 2023 IQiYi Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/tools/healthcheck/main.go b/tools/healthcheck/main.go new file mode 100644 index 000000000..064cdabf2 --- /dev/null +++ b/tools/healthcheck/main.go @@ -0,0 +1,103 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "time" + + "github.com/golang/glog" + gops "github.com/google/gops/agent" + + hc "github.com/iqiyi/dpvs/tools/healthcheck/pkg/helthcheck" + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/server" +) + +var ( + notifyChannelSize = flag.Uint("channel_size", + hc.DefaultServerConfig().NotifyChannelSize, + "The size of the notification channel") + + notifyInterval = flag.Duration("notify_interval", + hc.DefaultServerConfig().NotifyInterval, + "The time between notifications") + + fetchInterval = flag.Duration("fetch_interval", + hc.DefaultServerConfig().FetchInterval, + "The time between healthcheck config fetches from DPVS") + + checkInterval = flag.Duration("check_interval", + 3*time.Second, + "The default time interval to run a check") + + checkTimeout = flag.Duration("check_timeout", + 1*time.Second, + "The default timeout before a check fails") + + checkRetry = flag.Uint("check_retry", + 1, + "The default retry count when a check fails") + + dryRun = flag.Bool("dry_run", + hc.DefaultServerConfig().DryRun, + "Skips actual check and always return healthy as result") + + debug = flag.Bool("debug", + hc.DefaultServerConfig().Debug, + "Enable gops for debug") + + lbIfaceType = flag.String("lb_iface_type", + hc.DefaultServerConfig().LbIfaceType, + "Type of load-balancer interface via which to get check objects and update results") + + lbIfaceAddr = flag.String("lb_iface_addr", + hc.DefaultServerConfig().LbIfaceAddr, + "Address of load-balancer interface via which to get check objects and update results") + + lbAutoMethod = flag.Bool("lb_auto_method", + hc.DefaultServerConfig().LbAutoMethod, + "Use default check method for the backends if not specified") +) + +func main() { + flag.Parse() + defer glog.Flush() + + cfg := hc.DefaultServerConfig() + cfg.NotifyChannelSize = *notifyChannelSize + cfg.NotifyInterval = *notifyInterval + cfg.FetchInterval = *fetchInterval + cfg.LbIfaceType = *lbIfaceType + cfg.LbIfaceAddr = *lbIfaceAddr + cfg.LbAutoMethod = *lbAutoMethod + cfg.DryRun = *dryRun + cfg.Debug = *debug + + hc.DefaultCheckConfig.Interval = *checkInterval + hc.DefaultCheckConfig.Timeout = *checkTimeout + hc.DefaultCheckConfig.Retry = *checkRetry + + if cfg.Debug { + if err := gops.Listen(gops.Options{}); err != nil { + glog.Warningf("Unable to start gops: %v", err) + } else { + defer gops.Close() + } + } + + hcs := hc.NewServer(&cfg) + server.ShutdownHandler(hcs) + hcs.Run() +} diff --git a/tools/healthcheck/pkg/helthcheck/checker.go b/tools/healthcheck/pkg/helthcheck/checker.go new file mode 100644 index 000000000..52b2357a4 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/checker.go @@ -0,0 +1,252 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "sync" + "time" + + log "github.com/golang/glog" +) + +const uweightDefault uint16 = 1 + +// Checks provides a map of healthcheck configurations. +type Checkers struct { + Configs map[Id]*CheckerConfig +} + +// Checker represents a healthcheck instance. +type Checker struct { + CheckerConfig + + lock sync.RWMutex + dryrun bool + uweight uint16 + start time.Time + successes uint64 + failures uint64 + failed uint64 + state State + result *Result + + update chan CheckerConfig + notify chan<- *Notification + quit chan bool +} + +// NewCheck returns an initialised Checker. +func NewChecker(notify chan<- *Notification, state State, weight uint16) *Checker { + // FIXME: how to obtain the original weight if the checker's + // initial state is unhealthy? + if state == StateUnhealthy && weight == 0 { + weight = uweightDefault + } + return &Checker{ + state: state, + uweight: weight, + notify: notify, + update: make(chan CheckerConfig, 1), + quit: make(chan bool, 1), + } +} + +// Status returns the current status for this healthcheck instance. +func (hc *Checker) Status() Status { + hc.lock.RLock() + defer hc.lock.RUnlock() + status := Status{ + LastCheck: hc.start, + Failures: hc.failures, + Successes: hc.successes, + State: hc.state, + } + if hc.state == StateHealthy { + status.Weight = hc.uweight + } + if hc.result != nil { + status.Duration = hc.result.Duration + status.Message = hc.result.String() + } + return status +} + +func (hc *Checker) updateConfig(conf *CheckerConfig) { + hc.CheckerConfig = *conf + if conf.State != StateUnhealthy { + hc.lock.Lock() + weight := hc.uweight + hc.uweight = conf.Weight + hc.lock.Unlock() + if weight != conf.Weight { + log.Infof("%v: user weight changed %d -> %d", hc.Id, weight, conf.Weight) + } + } +} + +// execute invokes the given healthcheck checker with the configured timeout. +func (hc *Checker) execute() *Result { + ch := make(chan *Result, 1) + checker := hc.CheckMethod + timeout := hc.Timeout + target := hc.Target + go func() { + // TODO: Determine a way to ensure that this go routine does not linger. + ch <- checker.Check(target, timeout) + }() + select { + case result := <-ch: + return result + case <-time.After(timeout + time.Second): + return &Result{"Timed out", false, timeout, nil} + } +} + +// Notification generates a healthcheck notification for this checker. +func (hc *Checker) Notification() *Notification { + return &Notification{ + Id: hc.Id, + Target: hc.Target, + Status: hc.Status(), + } +} + +// Notify sends a healthcheck notification for this checker. +func (hc *Checker) Notify() { + hc.notify <- hc.Notification() +} + +// healthcheck executes the given checker. +func (hc *Checker) healthcheck() { + if hc.CheckMethod == nil { + return + } + start := time.Now() + + var result *Result + if hc.dryrun { + result = NewResult(start, "dryrun mode; always succeed", true, nil) + } else { + result = hc.execute() + } + + status := "SUCCESS" + if !result.Success { + status = "FAILURE" + } + log.Infof("%v: %s: %v", hc.Id, status, result) + + hc.lock.Lock() + + hc.start = start + hc.result = result + + var state State + if result.Success { + state = StateHealthy + hc.failed = 0 + hc.successes++ + } else { + hc.failed++ + hc.failures++ + state = StateUnhealthy + } + + if hc.state == StateHealthy && hc.failed > 0 && hc.failed <= uint64(hc.CheckerConfig.Retry) { + log.Infof("%v: Failure %d - retrying...", hc.Id, hc.failed) + state = StateHealthy + } + transition := (hc.state != state) + hc.state = state + + hc.lock.Unlock() + + if transition { + hc.Notify() + } +} + +// Run invokes a healthcheck. It waits for the initial configuration to be +// provided via the configuration channel, after which the configured +// healthchecker is invoked at the given interval. If a new configuration +// is provided the healthchecker is updated and checks are scheduled at the +// new interval. Notifications are generated and sent via the notification +// channel whenever a state transition occurs. Run will terminate once a +// value is received on the quit channel. +func (hc *Checker) Run(start <-chan time.Time) { + // Wait for initial configuration. + select { + case config := <-hc.update: + hc.updateConfig(&config) + case <-hc.quit: + return + } + + // Wait for a tick to avoid a thundering herd at startup and to + // stagger healthchecks that have the same interval. + if start != nil { + <-start + } + log.Infof("Starting healthchecker for %v", hc.Id) + + ticker := time.NewTicker(hc.Interval) + hc.healthcheck() + for { + select { + case <-hc.quit: + ticker.Stop() + log.Infof("Stopping healthchecker for %v", hc.Id) + return + + case config := <-hc.update: + if hc.Interval != config.Interval { + ticker.Stop() + if start != nil { + <-start + } + ticker = time.NewTicker(config.Interval) + } + hc.updateConfig(&config) + + case <-ticker.C: + hc.healthcheck() + } + } +} + +// Stop notifies a running healthcheck that it should quit. +func (hc *Checker) Stop() { + select { + case hc.quit <- true: + default: + } +} + +// SetDryrun enables or disables dryrun mode for a healthcheck. +func (hc *Checker) SetDryrun(dryrun bool) { + hc.dryrun = dryrun +} + +// Update queues a healthcheck configuration update for processing. +func (hc *Checker) Update(config *CheckerConfig) { + select { + case hc.update <- *config: + default: + log.Warningf("Unable to update %v, last update still queued", hc.Id) + } +} diff --git a/tools/healthcheck/pkg/helthcheck/configs.go b/tools/healthcheck/pkg/helthcheck/configs.go new file mode 100644 index 000000000..3d95a6ec1 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/configs.go @@ -0,0 +1,94 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "time" +) + +// ServerConfig specifies the configuration for a healthcheck server. +type ServerConfig struct { + NotifyChannelSize uint + NotifyInterval time.Duration + FetchInterval time.Duration + LbIfaceType string + LbIfaceAddr string + LbAutoMethod bool + DryRun bool + Debug bool +} + +func (cfg *ServerConfig) String() string { + return fmt.Sprintf("notitfy-channel-size: %v, ", cfg.NotifyChannelSize) + + fmt.Sprintf("notify-interval: %v, ", cfg.NotifyInterval) + + fmt.Sprintf("fetch-interval: %v, ", cfg.FetchInterval) + + fmt.Sprintf("lb-auto-method: %v, ", cfg.LbAutoMethod) + + fmt.Sprintf("dryrun: %v, ", cfg.DryRun) + + fmt.Sprintf("debug: %v", cfg.Debug) +} + +var defaultServerConfig = ServerConfig{ + NotifyChannelSize: 1000, + NotifyInterval: 15 * time.Second, + FetchInterval: 15 * time.Second, + LbIfaceType: "dpvs-agent", // only type supported now + LbIfaceAddr: "localhost:6600", + LbAutoMethod: true, + DryRun: false, + Debug: false, +} + +// DefaultServerConfig returns the default server configuration. +func DefaultServerConfig() ServerConfig { + return defaultServerConfig +} + +// CheckerConfig contains the configuration for a healthcheck. +type CheckerConfig struct { + Id + + Target + State + Weight uint16 + CheckMethod + + Interval time.Duration + Timeout time.Duration + Retry uint +} + +var DefaultCheckConfig CheckerConfig + +// NewConfig returns an initialised Config. +func NewCheckerConfig(id *Id, checker CheckMethod, + target *Target, state State, weight uint16, + interval, timeout time.Duration, retry uint) *CheckerConfig { + config := CheckerConfig{ + Id: *id, + Target: *target, + State: state, + Weight: weight, + CheckMethod: checker, + Interval: interval, + Timeout: timeout, + Retry: retry, + } + config.BindConfig(&config) + return &config +} diff --git a/tools/healthcheck/pkg/helthcheck/ping_checker.go b/tools/healthcheck/pkg/helthcheck/ping_checker.go new file mode 100644 index 000000000..dae8eda92 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/ping_checker.go @@ -0,0 +1,203 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +// ICMP ping healthcheck implementation. + +package hc + +import ( + "bytes" + "fmt" + "math/rand" + "net" + "os" + "time" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +var _ CheckMethod = (*PingChecker)(nil) + +var nextPingCheckerID uint16 + +func init() { + s := rand.NewSource(int64(os.Getpid())) + nextPingCheckerID = uint16(s.Int63() & 0xffff) +} + +// PingChecker contains configuration specific to a ping healthcheck. +type PingChecker struct { + Config *CheckerConfig + + ID uint16 + Seqnum uint16 +} + +// NewPingChecker returns an initialised PingChecker. +func NewPingChecker() *PingChecker { + checker := PingChecker{ID: nextPingCheckerID} + nextPingCheckerID++ + return &checker +} + +func (hc *PingChecker) BindConfig(conf *CheckerConfig) { + hc.Config = conf +} + +// String returns the string representation of a Ping healthcheck. +func (hc *PingChecker) String() string { + return fmt.Sprintf("PING checker for %s", hc.Config.Id) +} + +// Check executes a ping healthcheck. +func (hc *PingChecker) Check(target Target, timeout time.Duration) *Result { + msg := fmt.Sprintf("ICMP ping to host %v", target.IP) + if target.IP.To4() != nil { + target.Proto = utils.IPProtoICMP + } else { + target.Proto = utils.IPProtoICMPv6 + } + seq := hc.Seqnum + hc.Seqnum++ + echo := newICMPEchoRequest(target.Proto, hc.ID, seq, 64, []byte("Healthcheck")) + start := time.Now() + if timeout == time.Duration(0) { + timeout = DefaultCheckConfig.Timeout + } + err := exchangeICMPEcho(target.Network(), target.IP, timeout, echo) + success := err == nil + if err != nil { + err = fmt.Errorf("ping target %v, %v", target.IP, err) + } + return NewResult(start, msg, success, err) +} + +// NB: The code below borrows heavily from pkg/net/ipraw_test.go. + +type icmpMsg []byte + +const ( + ICMP4_ECHO_REQUEST = 8 + ICMP4_ECHO_REPLY = 0 + ICMP6_ECHO_REQUEST = 128 + ICMP6_ECHO_REPLY = 129 +) + +func newICMPEchoRequest(proto utils.IPProto, id, seqnum, msglen uint16, filler []byte) icmpMsg { + switch proto { + case utils.IPProtoICMP: + return newICMPv4EchoRequest(id, seqnum, msglen, filler) + case utils.IPProtoICMPv6: + return newICMPv6EchoRequest(id, seqnum, msglen, filler) + } + return nil +} + +func newICMPv4EchoRequest(id, seqnum, msglen uint16, filler []byte) icmpMsg { + msg := newICMPInfoMessage(id, seqnum, msglen, filler) + msg[0] = ICMP4_ECHO_REQUEST + cs := icmpChecksum(msg) + // place checksum back in header; using ^= avoids the assumption that the + // checksum bytes are zero + msg[2] ^= uint8(cs & 0xff) + msg[3] ^= uint8(cs >> 8) + return msg +} + +func icmpChecksum(msg icmpMsg) uint16 { + cklen := len(msg) + s := uint32(0) + for i := 0; i < cklen-1; i += 2 { + s += uint32(msg[i+1])<<8 | uint32(msg[i]) + } + if cklen&1 == 1 { + s += uint32(msg[cklen-1]) + } + s = (s >> 16) + (s & 0xffff) + s = s + (s >> 16) + return uint16(^s) +} + +func newICMPv6EchoRequest(id, seqnum, msglen uint16, filler []byte) icmpMsg { + msg := newICMPInfoMessage(id, seqnum, msglen, filler) + msg[0] = ICMP6_ECHO_REQUEST + // Note: For IPv6, the OS will compute and populate the ICMP checksum bytes. + return msg +} + +func newICMPInfoMessage(id, seqnum, msglen uint16, filler []byte) icmpMsg { + b := make([]byte, msglen) + copy(b[8:], bytes.Repeat(filler, (int(msglen)-8)/(len(filler)+1))) + b[0] = 0 // type + b[1] = 0 // code + b[2] = 0 // checksum + b[3] = 0 // checksum + b[4] = uint8(id >> 8) // identifier + b[5] = uint8(id & 0xff) // identifier + b[6] = uint8(seqnum >> 8) // sequence number + b[7] = uint8(seqnum & 0xff) // sequence number + return b +} + +func parseICMPEchoReply(msg icmpMsg) (id, seqnum, chksum uint16) { + id = uint16(msg[4])<<8 | uint16(msg[5]) + seqnum = uint16(msg[6])<<8 | uint16(msg[7]) + chksum = uint16(msg[2])<<8 | uint16(msg[3]) + return +} + +func exchangeICMPEcho(network string, ip net.IP, timeout time.Duration, echo icmpMsg) error { + c, err := net.ListenPacket(network, "") + if err != nil { + return err + } + defer c.Close() + + _, err = c.WriteTo(echo, &net.IPAddr{IP: ip}) + if err != nil { + return err + } + + c.SetDeadline(time.Now().Add(timeout)) + reply := make([]byte, 256) + for { + _, addr, err := c.ReadFrom(reply) + if err != nil { + return err + } + if !ip.Equal(net.ParseIP(addr.String())) { + continue + } + if reply[0] != ICMP4_ECHO_REPLY && reply[0] != ICMP6_ECHO_REPLY { + continue + } + xid, xseqnum, _ := parseICMPEchoReply(echo) + rid, rseqnum, rchksum := parseICMPEchoReply(reply) + if rid != xid || rseqnum != xseqnum { + continue + } + if reply[0] == ICMP4_ECHO_REPLY { + cs := icmpChecksum(reply) + if cs != 0 { + return fmt.Errorf("Bad ICMP checksum: %x", rchksum) + } + } + // TODO(angusc): Validate checksum for IPv6 + break + } + return nil +} diff --git a/tools/healthcheck/pkg/helthcheck/ping_checker_test.go b/tools/healthcheck/pkg/helthcheck/ping_checker_test.go new file mode 100644 index 000000000..686ff15cf --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/ping_checker_test.go @@ -0,0 +1,45 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "net" + "testing" + "time" +) + +var targets = []Target{ + {net.ParseIP("127.0.0.1"), 0, 0}, + {net.ParseIP("192.168.88.30"), 0, 0}, + {net.ParseIP("11.22.33.44"), 0, 0}, + {net.ParseIP("::1"), 0, 0}, + {net.ParseIP("2001::1"), 0, 0}, + {net.ParseIP("2001::68"), 0, 0}, +} + +func TestPingChecker(t *testing.T) { + for _, target := range targets { + checker := NewPingChecker() + id := Id(target.IP.String()) + config := NewCheckerConfig(&id, checker, + &target, StateUnknown, 0, + 3*time.Second, 1*time.Second, 3) + result := checker.Check(target, config.Timeout) + t.Logf("%v", result) + } +} diff --git a/tools/healthcheck/pkg/helthcheck/server.go b/tools/healthcheck/pkg/helthcheck/server.go new file mode 100644 index 000000000..bd26265cb --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/server.go @@ -0,0 +1,248 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "math/rand" + "time" + + log "github.com/golang/glog" + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/lb" + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +// Server contains the data needed to run a healthcheck server. +type Server struct { + config *ServerConfig + comm lb.Comm + + healthchecks map[Id]*Checker + configs chan map[Id]*CheckerConfig + notify chan *Notification + + quit chan bool +} + +// NewServer returns an initialised healthcheck server. +func NewServer(cfg *ServerConfig) *Server { + rand.Seed(time.Now().UnixNano()) + + if cfg == nil { + defaultCfg := DefaultServerConfig() + cfg = &defaultCfg + } + + var comm lb.Comm + switch cfg.LbIfaceType { + case "dpvs-agent": + comm = lb.NewDpvsAgentComm(cfg.LbIfaceAddr) + default: + panic(fmt.Sprintf("lb_iface_type %q not supported", cfg.LbIfaceType)) + } + + return &Server{ + config: cfg, + comm: comm, + + healthchecks: make(map[Id]*Checker), + notify: make(chan *Notification, cfg.NotifyChannelSize), + configs: make(chan map[Id]*CheckerConfig), + + quit: make(chan bool, 1), + } +} + +func (s *Server) NewChecker(typ lb.Checker, proto utils.IPProto) CheckMethod { + // TODO: support user specified Send/Receive data for TCP/UDP checker + var checker CheckMethod + switch typ { + case lb.CheckerTCP: + checker = NewTCPChecker("", "") + case lb.CheckerUDP: + checker = NewUDPChecker("", "") + case lb.CheckerPING: + checker = NewPingChecker() + case lb.CheckerNone: + if s.config.LbAutoMethod { + switch proto { + case utils.IPProtoTCP: + checker = NewTCPChecker("", "") + case utils.IPProtoUDP: + checker = NewUDPChecker("", "") + } + } + } + return checker +} + +// getHealthchecks attempts to get the current healthcheck configurations from DPVS +func (s *Server) getHealthchecks() (*Checkers, error) { + vss, err := s.comm.ListVirtualServices() + if err != nil { + return nil, err + } + results := &Checkers{Configs: make(map[Id]*CheckerConfig)} + for _, vs := range vss { + for _, rs := range vs.RSs { + target := &Target{rs.IP, rs.Port, vs.Protocol} + id := NewId(vs.Id, target) + checker := s.NewChecker(vs.Checker, vs.Protocol) + if checker == nil { + log.Info("Skip checking vs %v with %v", vs.Id, vs.Checker) + continue + } + weight := rs.Weight + state := StateUnknown + if weight > 0 { + state = StateHealthy + } else if rs.Inhibited { + state = StateUnhealthy + } + // TODO: allow users to specify check interval, timeout and retry + config := NewCheckerConfig(id, checker, + target, state, weight, + DefaultCheckConfig.Interval, + DefaultCheckConfig.Timeout, + DefaultCheckConfig.Retry) + results.Configs[*id] = config + } + } + return results, nil +} + +// updater attempts to fetch healthcheck configurations at regular intervals. +// When configurations are successfully retrieved they are provided to the +// manager via the configs channel. +func (s *Server) updater() { + for { + log.Info("Getting healthchecks from DPVS ...") + checkers, err := s.getHealthchecks() + if err != nil { + log.Errorf("Getting healthchecks failed: %v, retry later", err) + time.Sleep(5 * time.Second) + } else if checkers != nil { + log.Infof("DPVS returned %d healthcheck(s)", len(checkers.Configs)) + s.configs <- checkers.Configs + time.Sleep(s.config.FetchInterval) + } else { // It should not happen. + log.Warning("No healthcheck returned from DPVS") + time.Sleep(s.config.FetchInterval) + } + } +} + +// notifier batches healthcheck notifications and sends them to DPVS. +func (s *Server) notifier() { + // TODO: support more concurrency and rate limit + for { + select { + case notification := <-s.notify: + log.Infof("Sending notification >>> %v", notification) + //fmt.Println("Sending notification >>>", notification) + inhibited := false + if notification.Status.State == StateUnhealthy { + inhibited = true + } + vs := &lb.VirtualService{ + Id: notification.Id.Vs(), + Protocol: notification.Target.Proto, + RSs: []lb.RealServer{{ + IP: notification.Target.IP, + Port: notification.Target.Port, + Weight: notification.Status.Weight, + Inhibited: inhibited, + }}, + } + + if err := s.comm.UpdateByChecker([]lb.VirtualService{*vs}); err != nil { + log.Warningf("Failed to Update %v healthy status to %v(weight: %d): %v", + notification.Id, notification.State, notification.Status.Weight, err) + } + } + } +} + +// manager is responsible for controlling the healthchecks that are currently +// running. When healthcheck configurations become available, the manager will +// stop and remove deleted healthchecks, spawn new healthchecks and provide +// the current configurations to each of the running healthchecks. +func (s *Server) manager() { + notifyTicker := time.NewTicker(s.config.NotifyInterval) + var configs map[Id]*CheckerConfig + for { + select { + case configs = <-s.configs: + + // Remove healthchecks that have been deleted. + for id, hc := range s.healthchecks { + if configs[id] == nil { + hc.Stop() + delete(s.healthchecks, id) + } + } + + // Spawn new healthchecks. + for id, conf := range configs { + if s.healthchecks[id] == nil { + hc := NewChecker(s.notify, conf.State, conf.Weight) + hc.SetDryrun(s.config.DryRun) + s.healthchecks[id] = hc + checkTicker := time.NewTicker(time.Duration((1 + rand.Intn( + int(DefaultCheckConfig.Interval.Milliseconds())))) * time.Millisecond) + go hc.Run(checkTicker.C) + } + } + + // Update configurations. + for id, hc := range s.healthchecks { + hc.Update(configs[id]) + } + + case <-notifyTicker.C: + log.Infof("Total checkers: %d", len(s.healthchecks)) + // Send notifications when status changed. + for id, hc := range s.healthchecks { + notification := hc.Notification() + if configs[id].State != notification.State { + // FIXME: Don't resend the notification after a successful one. + hc.notify <- notification + } + } + } + } +} + +// Run runs a healthcheck server. +func (s *Server) Run() { + log.Infof("Starting healthcheck server (%v) ...", s.config) + go s.updater() + go s.notifier() + go s.manager() + + <-s.quit +} + +// Shutdown notifies a healthcheck server to shutdown. +func (s *Server) Shutdown() { + log.Info("Closing healthcheck server ...") + select { + case s.quit <- true: + default: + } +} diff --git a/tools/healthcheck/pkg/helthcheck/tcp_checker.go b/tools/healthcheck/pkg/helthcheck/tcp_checker.go new file mode 100644 index 000000000..5b6026cc0 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/tcp_checker.go @@ -0,0 +1,122 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "io" + "net" + "time" +) + +var _ CheckMethod = (*TCPChecker)(nil) + +// TCPChecker contains configuration specific to a TCP healthcheck. +type TCPChecker struct { + Config *CheckerConfig + + Receive string + Send string +} + +// NewTCPChecker returns an initialised TCPChecker. +func NewTCPChecker(recv, send string) *TCPChecker { + return &TCPChecker{Receive: recv, Send: send} +} + +func (hc *TCPChecker) BindConfig(conf *CheckerConfig) { + hc.Config = conf +} + +// String returns the string representation of a TCP healthcheck. +func (hc *TCPChecker) String() string { + return fmt.Sprintf("TCP checker for %v", hc.Config.Id) +} + +// Check executes a TCP healthcheck. +func (hc *TCPChecker) Check(target Target, timeout time.Duration) *Result { + msg := fmt.Sprintf("TCP connect to %s", target.Addr()) + start := time.Now() + if timeout == time.Duration(0) { + timeout = DefaultCheckConfig.Timeout + } + deadline := start.Add(timeout) + + dial := net.Dialer{ + Timeout: timeout, + } + conn, err := dial.Dial(target.Network(), target.Addr()) + if err != nil { + msg = fmt.Sprintf("%s: failed to dail", msg) + return NewResult(start, msg, false, err) + } + defer conn.Close() + + tcpConn, ok := conn.(*net.TCPConn) + if !ok { + msg = fmt.Sprintf("%s: failed to create tcp socket", msg) + return NewResult(start, msg, false, err) + } + + if hc.Send == "" && hc.Receive == "" { + msg = fmt.Sprintf("%s succeed", msg) + return NewResult(start, msg, true, err) + } + + err = tcpConn.SetDeadline(deadline) + if err != nil { + msg = fmt.Sprintf("%s: failed to set deadline", msg) + return NewResult(start, msg, false, err) + } + + if hc.Send != "" { + err = writeFull(tcpConn, []byte(hc.Send)) + if err != nil { + msg = fmt.Sprintf("%s: failed to send request", msg) + return NewResult(start, msg, false, err) + } + } + + if hc.Receive != "" { + buf := make([]byte, len(hc.Receive)) + n, err := io.ReadFull(tcpConn, buf) + if err != nil { + msg = fmt.Sprintf("%s: failed to read response", msg) + return NewResult(start, msg, false, err) + } + got := string(buf[0:n]) + if got != hc.Receive { + msg = fmt.Sprintf("%s: unexpected response %q", msg, got) + return NewResult(start, msg, false, err) + } + } + + msg = fmt.Sprintf("%s succeed", msg) + return NewResult(start, msg, true, err) +} + +func writeFull(conn net.Conn, b []byte) error { + for len(b) > 0 { + n, err := conn.Write(b) + if err != nil { + return err + } + b = b[n:] + } + return nil +} diff --git a/tools/healthcheck/pkg/helthcheck/test/tcp_checker.go b/tools/healthcheck/pkg/helthcheck/test/tcp_checker.go new file mode 100644 index 000000000..cd8f1707b --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/test/tcp_checker.go @@ -0,0 +1,130 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package main + +import ( + "errors" + "fmt" + "io" + "net" + "time" +) + +func Check(addr, network, send, recv string, timeout time.Duration) *Result { + msg := fmt.Sprintf("TCP connect to %s", addr) + start := time.Now() + if timeout == time.Duration(0) { + timeout = 3 * time.Second + } + deadline := start.Add(timeout) + + dial := net.Dialer{ + Timeout: timeout, + } + conn, err := dial.Dial(network, addr) + if err != nil { + msg = fmt.Sprintf("%s: failed to dail", msg) + return NewResult(start, msg, false, err) + } + defer conn.Close() + + tcpConn, ok := conn.(*net.TCPConn) + if !ok { + msg = fmt.Sprintf("%s: not a TCP conn", msg) + err = errors.New("failed to create tcp socket") + return NewResult(start, msg, false, err) + } + + if send == "" && recv == "" { + msg = fmt.Sprintf("%s: succeed", msg) + return NewResult(start, msg, true, err) + } + + err = tcpConn.SetDeadline(deadline) + if err != nil { + msg = fmt.Sprintf("%s: failed to set deadline", msg) + return NewResult(start, msg, false, err) + } + + if send != "" { + err = writeFull(tcpConn, []byte(send)) + if err != nil { + msg = fmt.Sprintf("%s: failed to send request", msg) + return NewResult(start, msg, false, err) + } + } + + if recv != "" { + buf := make([]byte, len(recv)) + n, err := io.ReadFull(tcpConn, buf) + if err != nil { + msg = fmt.Sprintf("%s: failed to read response", msg) + return NewResult(start, msg, false, err) + } + got := string(buf[0:n]) + if got != recv { + msg = fmt.Sprintf("%s: unexpected response %q", msg, got) + return NewResult(start, msg, false, err) + } + } + + msg = fmt.Sprintf("%s: succeed", msg) + return NewResult(start, msg, true, err) +} + +func writeFull(conn net.Conn, b []byte) error { + for len(b) > 0 { + n, err := conn.Write(b) + if err != nil { + return err + } + b = b[n:] + } + return nil +} + +type Result struct { + Message string + Success bool + time.Duration + Err error +} + +func (r *Result) String() string { + msg := fmt.Sprintf("[result: %v, duration: %v] ", r.Success, r.Duration) + if r.Err != nil { + return msg + r.Err.Error() + } + return msg + r.Message +} + +func NewResult(start time.Time, msg string, success bool, err error) *Result { + duration := time.Since(start) + return &Result{msg, success, duration, err} +} + +func main() { + fmt.Println(Check("192.168.88.30:80", "tcp4", "", "", 10*time.Second)) + fmt.Println(Check("192.168.88.30:80", "tcp4", "1", "cds1sfdafasdfasdfafafasssssssssssssssssssssssssss", 1*time.Second)) + fmt.Println(Check("192.168.88.31:80", "tcp4", "", "", 10*time.Second)) + fmt.Println(Check("10.130.133.208:80", "tcp4", "", "", 0)) + fmt.Println(Check("1.2.1.2:12123", "tcp4", "", "", 0)) + fmt.Println(Check("[2001::30]:80", "tcp6", "", "", 0)) + fmt.Println(Check("[2001::30]:80", "tcp6", "a", "HTTP", 0)) + fmt.Println(Check("[2001::33]:81", "tcp6", "", "", 0)) +} diff --git a/tools/healthcheck/pkg/helthcheck/test/udp_checker.go b/tools/healthcheck/pkg/helthcheck/test/udp_checker.go new file mode 100644 index 000000000..150587126 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/test/udp_checker.go @@ -0,0 +1,119 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package main + +import ( + "errors" + "fmt" + "net" + "os" + "time" +) + +func udpPortCheck(udpConn *net.UDPConn) (bool, error) { + return true, nil +} + +func Check(addr, network, send, recv string, timeout time.Duration) *Result { + msg := fmt.Sprintf("UDP check to %s", addr) + start := time.Now() + if timeout == time.Duration(0) { + timeout = 3 + } + deadline := start.Add(timeout) + + dial := net.Dialer{Timeout: timeout} + conn, err := dial.Dial(network, addr) + if err != nil { + msg = fmt.Sprintf("%s: failed to dail", msg) + return NewResult(start, msg, false, err) + } + defer conn.Close() + + udpConn, ok := conn.(*net.UDPConn) + if !ok { + msg = fmt.Sprintf("%s: not an UDP conn", msg) + err = errors.New("failed to create udp socket") + return NewResult(start, msg, false, err) + } + + err = udpConn.SetDeadline(deadline) + if err != nil { + msg = fmt.Sprintf("%s: failed to set deadline", msg) + return NewResult(start, msg, false, err) + } + + if _, err = udpConn.Write([]byte(send)); err != nil { + msg = fmt.Sprintf("%s: failed to send request", msg) + return NewResult(start, msg, false, err) + } + + buf := make([]byte, len(recv)+1) + n, _, err := udpConn.ReadFrom(buf) + if err != nil { + if send == "" && recv == "" { + if neterr, ok := err.(net.Error); ok { + // When Send and Recv is none and i/o timeout, the dest port state + // is undetermined. Check shall return success in the case. + if neterr.Timeout() { + msg = fmt.Sprintf("%s: %s, port state unkown", msg, err) + return NewResult(start, msg, true, nil) + } + } + } + msg = fmt.Sprintf("%s: failed to read response", msg) + return NewResult(start, msg, false, err) + } + + got := string(buf[0:n]) + if got != recv { + msg = fmt.Sprintf("%s: unexpected response %q", msg, got) + return NewResult(start, msg, false, err) + } + msg = fmt.Sprintf("%s: succeed", msg) + return NewResult(start, msg, true, err) +} + +type Result struct { + Message string + Success bool + time.Duration + Err error +} + +func (r *Result) String() string { + msg := fmt.Sprintf("[result: %v, duration: %v] ", r.Success, r.Duration) + if r.Err != nil { + return msg + r.Err.Error() + } + return msg + r.Message +} + +func NewResult(start time.Time, msg string, success bool, err error) *Result { + duration := time.Since(start) + return &Result{msg, success, duration, err} +} + +func main() { + if len(os.Args) != 6 { + fmt.Printf("%s addr network send recv timeout\n", os.Args[0]) + return + } + timeout, _ := time.ParseDuration(os.Args[5]) + fmt.Println(Check(os.Args[1], os.Args[2], os.Args[3], os.Args[4], timeout)) +} diff --git a/tools/healthcheck/pkg/helthcheck/types.go b/tools/healthcheck/pkg/helthcheck/types.go new file mode 100644 index 000000000..560ebc84e --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/types.go @@ -0,0 +1,225 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "net" + "strconv" + "strings" + "time" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +// Id provides the unique identifier of a given healthcheck. It has format +// of {vs}/{rs}, where {vs} is service id confined by the lb_interface_type, +// and {vs} is the backend id within the service of format ip:proto:port. +// Id should be created using NewId() function. +type Id string + +func NewId(vs string, rs *Target) *Id { + id := Id(fmt.Sprintf("%s/%v", vs, rs)) + return &id +} + +func (id Id) Vs() string { + strId := string(id) + idx := strings.LastIndexByte(strId, '/') + if idx < 0 { + return "" + } + return strId[:idx] +} + +func (id Id) Rs() *Target { + strId := string(id) + idx := strings.LastIndexByte(strId, '/') + if idx < 0 { + return nil + } + return NewTargetFromStr(strId[idx+1:]) +} + +// MethodType is the type of check method supported for now. +type MethodType int + +const ( + MethodTypeNone MethodType = iota + MethodTypeTCP + MethodTypeUDP + MethodTypePING +) + +// String returns the name for the given MethodType. +func (h MethodType) String() string { + switch h { + case MethodTypeTCP: + return "TCP" + case MethodTypeUDP: + return "UDP" + case MethodTypePING: + return "PING" + } + return "(unknown)" +} + +// CheckMethod is the interface that must be implemented by a healthcheck. +type CheckMethod interface { + Check(target Target, timeout time.Duration) *Result + BindConfig(conf *CheckerConfig) + String() string +} + +// State represents the current state of a healthcheck. +type State int + +const ( + StateUnknown State = iota + StateUnhealthy + StateHealthy +) + +var stateNames = map[State]string{ + StateUnknown: "Unknown", + StateUnhealthy: "Unhealthy", + StateHealthy: "Healthy", +} + +// String returns the string representation for the given healthcheck state. +func (s State) String() string { + if name, ok := stateNames[s]; ok { + return name + } + return "" +} + +// Target specifies the target for a healthcheck. +type Target struct { + IP net.IP // IP address of the healthcheck target. + Port uint16 + Proto utils.IPProto +} + +// Create a Target from str of format "IPv4:Proto:Port" or "[IPv6]:Proto:Port". +func NewTargetFromStr(str string) *Target { + idx2 := strings.LastIndexByte(str, ':') + idx1 := strings.LastIndexByte(str[:idx2], ':') + if idx1 < 0 || idx2 < 0 || idx1 >= idx2 { + return nil + } + port, err := strconv.ParseUint(str[idx2:], 10, 16) + if err != nil { + return nil + } + proto := utils.IPProtoFromStr(str[idx1:idx2]) + if proto == 0 { + return nil + } + ip := net.ParseIP(strings.TrimRight(strings.TrimLeft(str[:idx1], "["), "]")) + if ip == nil { + return nil + } + return &Target{ip, uint16(port), proto} +} + +// String returns the string representation of a healthcheck target. +func (t Target) String() string { + if t.IP.To4() != nil { + return fmt.Sprintf("%v:%v:%d", t.IP, t.Proto, t.Port) + } + return fmt.Sprintf("[%v]:%v:%d", t.IP, t.Proto, t.Port) +} + +// Addr returns the IP:Port representation of a healthcheck target +func (t Target) Addr() string { + if t.IP.To4() != nil { + return fmt.Sprintf("%v:%d", t.IP, t.Port) + } + return fmt.Sprintf("[%v]:%d", t.IP, t.Port) +} + +// Network returns the network name for the healthcheck target. +func (t *Target) Network() string { + var network string + version := 4 + if t.IP.To4() == nil { + version = 6 + } + switch t.Proto { + case utils.IPProtoICMP: + network = "ip4:icmp" + case utils.IPProtoICMPv6: + network = "ip6:ipv6-icmp" + case utils.IPProtoTCP: + network = fmt.Sprintf("tcp%d", version) + case utils.IPProtoUDP: + network = fmt.Sprintf("udp%d", version) + default: + return "(unknown)" + } + return network +} + +// Result stores the result of a healthcheck performed by a checker. +type Result struct { + Message string + Success bool + time.Duration + Err error +} + +// String returns the string representation of a healthcheck result. +func (r *Result) String() string { + msg := fmt.Sprintf("[result: %v, duration: %v] ", r.Success, r.Duration) + if r.Err != nil { + return msg + r.Err.Error() + } + return msg + r.Message +} + +func NewResult(start time.Time, msg string, success bool, err error) *Result { + // TODO: Make this clock skew safe. + duration := time.Since(start) + return &Result{msg, success, duration, err} +} + +// Status represents the current status of a healthcheck instance. +type Status struct { + LastCheck time.Time + Duration time.Duration + Failures uint64 + Successes uint64 + State + Weight uint16 + Message string +} + +// Notification stores a status notification for a healthcheck. +type Notification struct { + Id + Target + Status +} + +// String returns the string representation for the given notification. +func (n *Notification) String() string { + return fmt.Sprintf("ID %v, %v, Weight %d, Fail %v, Success %v, Last check %s in %v", n.Id, + stateNames[n.Status.State], n.Status.Weight, n.Status.Failures, n.Status.Successes, + n.Status.LastCheck.Format("2006-01-02 15:04:05.000"), n.Status.Duration) +} diff --git a/tools/healthcheck/pkg/helthcheck/udp_checker.go b/tools/healthcheck/pkg/helthcheck/udp_checker.go new file mode 100644 index 000000000..ceb6d4467 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/udp_checker.go @@ -0,0 +1,108 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "net" + "time" +) + +var _ CheckMethod = (*UDPChecker)(nil) + +// UDPChecker contains configuration specific to a UDP healthcheck. +type UDPChecker struct { + Config *CheckerConfig + + Receive string + Send string +} + +// NewUDPChecker returns an initialised UDPChecker. +func NewUDPChecker(recv, send string) *UDPChecker { + return &UDPChecker{Receive: recv, Send: send} +} + +func (hc *UDPChecker) BindConfig(conf *CheckerConfig) { + hc.Config = conf +} + +// String returns the string representation of a UDP healthcheck. +func (hc *UDPChecker) String() string { + return fmt.Sprintf("UDP checker for %v", hc.Config.Id) +} + +// Check executes a UDP healthcheck. +func (hc *UDPChecker) Check(target Target, timeout time.Duration) *Result { + msg := fmt.Sprintf("UDP check to %s", target.Addr()) + start := time.Now() + if timeout == time.Duration(0) { + timeout = DefaultCheckConfig.Timeout + } + deadline := start.Add(timeout) + + dial := net.Dialer{Timeout: timeout} + conn, err := dial.Dial(target.Network(), target.Addr()) + if err != nil { + msg = fmt.Sprintf("%s: failed to dail", msg) + return NewResult(start, msg, false, err) + } + defer conn.Close() + + udpConn, ok := conn.(*net.UDPConn) + if !ok { + msg = fmt.Sprintf("%s: failed to create udp socket", msg) + return NewResult(start, msg, false, err) + } + + err = udpConn.SetDeadline(deadline) + if err != nil { + msg = fmt.Sprintf("%s: failed to set deadline", msg) + return NewResult(start, msg, false, err) + } + + if _, err = udpConn.Write([]byte(hc.Send)); err != nil { + msg = fmt.Sprintf("%s: failed to send request", msg) + return NewResult(start, msg, false, err) + } + + buf := make([]byte, len(hc.Receive)+1) + n, _, err := udpConn.ReadFrom(buf) + if err != nil { + if hc.Send == "" && hc.Receive == "" { + if neterr, ok := err.(net.Error); ok { + // When hc.Send and hc.Receive is none and i/o timeout, the dest port state + // is undetermined. Check shall return success in the case. + if neterr.Timeout() { + msg = fmt.Sprintf("%s: %s, port state unkown", msg, err) + return NewResult(start, msg, true, nil) + } + } + } + msg = fmt.Sprintf("%s: failed to read response", msg) + return NewResult(start, msg, false, err) + } + + got := string(buf[0:n]) + if got != hc.Receive { + msg = fmt.Sprintf("%s: unexpected response %q", msg, got) + return NewResult(start, msg, false, err) + } + msg = fmt.Sprintf("%s: succeed", msg) + return NewResult(start, msg, true, err) +} diff --git a/tools/healthcheck/pkg/lb/dpvs_agent.go b/tools/healthcheck/pkg/lb/dpvs_agent.go new file mode 100644 index 000000000..0e0072785 --- /dev/null +++ b/tools/healthcheck/pkg/lb/dpvs_agent.go @@ -0,0 +1,228 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package lb + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "strings" + "time" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +var _ Comm = (*DpvsAgentComm)(nil) + +var ( + serverDefault = "localhost:6600" + listUri = LbApi{"/v2/vs", http.MethodGet} + noticeUri = LbApi{"/v2/vs/%s/rs?healthcheck=true", http.MethodPut} + + client *http.Client = &http.Client{Timeout: httpClientTimeout} +) + +const httpClientTimeout = 10 * time.Second + +type DpvsAgentComm struct { + listApi LbApi + noticeApis []LbApi +} + +type LbApi struct { + Url string + HttpMethod string // http.MethodGet, http.MethodPut, ... +} + +type DpvsAgentRs struct { + IP string `json:"ip"` + Port uint16 `json:"port"` + Weight uint16 `json:"weight"` + Inhibited bool `json:"inhibited,omitempty"` +} + +type DpvsAgentRsItem struct { + Spec DpvsAgentRs +} + +type DpvsAgentRsList struct { + Items []DpvsAgentRsItem +} + +type DpvsAgentRsListPut struct { + Items []DpvsAgentRs +} + +type DpvsAgentVs struct { + Addr string + Port uint16 + Proto uint16 + DestCheck []string + Rss DpvsAgentRsList `json:"RSs"` +} + +type DpvsAgentVsList struct { + Items []DpvsAgentVs +} + +func (avs *DpvsAgentVs) serviceId() string { + return strings.ToLower(fmt.Sprintf("%s-%d-%s", avs.Addr, avs.Port, + utils.IPProto(avs.Proto))) +} + +func (avs *DpvsAgentVs) toVs() (*VirtualService, error) { + vip := net.ParseIP(avs.Addr) + if vip == nil { + return nil, fmt.Errorf("invalid Vs Addr %q", avs.Addr) + } + vport := avs.Port + proto := utils.IPProto(avs.Proto) + if proto != utils.IPProtoTCP && proto != utils.IPProtoUDP { + return nil, fmt.Errorf("Vs protocol type 0x%x not supported", avs.Port) + } + checker := CheckerNone + for _, name := range avs.DestCheck { + name = strings.ToLower(name) + switch name { + case "tcp": + checker = CheckerTCP + case "udp": + checker = CheckerUDP + case "ping": + checker = CheckerPING + } + } + vs := &VirtualService{ + Checker: checker, + IP: vip, + Port: vport, + Protocol: proto, + RSs: make([]RealServer, len(avs.Rss.Items)), + } + vs.Id = avs.serviceId() + + for i, ars := range avs.Rss.Items { + rip := net.ParseIP(ars.Spec.IP) + if rip == nil { + return nil, fmt.Errorf("%s: invalid Rs IP %q", vs.Id, ars.Spec.IP) + } + rs := &RealServer{ + IP: rip, + Port: ars.Spec.Port, + Weight: ars.Spec.Weight, + Inhibited: ars.Spec.Inhibited, + } + vs.RSs[i] = *rs + } + return vs, nil +} + +func (avslist *DpvsAgentVsList) toVsList() ([]VirtualService, error) { + if len(avslist.Items) == 0 { + return nil, nil + } + vslist := make([]VirtualService, len(avslist.Items)) + for i, avs := range avslist.Items { + vs, err := avs.toVs() + if err != nil { + return nil, err + } + vslist[i] = *vs + } + return vslist, nil +} + +func NewDpvsAgentComm(server string) *DpvsAgentComm { + if len(server) == 0 { + server = serverDefault + } + addr := "http://" + server + return &DpvsAgentComm{ + listApi: LbApi{addr + listUri.Url, listUri.HttpMethod}, + noticeApis: []LbApi{{addr + noticeUri.Url, noticeUri.HttpMethod}}, + } +} + +func (comm *DpvsAgentComm) ListVirtualServices() ([]VirtualService, error) { + req, err := http.NewRequest(comm.listApi.HttpMethod, comm.listApi.Url, nil) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", "application/json") + resp, err := client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + data, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + if len(data) == 0 { + return nil, nil + } + //fmt.Printf("Code: %v, Resp: %v, Err: %v\n", resp.StatusCode, string(data), err) + var svcs DpvsAgentVsList + if err = json.Unmarshal(data, &svcs); err != nil { + return nil, err + } + vslist, err := svcs.toVsList() + if err != nil { + return nil, err + } + //fmt.Println(vslist) + return vslist, nil +} + +func (comm *DpvsAgentComm) UpdateByChecker(targets []VirtualService) error { + // TODO: support batch operation + for _, vs := range targets { + for _, rs := range vs.RSs { + ars := &DpvsAgentRsListPut{ + Items: []DpvsAgentRs{ + { + IP: rs.IP.String(), + Port: rs.Port, + Weight: rs.Weight, + Inhibited: rs.Inhibited, + }, + }, + } + data, err := json.Marshal(ars) + if err != nil { + return err + } + for _, notice := range comm.noticeApis { + url := fmt.Sprintf(notice.Url, vs.Id) + req, err := http.NewRequest(notice.HttpMethod, url, bytes.NewBuffer(data)) + req.Header.Set("Content-Type", "application/json") + resp, err := client.Do(req) + if err != nil { + return err + } + //fmt.Println("Code:", resp.Status) + if resp.StatusCode != 200 { + data, _ = io.ReadAll(resp.Body) + return fmt.Errorf("CODE: %v, ERROR: %s", resp.StatusCode, strings.TrimSpace(string(data))) + } + resp.Body.Close() + } + } + } + return nil +} diff --git a/tools/healthcheck/pkg/lb/dpvs_agent_test.go b/tools/healthcheck/pkg/lb/dpvs_agent_test.go new file mode 100644 index 000000000..2d8e00122 --- /dev/null +++ b/tools/healthcheck/pkg/lb/dpvs_agent_test.go @@ -0,0 +1,49 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package lb + +import ( + "testing" + "time" +) + +func TestListAndUpdate(t *testing.T) { + comm := NewDpvsAgentComm("") + vss, err := comm.ListVirtualServices() + if err != nil { + t.Errorf("list error: %v", err) + } + t.Logf("list Results: %v", vss) + if len(vss) < 2 { + return + } + t.Logf("Updating %v", vss[1]) + vss[1].RSs[0].Weight = 0 + vss[1].RSs[0].Inhibited = true + //vss[1].RSs[0].Port = 8081 + //vss[1].RSs[1].Weight = 100 + //vss[1].RSs[1].Inhibited = false + //vss[1].RSs[1].IP = net.ParseIP("1.2.3.4") + if err = comm.UpdateByChecker(vss[1:2]); err != nil { + t.Errorf("inhibit rs error: %v", err) + } + time.Sleep(3 * time.Second) + t.Logf("Restoring %v", vss[1]) + vss[1].RSs[0].Weight = 100 + vss[1].RSs[0].Inhibited = false + if err = comm.UpdateByChecker(vss[1:2]); err != nil { + t.Errorf("restore rs error: %v", err) + } +} diff --git a/tools/healthcheck/pkg/lb/types.go b/tools/healthcheck/pkg/lb/types.go new file mode 100644 index 000000000..bc3f8a02e --- /dev/null +++ b/tools/healthcheck/pkg/lb/types.go @@ -0,0 +1,65 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package lb + +import ( + "net" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +type Checker uint16 + +const ( + CheckerNone Checker = iota + CheckerTCP + CheckerUDP + CheckerPING +) + +type RealServer struct { + IP net.IP + Port uint16 + Weight uint16 + Inhibited bool +} + +type VirtualService struct { + Id string + Checker Checker + Protocol utils.IPProto + Port uint16 + IP net.IP + RSs []RealServer +} + +type Comm interface { + ListVirtualServices() ([]VirtualService, error) + UpdateByChecker(targets []VirtualService) error +} + +func (checker Checker) String() string { + switch checker { + case CheckerNone: + return "checker_none" + case CheckerTCP: + return "checker_tcp" + case CheckerUDP: + return "checker_udp" + case CheckerPING: + return "checker_ping" + } + return "checker_unknown" +} diff --git a/tools/healthcheck/pkg/server/server.go b/tools/healthcheck/pkg/server/server.go new file mode 100644 index 000000000..d6591d0da --- /dev/null +++ b/tools/healthcheck/pkg/server/server.go @@ -0,0 +1,72 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package server + +import ( + "fmt" + "os" + "os/signal" + "runtime" + "syscall" + + log "github.com/golang/glog" +) + +// Shutdowner is an interface for a server that can be shutdown. +type Shutdowner interface { + Shutdown() +} + +var signalNames = map[syscall.Signal]string{ + syscall.SIGINT: "SIGINT", + syscall.SIGQUIT: "SIGQUIT", + syscall.SIGTERM: "SIGTERM", + syscall.SIGUSR1: "SIGUSR1", +} + +// signalName returns a string containing the standard name for a given signal. +func signalName(s syscall.Signal) string { + if name, ok := signalNames[s]; ok { + return name + } + return fmt.Sprintf("SIG %d", s) +} + +// ShutdownHandler configures signal handling and initiates a shutdown if a +// SIGINT, SIGQUIT or SIGTERM is received by the process. +func ShutdownHandler(server Shutdowner) { + sigc := make(chan os.Signal, 3) + signal.Notify(sigc, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGUSR1) + go func() { + for s := range sigc { + name := s.String() + if sig, ok := s.(syscall.Signal); ok { + if sig == syscall.SIGUSR1 { + dumpStacks() + continue + } + name = signalName(sig) + } + log.Infof("Received %v, initiating shutdown...", name) + server.Shutdown() + } + }() +} + +func dumpStacks() { + buf := make([]byte, 16384) + buf = buf[:runtime.Stack(buf, true)] + log.Infof("=== BEGIN goroutine stack dump ===\n%s\n=== END goroutine stack dump ===", buf) +} diff --git a/tools/healthcheck/pkg/utils/net.go b/tools/healthcheck/pkg/utils/net.go new file mode 100644 index 000000000..a82e36743 --- /dev/null +++ b/tools/healthcheck/pkg/utils/net.go @@ -0,0 +1,124 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "fmt" + "net" + "syscall" +) + +// AF represents a network address family. +type AF int + +const ( + IPv4 AF = syscall.AF_INET + IPv6 AF = syscall.AF_INET6 +) + +// String returns the string representation of an AF. +func (af AF) String() string { + switch af { + case IPv4: + return "IPv4" + case IPv6: + return "IPv6" + } + return "(unknown)" +} + +// AFs returns the supported address families. +func AFs() []AF { + return []AF{IPv4, IPv6} +} + +// IP specifies an IP address. +type IP [net.IPv6len]byte + +// NewIP returns a seesaw IP initialised from a net.IP address. +func NewIP(nip net.IP) IP { + var ip IP + copy(ip[:], nip.To16()) + return ip +} + +// ParseIP parses the given string and returns a healthcheck IP initialised +// with the resulting IP address. +func ParseIP(ip string) IP { + return NewIP(net.ParseIP(ip)) +} + +// Equal returns true of the given IP addresses are equal, as determined by +// net.IP.Equal(). +func (ip IP) Equal(eip IP) bool { + return ip.IP().Equal(eip.IP()) +} + +// IP returns the net.IP representation of a healthcheck IP address. +func (ip IP) IP() net.IP { + return net.IP(ip[:]) +} + +// AF returns the address family of a healthcheck IP address. +func (ip IP) AF() AF { + if ip.IP().To4() != nil { + return IPv4 + } + return IPv6 +} + +// String returns the string representation of an IP address. +func (ip IP) String() string { + return fmt.Sprintf("%v", ip.IP()) +} + +// IPProto specifies an IP protocol. +type IPProto uint16 + +const ( + IPProtoICMP IPProto = syscall.IPPROTO_ICMP + IPProtoICMPv6 IPProto = syscall.IPPROTO_ICMPV6 + IPProtoTCP IPProto = syscall.IPPROTO_TCP + IPProtoUDP IPProto = syscall.IPPROTO_UDP +) + +// String returns the name for the given protocol value. +func (proto IPProto) String() string { + switch proto { + case IPProtoICMP: + return "ICMP" + case IPProtoICMPv6: + return "ICMPv6" + case IPProtoTCP: + return "TCP" + case IPProtoUDP: + return "UDP" + } + return fmt.Sprintf("IP(%d)", proto) +} + +func IPProtoFromStr(str string) IPProto { + switch str { + case "TCP": + return IPProtoTCP + case "UDP": + return IPProtoUDP + case "ICMP": + return IPProtoICMP + case "ICMPv6": + return IPProtoICMPv6 + } + return 0 +} diff --git a/tools/healthcheck/test/README.md b/tools/healthcheck/test/README.md new file mode 100644 index 000000000..d8977e4b6 --- /dev/null +++ b/tools/healthcheck/test/README.md @@ -0,0 +1,238 @@ +DPVS 健康检查程序压力测试 +--- + +# 测试方法 + +首先,使用 [stress-test.sh](./stress-test.sh) 脚本生成测试业务。 + +* 测试业务列表只需要有 VS 和 RS 配置,不需要配置 VIP、local IP 等。 +* 通过调整脚本 `Step 2` 中的 i, j 两个循环控制变量的范围控制产生的健康检查配置数量的多少。 +* 通过调整脚本 `Step 2` 中循环控制变量 j 的范围控制每个 VS 下配置的 RS 数量的多少,默认每个 VS 配置 5 个 RS。 + +测试业务生成后 RS 初始状态都是 UP(权重为1): + +``` +## 未启动健康检查服务时测试业务状态 +IP Virtual Server version 1.9.4 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.0.1:80 wlc + -> 192.168.19.155:8080 FullNat 1 0 0 + -> 192.168.19.156:8080 FullNat 1 0 0 + -> 192.168.19.157:8080 FullNat 1 0 0 + -> 192.168.19.158:8080 FullNat 1 0 0 + -> 192.168.19.159:8080 FullNat 1 0 0 +TCP 192.168.0.2:80 wlc + -> 192.168.19.160:8080 FullNat 1 0 0 + -> 192.168.19.161:8080 FullNat 1 0 0 + -> 192.168.19.162:8080 FullNat 1 0 0 + -> 192.168.19.163:8080 FullNat 1 0 0 + -> 192.168.19.164:8080 FullNat 1 0 0 +TCP 192.168.0.3:80 wlc + -> 192.168.19.165:8080 FullNat 1 0 0 + -> 192.168.19.166:8080 FullNat 1 0 0 +... +``` + +但实际上这些 RS 是不通的,后续健康检查程序会把所有的 RS 设置为 DOWN(权重为 0,并添加 标志)。 + +``` +## 健康检查完成测试业务状态 +IP Virtual Server version 1.9.4 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.0.1:80 wlc + -> 192.168.19.155:8080 FullNat 0 0 0 inhibited + -> 192.168.19.156:8080 FullNat 0 0 0 inhibited + -> 192.168.19.157:8080 FullNat 0 0 0 inhibited + -> 192.168.19.158:8080 FullNat 0 0 0 inhibited + -> 192.168.19.159:8080 FullNat 0 0 0 inhibited +TCP 192.168.0.2:80 wlc + -> 192.168.19.160:8080 FullNat 0 0 0 inhibited + -> 192.168.19.161:8080 FullNat 0 0 0 inhibited + -> 192.168.19.162:8080 FullNat 0 0 0 inhibited + -> 192.168.19.163:8080 FullNat 0 0 0 inhibited + -> 192.168.19.164:8080 FullNat 0 0 0 inhibited +TCP 192.168.0.3:80 wlc + -> 192.168.19.165:8080 FullNat 0 0 0 inhibited + -> 192.168.19.166:8080 FullNat 0 0 0 inhibited +... +``` + +测试业务创建后,`stress-test.sh` 脚本会循环检测当前的 RS 总数和被置为 DOWN 状态的 RS 数量。当我们启动健康检查程序后, + +```sh +./healthcheck -log_dir=./log +``` + +测试业务的 RS 会陆续由初始的 UP 状态而转为 DOWN 状态,我们根据 RS 被置为 DOWN 的数量的增长速度即可评估健康检查程序的并发性能。 + +# 测试数据 + +* RS 数量:测试脚本自动创建的 RS 总量 +* 初始探测耗时:健康检查程序启动到看到第一个 RS 被置为 DOWN 的时间。 +* 耗时(5分位):从第一个 RS 被置为 DOWN 到 50% 的 RS 被置为 DOWN 的时间。 +* 耗时(9分位):从第一个 RS 被置为 DOWN 到 90% 的 RS 被置为 DOWN 的时间。 +* 总耗时:从第一个 RS 被置为 DOWN 到所有的 RS 被置为 DOWN 的时间。 +* CPU 占用:健康检查程序的 CPU 使用量(用 iftop 命令观测得到)。 +* 内存占用:健康检查程序的内存使用量(用 iftop 命令观测得到)。 + +| RS数量 | 初始探测耗时 | 耗时(5分位) | 耗时(9分位) | 总耗时 | CPU占用 | 内存占用 | +| ------ | ------------ | ------------ | ----------- | ------ | ------- | -------- | +| 0 | 0 | 0 | 0 | 0 | 0.1核 | 100MB | +| 1040 | 6s | 1s | 2s | 2s | 0.1核 | 110MB | +| 5080 | 6s | 1s | 2s | 3s | 0.4核 | 160MB | +| 10160 | 5s | 4s | 6s | 8s | 0.8核 | 200MB | +| 26670 | 5s | 9s | 16s | 34s | 1.8核 | 560MB | +| 52070 | 7s | 7s | 33s | 90s | 4.4核 | 1120MB | + +> 说明: 健康检查程序默认配置的 retry 为 1 次、timeout 为 1s、周期为 3s,因此初始探测时间理论上为 1s(timeout) + 3s (delay loop) + 1s (timeout) = 5s。该数据和我们测试数据基本一致,不计入性能延迟。 + + +# 测试日志 + +**1040 个 RS** + +``` +[2023-06-02.17:08:51] total: 1040, inhibited: 0 +[2023-06-02.17:08:55] total: 1040, inhibited: 0 +[2023-06-02.17:08:56] total: 1040, inhibited: 0 +[2023-06-02.17:08:57] total: 1040, inhibited: 0 +[2023-06-02.17:08:58] total: 1040, inhibited: 321 +[2023-06-02.17:08:59] total: 1040, inhibited: 709 +[2023-06-02.17:09:00] total: 1040, inhibited: 1040 +[2023-06-02.17:09:01] total: 1040, inhibited: 1040 +[2023-06-02.17:09:02] total: 1040, inhibited: 1040 +[2023-06-02.17:09:03] total: 1040, inhibited: 1040 +``` + +**5080 个 RS** + +``` +[2023-06-02.17:02:17] total: 5080, inhibited: 0 +[2023-06-02.17:02:18] total: 5080, inhibited: 0 +[2023-06-02.17:02:19] total: 5080, inhibited: 0 +[2023-06-02.17:02:20] total: 5080, inhibited: 0 +[2023-06-02.17:02:21] total: 5080, inhibited: 1474 +[2023-06-02.17:02:22] total: 5080, inhibited: 3340 +[2023-06-02.17:02:23] total: 5080, inhibited: 5078 +[2023-06-02.17:02:25] total: 5080, inhibited: 5080 +[2023-06-02.17:02:26] total: 5080, inhibited: 5080 +[2023-06-02.17:02:27] total: 5080, inhibited: 5080 +[2023-06-02.17:02:28] total: 5080, inhibited: 5080 +``` + +**10160 个 RS** + +``` +[2023-06-02.16:51:21] total: 10160, inhibited: 0 +[2023-06-02.16:51:23] total: 10160, inhibited: 0 +[2023-06-02.16:51:24] total: 10160, inhibited: 0 +[2023-06-02.16:51:25] total: 10160, inhibited: 0 +[2023-06-02.16:51:27] total: 10160, inhibited: 0 +[2023-06-02.16:51:28] total: 10160, inhibited: 52 +[2023-06-02.16:51:29] total: 10160, inhibited: 2050 +[2023-06-02.16:51:30] total: 10160, inhibited: 4021 +[2023-06-02.16:51:32] total: 10160, inhibited: 6027 +[2023-06-02.16:51:33] total: 10160, inhibited: 8094 +[2023-06-02.16:51:34] total: 10160, inhibited: 10116 +[2023-06-02.16:51:36] total: 10160, inhibited: 10160 +[2023-06-02.16:51:37] total: 10160, inhibited: 10160 +[2023-06-02.16:51:38] total: 10160, inhibited: 10160 +[2023-06-02.16:51:39] total: 10160, inhibited: 10160 +``` + +**26670 个 RS** + +``` +[2023-06-02.16:44:45] total: 26670, inhibited: 0 +[2023-06-02.16:44:46] total: 26670, inhibited: 0 +[2023-06-02.16:44:48] total: 26670, inhibited: 0 +[2023-06-02.16:44:50] total: 26670, inhibited: 0 +[2023-06-02.16:44:51] total: 26670, inhibited: 0 +[2023-06-02.16:44:53] total: 26670, inhibited: 1857 +[2023-06-02.16:44:55] total: 26670, inhibited: 4389 +[2023-06-02.16:44:56] total: 26670, inhibited: 6887 +[2023-06-02.16:44:58] total: 26670, inhibited: 9388 +[2023-06-02.16:45:00] total: 26670, inhibited: 12166 +[2023-06-02.16:45:02] total: 26670, inhibited: 15079 +[2023-06-02.16:45:03] total: 26670, inhibited: 17741 +[2023-06-02.16:45:05] total: 26670, inhibited: 20307 +[2023-06-02.16:45:07] total: 26670, inhibited: 23046 +[2023-06-02.16:45:09] total: 26670, inhibited: 25967 +[2023-06-02.16:45:10] total: 26670, inhibited: 26665 +[2023-06-02.16:45:12] total: 26670, inhibited: 26665 +[2023-06-02.16:45:14] total: 26670, inhibited: 26666 +[2023-06-02.16:45:16] total: 26670, inhibited: 26667 +[2023-06-02.16:45:18] total: 26670, inhibited: 26667 +[2023-06-02.16:45:19] total: 26670, inhibited: 26667 +[2023-06-02.16:45:21] total: 26670, inhibited: 26668 +[2023-06-02.16:45:23] total: 26670, inhibited: 26669 +[2023-06-02.16:45:25] total: 26670, inhibited: 26669 +[2023-06-02.16:45:26] total: 26670, inhibited: 26670 +[2023-06-02.16:45:28] total: 26670, inhibited: 26670 +[2023-06-02.16:45:30] total: 26670, inhibited: 26670 +[2023-06-02.16:45:32] total: 26670, inhibited: 26670 +[2023-06-02.16:45:34] total: 26670, inhibited: 26670 +``` + +**52070 个 RS** + +``` +[2023-06-02.16:37:39] total: 52070, inhibited: 0 +[2023-06-02.16:37:42] total: 52070, inhibited: 0 +[2023-06-02.16:37:44] total: 52070, inhibited: 0 +[2023-06-02.16:37:46] total: 52070, inhibited: 0 +[2023-06-02.16:37:48] total: 52070, inhibited: 1 +[2023-06-02.16:37:51] total: 52070, inhibited: 3032 +[2023-06-02.16:37:53] total: 52070, inhibited: 6743 +[2023-06-02.16:37:55] total: 52070, inhibited: 10129 +[2023-06-02.16:37:58] total: 52070, inhibited: 13849 +[2023-06-02.16:38:00] total: 52070, inhibited: 17478 +[2023-06-02.16:38:03] total: 52070, inhibited: 21177 +[2023-06-02.16:38:05] total: 52070, inhibited: 25168 +[2023-06-02.16:38:08] total: 52070, inhibited: 28867 +[2023-06-02.16:38:10] total: 52070, inhibited: 32909 +[2023-06-02.16:38:13] total: 52070, inhibited: 37034 +[2023-06-02.16:38:16] total: 52070, inhibited: 40798 +[2023-06-02.16:38:18] total: 52070, inhibited: 44471 +[2023-06-02.16:38:21] total: 52070, inhibited: 48355 +[2023-06-02.16:38:23] total: 52070, inhibited: 51830 +[2023-06-02.16:38:26] total: 52070, inhibited: 52025 +[2023-06-02.16:38:29] total: 52070, inhibited: 52030 +[2023-06-02.16:38:31] total: 52070, inhibited: 52034 +[2023-06-02.16:38:34] total: 52070, inhibited: 52035 +[2023-06-02.16:38:36] total: 52070, inhibited: 52035 +[2023-06-02.16:38:39] total: 52070, inhibited: 52035 +[2023-06-02.16:38:41] total: 52070, inhibited: 52035 +[2023-06-02.16:38:44] total: 52070, inhibited: 52035 +[2023-06-02.16:38:46] total: 52070, inhibited: 52035 +[2023-06-02.16:38:49] total: 52070, inhibited: 52035 +[2023-06-02.16:38:51] total: 52070, inhibited: 52037 +[2023-06-02.16:38:53] total: 52070, inhibited: 52042 +[2023-06-02.16:38:56] total: 52070, inhibited: 52042 +[2023-06-02.16:38:58] total: 52070, inhibited: 52047 +[2023-06-02.16:39:01] total: 52070, inhibited: 52049 +[2023-06-02.16:39:03] total: 52070, inhibited: 52052 +[2023-06-02.16:39:06] total: 52070, inhibited: 52053 +[2023-06-02.16:39:08] total: 52070, inhibited: 52057 +[2023-06-02.16:39:11] total: 52070, inhibited: 52060 +[2023-06-02.16:39:13] total: 52070, inhibited: 52060 +[2023-06-02.16:39:16] total: 52070, inhibited: 52065 +[2023-06-02.16:39:18] total: 52070, inhibited: 52070 +[2023-06-02.16:39:21] total: 52070, inhibited: 52070 +[2023-06-02.16:39:23] total: 52070, inhibited: 52070 +[2023-06-02.16:39:25] total: 52070, inhibited: 52070 +[2023-06-02.16:39:28] total: 52070, inhibited: 52070 +``` + +# 结论 + +1. 健康检查程序处理能力约为 3000 RS/s; +2. RS 状态变化不超过 5000 RS/s 时,健康检查程序能够快速摘除或恢复故障的 RS; +3. RS 状态变化 10000 RS/s 时,健康检查程序可以在 8s 内摘除或恢复故障的 RS; +3. 可以支持 50000+ RS/s 的 RS 状态变化,但约 50% 的 RS 故障可能得不到及时发现。 + +此外,在 50000+ 个 RS 配置处于健康状态稳定的场景下,单个 RS 故障的摘除和恢复时间约为 5s,与只有此 1 个 RS 配置时的处理时间区别不大。 + +> 说明: 以上结论采用健康检查程序默认配置时测试得到,测试过程中 DPVS 服务无数据面流量。 diff --git a/tools/healthcheck/test/dpvs-agent-api.sh b/tools/healthcheck/test/dpvs-agent-api.sh new file mode 100755 index 000000000..a5013c206 --- /dev/null +++ b/tools/healthcheck/test/dpvs-agent-api.sh @@ -0,0 +1,31 @@ +# Copyright 2023 IQiYi Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import requests +import json + +def UpdateService(): + payload="{\"Items\":[{\"inhibited\":false,\"ip\":\"192.168.88.68\",\"port\":80,\"weight\":100}]}" + url = "http://127.0.0.1:6600/v2/vs/192.168.88.1-80-TCP/rs?healthcheck=true" + headers = {'content-type': 'application/json'} + r = requests.put(url, headers=headers, data=payload) + print(r, r.json()) + + url = "http://127.0.0.1:6600/v2/vs/192.168.88.1-80-TCP" + headers = {'content-type': 'application/json'} + r = requests.get(url, headers=headers, data=payload) + print(r, r.json()) + +if __name__ == '__main__': + UpdateService() diff --git a/tools/healthcheck/test/stress-test.sh b/tools/healthcheck/test/stress-test.sh new file mode 100755 index 000000000..6ea848f85 --- /dev/null +++ b/tools/healthcheck/test/stress-test.sh @@ -0,0 +1,67 @@ +#!/bin/sh +# Copyright 2023 IQiYi Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +## Step 1. +echo -e "Cleaning existing services ..." +ipvsadm -C +sleep 5 + +now=$(date +%F.%T) +echo -e "[$now] Start" + +## Step 2. +echo -e "Adding test services ..." +rsid=5000 +for i in $(seq 0 32) +do + for j in $(seq 1 255) + do + vip="192.168.${i}.${j}" + flag="-t" + #udp=$((j%2)) + #[ "$udp" -eq 1 ] && flag="-u" + #echo $vip $flag + ipvsadm -A $flag $vip:80 + for k in $(seq 5) + do + seg3=$((rsid/255)) + seg4=$((rsid%255)) + rsid=$((rsid+1)) + rip="192.168.${seg3}.${seg4}" + #echo "-> $rip" + ipvsadm -a $flag $vip:80 -r $rip:8080 -b -w 100 + done + #dpip addr add $vip/32 dev dpdk0 + done +done + +## Step 3. +echo "" +echo "****************************************" +echo -e "Start healthcheck program on your own." +echo "****************************************" +echo "" + +## Step 4. +echo -e "Do Checking ..." +while true +do + now=$(date +%F.%T) + total=$(ipvsadm -ln| grep FullNat -c) + down=$(ipvsadm -ln| grep inhibited -c) + echo "[$now] total: $total, inhibited: $down" + sleep 1 +done From 29df3face52306692eb6b825385ad414ae34ef5e Mon Sep 17 00:00:00 2001 From: huangyichen Date: Mon, 10 Jul 2023 14:18:11 +0800 Subject: [PATCH 049/105] Add dpvs-agent source code --- tools/dpvs-agent/.gitignore | 2 + tools/dpvs-agent/Makefile | 32 + tools/dpvs-agent/README.md | 4 + .../cmd/device/delete_device_name_addr.go | 45 + .../cmd/device/delete_device_name_netlink.go | 49 + .../device/delete_device_name_netlink_addr.go | 68 + .../cmd/device/delete_device_name_route.go | 59 + .../cmd/device/delete_device_name_vlan.go | 46 + .../cmd/device/get_device_name_nic.go | 78 + tools/dpvs-agent/cmd/device/ioctl.go | 23 + .../cmd/device/put_device_name_addr.go | 57 + .../cmd/device/put_device_name_netlink.go | 46 + .../device/put_device_name_netlink_addr.go | 72 + .../cmd/device/put_device_name_nic.go | 63 + .../cmd/device/put_device_name_route.go | 66 + .../cmd/device/put_device_name_vlan.go | 71 + .../device/todo_delete_device_name_linux.go | 25 + .../todo_delete_device_name_linux_addr.go | 117 + .../dpvs-agent/cmd/device/todo_get_device.go | 1 + .../cmd/device/todo_get_device_name_addr.go | 1 + .../cmd/device/todo_get_device_name_linux.go | 1 + .../device/todo_get_device_name_linux_addr.go | 1 + .../cmd/device/todo_get_device_name_route.go | 1 + .../cmd/device/todo_get_device_name_vlan.go | 1 + .../cmd/device/todo_put_device_name_linux.go | 3 + .../device/todo_put_device_name_linux_addr.go | 132 + .../dpvs-agent/cmd/dpvs-agent-server/Makefile | 26 + .../cmd/dpvs-agent-server/api_init.go | 181 + .../dpvs-agent/cmd/dpvs-agent-server/main.go | 55 + .../dpvs-agent/cmd/ipvs/delete_vs_vip_port.go | 45 + .../cmd/ipvs/delete_vs_vip_port_allow.go | 56 + .../cmd/ipvs/delete_vs_vip_port_deny.go | 56 + .../cmd/ipvs/delete_vs_vip_port_laddr.go | 52 + .../cmd/ipvs/delete_vs_vip_port_rs.go | 56 + tools/dpvs-agent/cmd/ipvs/get_vs.go | 71 + tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go | 79 + .../cmd/ipvs/get_vs_vip_port_laddr.go | 50 + .../cmd/ipvs/post_vs_vip_port_rs.go | 59 + tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go | 96 + .../cmd/ipvs/put_vs_vip_port_allow.go | 58 + .../cmd/ipvs/put_vs_vip_port_deny.go | 58 + .../cmd/ipvs/put_vs_vip_port_laddr.go | 55 + .../dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go | 74 + .../cmd/ipvs/todo_get_vs_vip_port_rs.go | 1 + tools/dpvs-agent/dpvs-agent-api.yaml | 1373 +++++ tools/dpvs-agent/go.mod | 40 + tools/dpvs-agent/go.sum | 232 + tools/dpvs-agent/models/acl_addr_list.go | 116 + tools/dpvs-agent/models/addr_range.go | 53 + tools/dpvs-agent/models/cert_auth_spec.go | 50 + tools/dpvs-agent/models/dest_check_spec.go | 84 + tools/dpvs-agent/models/error.go | 27 + tools/dpvs-agent/models/inet_addr_spec.go | 56 + .../models/local_address_expand_list.go | 116 + .../models/local_address_spec_expand.go | 62 + .../models/local_address_spec_tiny.go | 53 + .../models/local_address_tiny_list.go | 116 + tools/dpvs-agent/models/match_spec.go | 156 + tools/dpvs-agent/models/nic_device_detail.go | 232 + .../models/nic_device_queue_data.go | 27 + tools/dpvs-agent/models/nic_device_spec.go | 150 + .../dpvs-agent/models/nic_device_spec_list.go | 116 + tools/dpvs-agent/models/nic_device_stats.go | 342 ++ .../models/real_server_expand_list.go | 116 + .../models/real_server_spec_expand.go | 150 + .../models/real_server_spec_tiny.go | 129 + .../models/real_server_tiny_list.go | 116 + tools/dpvs-agent/models/route_spec.go | 71 + tools/dpvs-agent/models/server_stats.go | 77 + tools/dpvs-agent/models/status.go | 114 + .../dpvs-agent/models/virtual_server_list.go | 116 + .../models/virtual_server_spec_expand.go | 438 ++ .../models/virtual_server_spec_tiny.go | 183 + tools/dpvs-agent/models/vlan_spec.go | 56 + tools/dpvs-agent/pkg/ipc/pool/conn.go | 316 ++ tools/dpvs-agent/pkg/ipc/pool/pool.go | 523 ++ tools/dpvs-agent/pkg/ipc/pool/util.go | 12 + tools/dpvs-agent/pkg/ipc/proto/reader.go | 335 ++ tools/dpvs-agent/pkg/ipc/proto/writer.go | 167 + tools/dpvs-agent/pkg/ipc/types/certificate.go | 369 ++ tools/dpvs-agent/pkg/ipc/types/const.go | 334 ++ tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go | 56 + tools/dpvs-agent/pkg/ipc/types/dpvsstats.go | 114 + tools/dpvs-agent/pkg/ipc/types/getmodel.go | 169 + tools/dpvs-agent/pkg/ipc/types/inetaddr.go | 571 +++ tools/dpvs-agent/pkg/ipc/types/iprange.go | 43 + tools/dpvs-agent/pkg/ipc/types/kni.go | 314 ++ tools/dpvs-agent/pkg/ipc/types/laddr.go | 492 ++ tools/dpvs-agent/pkg/ipc/types/method.go | 1 + tools/dpvs-agent/pkg/ipc/types/netif.go | 728 +++ tools/dpvs-agent/pkg/ipc/types/realserver.go | 633 +++ tools/dpvs-agent/pkg/ipc/types/route.go | 470 ++ tools/dpvs-agent/pkg/ipc/types/sockmsg.go | 132 + tools/dpvs-agent/pkg/ipc/types/utility.go | 11 + .../dpvs-agent/pkg/ipc/types/virtualserver.go | 693 +++ tools/dpvs-agent/pkg/ipc/types/vlan.go | 312 ++ .../restapi/configure_dpvs_agent.go | 172 + tools/dpvs-agent/restapi/doc.go | 19 + tools/dpvs-agent/restapi/embedded_spec.go | 4449 +++++++++++++++++ .../device/delete_device_name_addr.go | 56 + .../delete_device_name_addr_parameters.go | 145 + .../delete_device_name_addr_responses.go | 98 + .../delete_device_name_addr_urlbuilder.go | 115 + .../device/delete_device_name_netlink.go | 56 + .../device/delete_device_name_netlink_addr.go | 56 + ...ete_device_name_netlink_addr_parameters.go | 101 + ...lete_device_name_netlink_addr_responses.go | 98 + ...ete_device_name_netlink_addr_urlbuilder.go | 99 + .../delete_device_name_netlink_parameters.go | 71 + .../delete_device_name_netlink_responses.go | 98 + .../delete_device_name_netlink_urlbuilder.go | 99 + .../device/delete_device_name_route.go | 56 + .../delete_device_name_route_parameters.go | 101 + .../delete_device_name_route_responses.go | 98 + .../delete_device_name_route_urlbuilder.go | 99 + .../device/delete_device_name_vlan.go | 56 + .../delete_device_name_vlan_parameters.go | 71 + .../delete_device_name_vlan_responses.go | 98 + .../delete_device_name_vlan_urlbuilder.go | 99 + .../restapi/operations/device/get_device.go | 56 + .../operations/device/get_device_name_addr.go | 56 + .../device/get_device_name_addr_parameters.go | 153 + .../device/get_device_name_addr_responses.go | 98 + .../device/get_device_name_addr_urlbuilder.go | 124 + .../device/get_device_name_netlink.go | 56 + .../device/get_device_name_netlink_addr.go | 56 + ...get_device_name_netlink_addr_parameters.go | 116 + .../get_device_name_netlink_addr_responses.go | 98 + ...get_device_name_netlink_addr_urlbuilder.go | 115 + .../get_device_name_netlink_parameters.go | 116 + .../get_device_name_netlink_responses.go | 98 + .../get_device_name_netlink_urlbuilder.go | 115 + .../operations/device/get_device_name_nic.go | 56 + .../device/get_device_name_nic_parameters.go | 153 + .../device/get_device_name_nic_responses.go | 102 + .../device/get_device_name_nic_urlbuilder.go | 124 + .../device/get_device_name_route.go | 56 + .../get_device_name_route_parameters.go | 116 + .../device/get_device_name_route_responses.go | 98 + .../get_device_name_route_urlbuilder.go | 115 + .../operations/device/get_device_name_vlan.go | 56 + .../device/get_device_name_vlan_parameters.go | 116 + .../device/get_device_name_vlan_responses.go | 98 + .../device/get_device_name_vlan_urlbuilder.go | 115 + .../device/get_device_parameters.go | 92 + .../operations/device/get_device_responses.go | 55 + .../device/get_device_urlbuilder.go | 105 + .../operations/device/put_device_name_addr.go | 56 + .../device/put_device_name_addr_parameters.go | 145 + .../device/put_device_name_addr_responses.go | 141 + .../device/put_device_name_addr_urlbuilder.go | 115 + .../device/put_device_name_netlink.go | 56 + .../device/put_device_name_netlink_addr.go | 56 + ...put_device_name_netlink_addr_parameters.go | 101 + .../put_device_name_netlink_addr_responses.go | 98 + ...put_device_name_netlink_addr_urlbuilder.go | 99 + .../put_device_name_netlink_parameters.go | 71 + .../put_device_name_netlink_responses.go | 98 + .../put_device_name_netlink_urlbuilder.go | 99 + .../operations/device/put_device_name_nic.go | 56 + .../device/put_device_name_nic_parameters.go | 218 + .../device/put_device_name_nic_responses.go | 98 + .../device/put_device_name_nic_urlbuilder.go | 131 + .../device/put_device_name_route.go | 56 + .../put_device_name_route_parameters.go | 101 + .../device/put_device_name_route_responses.go | 141 + .../put_device_name_route_urlbuilder.go | 99 + .../operations/device/put_device_name_vlan.go | 56 + .../device/put_device_name_vlan_parameters.go | 101 + .../device/put_device_name_vlan_responses.go | 98 + .../device/put_device_name_vlan_urlbuilder.go | 99 + .../restapi/operations/dpvs_agent_api.go | 736 +++ .../virtualserver/delete_vs_vip_port.go | 56 + .../virtualserver/delete_vs_vip_port_allow.go | 56 + .../delete_vs_vip_port_allow_parameters.go | 101 + .../delete_vs_vip_port_allow_responses.go | 211 + .../delete_vs_vip_port_allow_urlbuilder.go | 99 + .../virtualserver/delete_vs_vip_port_deny.go | 56 + .../delete_vs_vip_port_deny_parameters.go | 101 + .../delete_vs_vip_port_deny_responses.go | 211 + .../delete_vs_vip_port_deny_urlbuilder.go | 99 + .../virtualserver/delete_vs_vip_port_laddr.go | 56 + .../delete_vs_vip_port_laddr_parameters.go | 101 + .../delete_vs_vip_port_laddr_responses.go | 186 + .../delete_vs_vip_port_laddr_urlbuilder.go | 99 + .../delete_vs_vip_port_parameters.go | 71 + .../delete_vs_vip_port_responses.go | 143 + .../virtualserver/delete_vs_vip_port_rs.go | 56 + .../delete_vs_vip_port_rs_parameters.go | 101 + .../delete_vs_vip_port_rs_responses.go | 211 + .../delete_vs_vip_port_rs_urlbuilder.go | 99 + .../delete_vs_vip_port_urlbuilder.go | 99 + .../operations/virtualserver/get_vs.go | 56 + .../virtualserver/get_vs_parameters.go | 92 + .../virtualserver/get_vs_responses.go | 59 + .../virtualserver/get_vs_urlbuilder.go | 105 + .../virtualserver/get_vs_vip_port.go | 56 + .../virtualserver/get_vs_vip_port_allow.go | 56 + .../get_vs_vip_port_allow_parameters.go | 71 + .../get_vs_vip_port_allow_responses.go | 98 + .../get_vs_vip_port_allow_urlbuilder.go | 99 + .../virtualserver/get_vs_vip_port_deny.go | 56 + .../get_vs_vip_port_deny_parameters.go | 71 + .../get_vs_vip_port_deny_responses.go | 98 + .../get_vs_vip_port_deny_urlbuilder.go | 99 + .../virtualserver/get_vs_vip_port_laddr.go | 56 + .../get_vs_vip_port_laddr_parameters.go | 116 + .../get_vs_vip_port_laddr_responses.go | 102 + .../get_vs_vip_port_laddr_urlbuilder.go | 115 + .../get_vs_vip_port_parameters.go | 116 + .../get_vs_vip_port_responses.go | 102 + .../virtualserver/get_vs_vip_port_rs.go | 56 + .../get_vs_vip_port_rs_parameters.go | 116 + .../get_vs_vip_port_rs_responses.go | 98 + .../get_vs_vip_port_rs_urlbuilder.go | 115 + .../get_vs_vip_port_urlbuilder.go | 115 + .../virtualserver/post_vs_vip_port_allow.go | 56 + .../post_vs_vip_port_allow_parameters.go | 101 + .../post_vs_vip_port_allow_responses.go | 229 + .../post_vs_vip_port_allow_urlbuilder.go | 99 + .../virtualserver/post_vs_vip_port_deny.go | 56 + .../post_vs_vip_port_deny_parameters.go | 101 + .../post_vs_vip_port_deny_responses.go | 229 + .../post_vs_vip_port_deny_urlbuilder.go | 99 + .../virtualserver/post_vs_vip_port_rs.go | 56 + .../post_vs_vip_port_rs_parameters.go | 101 + .../post_vs_vip_port_rs_responses.go | 229 + .../post_vs_vip_port_rs_urlbuilder.go | 99 + .../virtualserver/put_vs_vip_port.go | 56 + .../virtualserver/put_vs_vip_port_allow.go | 56 + .../put_vs_vip_port_allow_parameters.go | 101 + .../put_vs_vip_port_allow_responses.go | 229 + .../put_vs_vip_port_allow_urlbuilder.go | 99 + .../virtualserver/put_vs_vip_port_deny.go | 56 + .../put_vs_vip_port_deny_parameters.go | 101 + .../put_vs_vip_port_deny_responses.go | 229 + .../put_vs_vip_port_deny_urlbuilder.go | 99 + .../virtualserver/put_vs_vip_port_laddr.go | 56 + .../put_vs_vip_port_laddr_parameters.go | 101 + .../put_vs_vip_port_laddr_responses.go | 229 + .../put_vs_vip_port_laddr_urlbuilder.go | 99 + .../put_vs_vip_port_parameters.go | 101 + .../put_vs_vip_port_responses.go | 229 + .../virtualserver/put_vs_vip_port_rs.go | 56 + .../put_vs_vip_port_rs_parameters.go | 145 + .../put_vs_vip_port_rs_responses.go | 229 + .../put_vs_vip_port_rs_urlbuilder.go | 115 + .../put_vs_vip_port_urlbuilder.go | 99 + tools/dpvs-agent/restapi/server.go | 507 ++ 249 files changed, 34985 insertions(+) create mode 100644 tools/dpvs-agent/.gitignore create mode 100644 tools/dpvs-agent/Makefile create mode 100644 tools/dpvs-agent/README.md create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_addr.go create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_netlink.go create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_route.go create mode 100644 tools/dpvs-agent/cmd/device/delete_device_name_vlan.go create mode 100644 tools/dpvs-agent/cmd/device/get_device_name_nic.go create mode 100644 tools/dpvs-agent/cmd/device/ioctl.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_addr.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_netlink.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_nic.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_route.go create mode 100644 tools/dpvs-agent/cmd/device/put_device_name_vlan.go create mode 100644 tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go create mode 100644 tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_route.go create mode 100644 tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go create mode 100644 tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go create mode 100644 tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go create mode 100644 tools/dpvs-agent/cmd/dpvs-agent-server/Makefile create mode 100644 tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go create mode 100644 tools/dpvs-agent/cmd/dpvs-agent-server/main.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/cmd/ipvs/get_vs.go create mode 100644 tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go create mode 100644 tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/dpvs-agent-api.yaml create mode 100644 tools/dpvs-agent/go.mod create mode 100644 tools/dpvs-agent/go.sum create mode 100644 tools/dpvs-agent/models/acl_addr_list.go create mode 100644 tools/dpvs-agent/models/addr_range.go create mode 100644 tools/dpvs-agent/models/cert_auth_spec.go create mode 100644 tools/dpvs-agent/models/dest_check_spec.go create mode 100644 tools/dpvs-agent/models/error.go create mode 100644 tools/dpvs-agent/models/inet_addr_spec.go create mode 100644 tools/dpvs-agent/models/local_address_expand_list.go create mode 100644 tools/dpvs-agent/models/local_address_spec_expand.go create mode 100644 tools/dpvs-agent/models/local_address_spec_tiny.go create mode 100644 tools/dpvs-agent/models/local_address_tiny_list.go create mode 100644 tools/dpvs-agent/models/match_spec.go create mode 100644 tools/dpvs-agent/models/nic_device_detail.go create mode 100644 tools/dpvs-agent/models/nic_device_queue_data.go create mode 100644 tools/dpvs-agent/models/nic_device_spec.go create mode 100644 tools/dpvs-agent/models/nic_device_spec_list.go create mode 100644 tools/dpvs-agent/models/nic_device_stats.go create mode 100644 tools/dpvs-agent/models/real_server_expand_list.go create mode 100644 tools/dpvs-agent/models/real_server_spec_expand.go create mode 100644 tools/dpvs-agent/models/real_server_spec_tiny.go create mode 100644 tools/dpvs-agent/models/real_server_tiny_list.go create mode 100644 tools/dpvs-agent/models/route_spec.go create mode 100644 tools/dpvs-agent/models/server_stats.go create mode 100644 tools/dpvs-agent/models/status.go create mode 100644 tools/dpvs-agent/models/virtual_server_list.go create mode 100644 tools/dpvs-agent/models/virtual_server_spec_expand.go create mode 100644 tools/dpvs-agent/models/virtual_server_spec_tiny.go create mode 100644 tools/dpvs-agent/models/vlan_spec.go create mode 100644 tools/dpvs-agent/pkg/ipc/pool/conn.go create mode 100644 tools/dpvs-agent/pkg/ipc/pool/pool.go create mode 100644 tools/dpvs-agent/pkg/ipc/pool/util.go create mode 100644 tools/dpvs-agent/pkg/ipc/proto/reader.go create mode 100644 tools/dpvs-agent/pkg/ipc/proto/writer.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/certificate.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/const.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/dpvsstats.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/getmodel.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/inetaddr.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/iprange.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/kni.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/laddr.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/method.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/netif.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/realserver.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/route.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/sockmsg.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/utility.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/virtualserver.go create mode 100644 tools/dpvs-agent/pkg/ipc/types/vlan.go create mode 100644 tools/dpvs-agent/restapi/configure_dpvs_agent.go create mode 100644 tools/dpvs-agent/restapi/doc.go create mode 100644 tools/dpvs-agent/restapi/embedded_spec.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_route.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_route_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_route_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_route_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_nic.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_nic_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_nic_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_nic_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_route.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_route_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_route_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_route_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_vlan.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/get_device_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_nic.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_nic_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_nic_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_route.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_route_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_route_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_route_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_vlan.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/dpvs_agent_api.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_parameters.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_responses.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go create mode 100644 tools/dpvs-agent/restapi/server.go diff --git a/tools/dpvs-agent/.gitignore b/tools/dpvs-agent/.gitignore new file mode 100644 index 000000000..496ec7999 --- /dev/null +++ b/tools/dpvs-agent/.gitignore @@ -0,0 +1,2 @@ +bin/ +cmd/dpvs-agent-server/dpvs-agent diff --git a/tools/dpvs-agent/Makefile b/tools/dpvs-agent/Makefile new file mode 100644 index 000000000..fb8e5ff18 --- /dev/null +++ b/tools/dpvs-agent/Makefile @@ -0,0 +1,32 @@ +MAKE = make +SUBDIRS = cmd/dpvs-agent-server +INSDIR = $(PWD)/bin +export INSDIR + +OPENAPISPEC = dpvs-agent-api.yaml + +all: + for i in $(SUBDIRS); do $(MAKE) -C $$i || exit 1; done + +clean: + for i in $(SUBDIRS); do $(MAKE) -C $$i clean || exit 1; done + +install:all + -mkdir -p $(INSDIR) + for i in $(SUBDIRS); do $(MAKE) -C $$i install || exit 1; done + +uninstall: + for i in $(SUBDIRS); do $(MAKE) -C $$i uninstall || exit 1; done + +openapi: $(OPENAPISPEC) +ifeq ($(shell swagger version),) + $(error "golang `swagger` command not found. You can install it with `go get github.com/go-swagger/go-swagger@v0.30.4`") +endif + swagger generate server -A dpvs-agent -f $< + git checkout cmd/dpvs-agent-server/main.go + +license: +ifeq ($(shell addlicense 2>&1|grep Usage),) + $(error "`addlicense` command not found. You can install it with `go install github.com/google/addlicense`") +endif + @addlicense -check -c "IQiYi Inc." -l apache -ignore dpvs/** . || /bin/true diff --git a/tools/dpvs-agent/README.md b/tools/dpvs-agent/README.md new file mode 100644 index 000000000..0c25a01d1 --- /dev/null +++ b/tools/dpvs-agent/README.md @@ -0,0 +1,4 @@ +#build +``` +swagger generate server -A dpvs-agent -f ./dpvs-agent-api.yaml +``` diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_addr.go b/tools/dpvs-agent/cmd/device/delete_device_name_addr.go new file mode 100644 index 000000000..68635af05 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_addr.go @@ -0,0 +1,45 @@ +package device + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delDeviceAddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelDeviceAddr(cp *pool.ConnPool, parentLogger hclog.Logger) *delDeviceAddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelDeviceAddr") + } + return &delDeviceAddr{connPool: cp, logger: logger} +} + +// dpip addr add 192.168.88.16/32 dev dpdk0.102 +func (h *delDeviceAddr) Handle(params apiDevice.DeleteDeviceNameAddrParams) middleware.Responder { + addr := types.NewInetAddrDetail() + addr.SetAddr(params.Spec.Addr) + addr.SetIfName(params.Name) + + result := addr.Del(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Delete addr from device success.", "Device Name", params.Name, "Addr", params.Spec.Addr) + return apiDevice.NewDeleteDeviceNameAddrOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Delete a not exist addr from device done.", "Device Name", params.Name, "Addr", params.Spec.Addr, "result", result.String()) + return apiDevice.NewDeleteDeviceNameAddrOK() + default: + h.logger.Error("Delete addr from device failed.", "Device Name", params.Name, "Addr", params.Spec.Addr, "result", result.String()) + } + + return apiDevice.NewDeleteDeviceNameAddrInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go b/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go new file mode 100644 index 000000000..d4fd6ba54 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go @@ -0,0 +1,49 @@ +package device + +import ( + "fmt" + + "github.com/vishvananda/netlink" + + "github.com/dpvs-agent/pkg/ipc/pool" + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +// ip link set xxx down +type setDeviceNetlinkDown struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewSetDeviceNetlinkDown(cp *pool.ConnPool, parentLogger hclog.Logger) *setDeviceNetlinkDown { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("SetDeviceNetlinkDown") + } + return &setDeviceNetlinkDown{connPool: cp, logger: logger} +} + +func (h *setDeviceNetlinkDown) Handle(params apiDevice.DeleteDeviceNameNetlinkParams) middleware.Responder { + cmd := fmt.Sprintf("ip link set %s down", params.Name) + dev, err := netlink.LinkByName(params.Name) + if err != nil { + h.logger.Error("Get iface failed.", "Name", params.Name, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkInternalServerError() + } + + if err := netlink.LinkSetDown(dev); err != nil { + h.logger.Error("Set iface down failed.", "cmd", cmd, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkInternalServerError() + } + + if err := netlink.LinkDel(dev); err != nil { + h.logger.Error("Delete iface failed.", "Name", params.Name, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkInternalServerError() + } + + h.logger.Info("Set down and remove iface success.", "cmd", cmd) + return apiDevice.NewDeleteDeviceNameNetlinkOK() +} diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go b/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go new file mode 100644 index 000000000..0ed8b943e --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go @@ -0,0 +1,68 @@ +package device + +import ( + "fmt" + "net" + "strings" + + "github.com/vishvananda/netlink" + + "github.com/dpvs-agent/pkg/ipc/pool" + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delDeviceNetlinkAddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelDeviceNetlinkAddr(cp *pool.ConnPool, parentLogger hclog.Logger) *delDeviceNetlinkAddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelDeviceNetlinkAddr") + } + return &delDeviceNetlinkAddr{connPool: cp, logger: logger} +} + +func (h *delDeviceNetlinkAddr) Handle(params apiDevice.DeleteDeviceNameNetlinkAddrParams) middleware.Responder { + var cidr string + if strings.Count(params.Spec.Addr, "/") == 0 { + ip := net.ParseIP(params.Spec.Addr) + if ip == nil { + return apiDevice.NewDeleteDeviceNameNetlinkAddrInternalServerError() + } + + if ip.To4() != nil { + cidr = params.Spec.Addr + "/32" + } else { + cidr = params.Spec.Addr + "/128" + } + } + + ip, ipnet, err := net.ParseCIDR(cidr) + if err != nil { + return apiDevice.NewDeleteDeviceNameNetlinkAddrInternalServerError() + } + + cmd := fmt.Sprintf("ip addr del %s dev %s", cidr, params.Name) + + ipnet.IP = ip + addr := &netlink.Addr{IPNet: ipnet} + + link, err := netlink.LinkByName(params.Name) + if err != nil { + h.logger.Error("Get linux network device by name failed.", "device Name", params.Name, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkAddrInternalServerError() + } + + if err := netlink.AddrDel(link, addr); err != nil { + h.logger.Error("linux network operation failed.", "cmd", cmd, "Error", err.Error()) + return apiDevice.NewDeleteDeviceNameNetlinkAddrInternalServerError() + } + + h.logger.Info("linux network operation success.", "cmd", cmd) + return apiDevice.NewDeleteDeviceNameNetlinkAddrOK() +} diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_route.go b/tools/dpvs-agent/cmd/device/delete_device_name_route.go new file mode 100644 index 000000000..eabc0f976 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_route.go @@ -0,0 +1,59 @@ +package device + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delDeviceRoute struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelDeviceRoute(cp *pool.ConnPool, parentLogger hclog.Logger) *delDeviceRoute { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelDeviceRoute") + } + return &delDeviceRoute{connPool: cp, logger: logger} +} + +// dpip del route 192.168.88.16/32 dev dpdk0.102 +func (h *delDeviceRoute) Handle(params apiDevice.DeleteDeviceNameRouteParams) middleware.Responder { + + // dest [addr], [mask] and [dev name] is useful of delete route only + route := types.NewRouteDetail() + route.SetDevice(params.Name) + if params.Spec == nil { + // FIXME: front error + return apiDevice.NewDeleteDeviceNameRouteInternalServerError() + } + + route.SetDst(params.Spec.Dst) + route.SetScope(params.Spec.Scope) + /* + route.SetSrc(params.Spec.Src) + route.SetGateway(params.Spec.Gateway) + route.SetScope(params.Spec.Scope) + route.SetMtu(params.Spec.Mtu) + route.SetMetric(params.Spec.Metric) + */ + result := route.Del(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Delete route success.", "Device Name", params.Name, "route Dst", params.Spec.Dst) + return apiDevice.NewDeleteDeviceNameRouteOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Delete not exist route done.", "Device Name", params.Name, "route Dst", params.Spec.Dst, "result", result.String()) + return apiDevice.NewDeleteDeviceNameRouteOK() + default: + h.logger.Error("Delete route failed.", "Device Name", params.Name, "route Dst", params.Spec.Dst, "result", result.String()) + } + + return apiDevice.NewDeleteDeviceNameRouteInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go b/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go new file mode 100644 index 000000000..abd2e5620 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go @@ -0,0 +1,46 @@ +package device + +import ( + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delDeviceVlan struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelDeviceVlan(cp *pool.ConnPool, parentLogger hclog.Logger) *delDeviceVlan { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelDeviceVlan") + } + return &delDeviceVlan{connPool: cp, logger: logger} +} + +// dpip vlan del dpdk0.102 +func (h *delDeviceVlan) Handle(params apiDevice.DeleteDeviceNameVlanParams) middleware.Responder { + // vlan device delete is need device name only + vlan := types.NewVlanDevice() + vlan.SetIfName(params.Name) + + result := vlan.Del(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Delete dpvs vlan success.", "Vlan Name", params.Name) + return apiDevice.NewDeleteDeviceNameVlanOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Delete dpvs vlan done.", "Vlan Name", params.Name, "result", result.String()) + return apiDevice.NewDeleteDeviceNameVlanOK() + default: + h.logger.Error("Delete dpvs vlan failed.", "Vlan Name", params.Name, "result", result.String()) + } + + return apiDevice.NewDeleteDeviceNameVlanInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/get_device_name_nic.go b/tools/dpvs-agent/cmd/device/get_device_name_nic.go new file mode 100644 index 000000000..2cedd92a2 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/get_device_name_nic.go @@ -0,0 +1,78 @@ +package device + +import ( + "strings" + + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type getDeviceNameNic struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewGetDeviceNameNic(cp *pool.ConnPool, parentLogger hclog.Logger) *getDeviceNameNic { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("GetDeviceNameNic") + } + return &getDeviceNameNic{connPool: cp, logger: logger} +} + +// dpip link show xxx +func (h *getDeviceNameNic) Handle(params apiDevice.GetDeviceNameNicParams) middleware.Responder { + name := make([]byte, 0x10) + copy(name[:], params.Name[:]) + + desc := types.NewNetifNicDesc() + list, err := desc.GetPortList(h.connPool, h.logger) + if err != types.EDPVS_OK { + h.logger.Info("Get netif ports failed.", "Error", err.String()) + return apiDevice.NewGetDeviceNameNicInternalServerError() + } + + h.logger.Info("Get netif port success.", "port list", list) + exist := false + specModels := new(models.NicDeviceSpecList) + specModels.Items = make([]*models.NicDeviceSpec, len(list.Entries)) + + for i, entry := range list.Entries { + specModels.Items[i] = new(models.NicDeviceSpec) + if strings.EqualFold(strings.ToLower(string(name)), strings.ToLower(entry.GetName())) { + exist = true + } + + portName := entry.GetName() + desc.SetName(portName) + detail, err := desc.GetPortBasic(h.connPool, h.logger) + if err != types.EDPVS_OK { + h.logger.Error("Get netif port base info failed.", "portName", portName, "Error", err.String()) + return apiDevice.NewGetDeviceNameNicInternalServerError() + } + h.logger.Info("Get netif port base info success.", "portName", portName, "port detail", detail) + + stats, err := desc.GetPortStats(h.connPool, h.logger) + if err != types.EDPVS_OK { + h.logger.Error("Get netif port stats info failed.", "portName", portName, "Error", err.String()) + return apiDevice.NewGetDeviceNameNicInternalServerError() + } + h.logger.Info("Get netif port stats info success.", "portName", portName, "port stats", stats) + + specModels.Items[i].Detail = detail.GetModel() + specModels.Items[i].Stats = stats.GetModel() + } + + if exist { + if *params.Stats { + } + } + + return apiDevice.NewGetDeviceNameNicOK().WithPayload(specModels) +} diff --git a/tools/dpvs-agent/cmd/device/ioctl.go b/tools/dpvs-agent/cmd/device/ioctl.go new file mode 100644 index 000000000..ab3297857 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/ioctl.go @@ -0,0 +1,23 @@ +package device + +import ( + "golang.org/x/sys/unix" +) + +func ioctl(fd int, code, data uintptr) error { + _, _, errno := unix.Syscall(unix.SYS_IOCTL, uintptr(fd), code, data) + if errno != 0 { + return errno + } + return nil +} + +type socketAddr4Request struct { + name [unix.IFNAMSIZ]byte + addr unix.RawSockaddrInet4 +} + +type socketAddr6Request struct { + name [unix.IFNAMSIZ]byte + addr unix.RawSockaddrInet6 +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_addr.go b/tools/dpvs-agent/cmd/device/put_device_name_addr.go new file mode 100644 index 000000000..03cd75c82 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_addr.go @@ -0,0 +1,57 @@ +package device + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceAddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceAddr(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceAddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceAddr") + } + return &putDeviceAddr{connPool: cp, logger: logger} +} + +// dpip addr add 192.168.88.16/32 dev dpdk0.102 +func (h *putDeviceAddr) Handle(params apiDevice.PutDeviceNameAddrParams) middleware.Responder { + addr := types.NewInetAddrDetail() + + if params.Spec == nil { + return apiDevice.NewPutDeviceNameAddrInternalServerError() + } + + addr.SetAddr(params.Spec.Addr) + addr.SetScope(params.Spec.Scope) + addr.SetBCast(params.Spec.Broadcast) + addr.SetIfName(params.Name) + if params.Sapool != nil && *params.Sapool { + addr.SetFlags("sapool") + } + // addr.SetValidLft(prarms.Spec.ValidLft) + // addr.SetPreferedLft(prarms.Spec.ValidLft) + + result := addr.Add(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Add addr from device success.", "Device Name", params.Name, "Addr", params.Spec.Addr) + return apiDevice.NewPutDeviceNameAddrOK() + case types.EDPVS_EXIST: + h.logger.Warn("Device already exist addr, add done.", "Device Name", params.Name, "Addr", params.Spec.Addr, "result", result.String()) + return apiDevice.NewPutDeviceNameAddrOK() + default: + h.logger.Error("Add addr from device failed.", "Device Name", params.Name, "Addr", params.Spec.Addr, "result", result.String()) + } + + return apiDevice.NewPutDeviceNameAddrInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_netlink.go b/tools/dpvs-agent/cmd/device/put_device_name_netlink.go new file mode 100644 index 000000000..1a643647c --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_netlink.go @@ -0,0 +1,46 @@ +package device + +import ( + "fmt" + "syscall" + + "github.com/vishvananda/netlink" + + "github.com/dpvs-agent/pkg/ipc/pool" + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +// ip link set xxx up +type setDeviceNetlinkUp struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewSetDeviceNetlinkUp(cp *pool.ConnPool, parentLogger hclog.Logger) *setDeviceNetlinkUp { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("SetDeviceNetlinkUp") + } + return &setDeviceNetlinkUp{connPool: cp, logger: logger} +} + +func (h *setDeviceNetlinkUp) Handle(params apiDevice.PutDeviceNameNetlinkParams) middleware.Responder { + dev := &netlink.Device{LinkAttrs: netlink.LinkAttrs{MTU: 1500, Name: params.Name}} + + if err := netlink.LinkAdd(dev); err != syscall.EEXIST { + h.logger.Error("Check device isExist failed.", "Device Name", params.Name, "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkInternalServerError() + } + + if err := netlink.LinkSetUp(dev); err != nil { + h.logger.Error("Set device link up failed.", "Device Name", params.Name, "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkInternalServerError() + } + + cmd := fmt.Sprintf("ip link set %s up", params.Name) + h.logger.Info("Set device link up success.", "cmd", cmd) + return apiDevice.NewPutDeviceNameNetlinkOK() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go b/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go new file mode 100644 index 000000000..a114ba8fe --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go @@ -0,0 +1,72 @@ +package device + +import ( + "fmt" + "net" + "strings" + + "github.com/vishvananda/netlink" + + "github.com/dpvs-agent/pkg/ipc/pool" + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceNetlinkAddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceNetlinkAddr(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceNetlinkAddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceNetlinkAddr") + } + return &putDeviceNetlinkAddr{connPool: cp, logger: logger} +} + +// ip addr add 10.0.0.1/32 dev eth0 +func (h *putDeviceNetlinkAddr) Handle(params apiDevice.PutDeviceNameNetlinkAddrParams) middleware.Responder { + // h.logger.Info("/v2/device/", params.Name, "/netlink/addr ", params.Spec.Addr) + var cidr string + if strings.Count(params.Spec.Addr, "/") == 0 { + ip := net.ParseIP(params.Spec.Addr) + if ip == nil { + h.logger.Info("Parse IP failed.", "Addr", params.Spec.Addr) + return apiDevice.NewPutDeviceNameNetlinkAddrInternalServerError() + } + if ip.To4() != nil { + cidr = params.Spec.Addr + "/32" + } else { + cidr = params.Spec.Addr + "/128" + } + } else { + cidr = params.Spec.Addr + } + + ip, ipnet, err := net.ParseCIDR(cidr) + if err != nil { + h.logger.Error("Parse CIDR failed.", "cidr", cidr, "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkAddrInternalServerError() + } + + ipnet.IP = ip + addr := &netlink.Addr{IPNet: ipnet} + + link, err := netlink.LinkByName(params.Name) + if err != nil { + h.logger.Error("netlink.LinkByName() failed.", "Device Name", params.Name, "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkAddrInternalServerError() + } + + if err := netlink.AddrAdd(link, addr); err != nil { + h.logger.Error("netlink.AddrAdd() failed.", "Error", err.Error()) + return apiDevice.NewPutDeviceNameNetlinkAddrInternalServerError() + } + + cmd := fmt.Sprintf("ip addr add %s dev %s", cidr, params.Name) + h.logger.Info("Device add Addr success.", "cmd", cmd) + return apiDevice.NewPutDeviceNameNetlinkAddrOK() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_nic.go b/tools/dpvs-agent/cmd/device/put_device_name_nic.go new file mode 100644 index 000000000..419026058 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_nic.go @@ -0,0 +1,63 @@ +package device + +import ( + "fmt" + + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceNameNic struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceNameNic(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceNameNic { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceNameNic") + } + return &putDeviceNameNic{connPool: cp, logger: logger} +} + +// ITEM [promisc|forward2kni|tc-ingress|tc-egress] / [link] +// VALUE [on|off] / [up|down] +// dpip link set nic-name $ITEM $VALUE +func (h *putDeviceNameNic) Handle(params apiDevice.PutDeviceNameNicParams) middleware.Responder { + set := false + cmd := "" + desc := types.NewNetifNicDesc() + if !set { + set = desc.SetFwd2Kni(params.Name, *params.Forward2Kni) + cmd = fmt.Sprintf("dpip link set %s %s", params.Name, params.Forward2Kni) + } + if !set { + set = desc.SetLink(params.Name, *params.Link) + cmd = fmt.Sprintf("dpip link set %s %s", params.Name, params.Link) + } + if !set { + set = desc.SetPromisc(params.Name, *params.Promisc) + cmd = fmt.Sprintf("dpip link set %s %s", params.Name, params.Promisc) + } + + if !set { + h.logger.Error("dpdk link port set failed.", "Name", params.Name) + return apiDevice.NewPutDeviceNameNicInternalServerError() + } + + result := desc.Set(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Set dpdk port success.", "cmd", cmd) + return apiDevice.NewPutDeviceNameNicOK() + default: + h.logger.Info("Set dpdk port failed.", "cmd", cmd, "result", result.String()) + } + + return apiDevice.NewPutDeviceNameNicInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_route.go b/tools/dpvs-agent/cmd/device/put_device_name_route.go new file mode 100644 index 000000000..d9ddea942 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_route.go @@ -0,0 +1,66 @@ +package device + +import ( + "fmt" + + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceRoute struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceRoute(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceRoute { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceRoute") + } + return &putDeviceRoute{connPool: cp, logger: logger} +} + +// dpip route add 192.168.88.16/32 dev dpdk0.102 scope kni_host +func (h *putDeviceRoute) Handle(params apiDevice.PutDeviceNameRouteParams) middleware.Responder { + + // dest [addr], [mask] and [dev name] is useful of delete route only + route := types.NewRouteDetail() + route.SetDevice(params.Name) + if params.Spec == nil { + // FIXME return front invalid + return apiDevice.NewPutDeviceNameRouteInternalServerError() + } + + src := "" + route.SetDst(params.Spec.Dst) + if route.SetSrc(params.Spec.Src) { + src = fmt.Sprintf("src %s", params.Spec.Src) + } + + gateway := "" + if route.SetGateway(params.Spec.Gateway) { + gateway = fmt.Sprintf("via %s", params.Spec.Gateway) + } + route.SetScope(params.Spec.Scope) + route.SetMtu(params.Spec.Mtu) + route.SetMetric(params.Spec.Metric) + + cmd := fmt.Sprintf("dpip route add %s %s dev %s %s", params.Spec.Dst, gateway, params.Name, src) + result := route.Add(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Set dpdk route success.", "cmd", cmd) + return apiDevice.NewPutDeviceNameRouteCreated() + // case types.EDPVS_EXIST: + // FIXME: update ? return apiDevice.NewPutDeviceNameRouteOK() + default: + h.logger.Info("Set dpdk route failed.", "cmd", cmd, "result", result.String()) + } + + return apiDevice.NewPutDeviceNameRouteInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/put_device_name_vlan.go b/tools/dpvs-agent/cmd/device/put_device_name_vlan.go new file mode 100644 index 000000000..4ec011bd7 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/put_device_name_vlan.go @@ -0,0 +1,71 @@ +package device + +import ( + "fmt" + "strconv" + "strings" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putDeviceVlan struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutDeviceVlan(cp *pool.ConnPool, parentLogger hclog.Logger) *putDeviceVlan { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutDeviceVlan") + } + return &putDeviceVlan{connPool: cp, logger: logger} +} + +// dpip vlan add dpdk0.102 link dpdk0 id 102 +func (h *putDeviceVlan) Handle(params apiDevice.PutDeviceNameVlanParams) middleware.Responder { + vlanName := strings.ToLower(params.Name) + + items := strings.Split(vlanName, ".") + if len(items) != 2 { + return apiDevice.NewPutDeviceNameVlanInternalServerError() + } + + dev := params.Spec.Device + if len(dev) == 0 { + dev = items[0] + } + + id := params.Spec.ID + if len(id) == 0 { + id = items[1] + } + + cmd := fmt.Sprintf("dpip vlan add %s link %s id %s", params.Name, dev, id) + + vlan := types.NewVlanDevice() + vlan.SetIfName(vlanName) + vlan.SetRealDev(dev) + i, err := strconv.Atoi(id) + if err != nil { + return apiDevice.NewPutDeviceNameVlanInternalServerError() + } + vlan.SetId(uint16(i)) + + result := vlan.Add(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Set dpdk vlan success.", "cmd", cmd) + return apiDevice.NewDeleteDeviceNameVlanOK() + default: + h.logger.Error("Set dpdk vlan failed.", "cmd", cmd, "result", result.String()) + } + + return apiDevice.NewDeleteDeviceNameVlanInternalServerError() +} diff --git a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go new file mode 100644 index 000000000..9e8771521 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go @@ -0,0 +1,25 @@ +package device + +/* +import ( + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" +) + +type putDeviceLinux struct { + connPool *pool.ConnPool +} + +func NewPutDeviceLinux(cp *pool.ConnPool) *putDeviceLinux { + return &putDeviceVlan{connPool: cp} +} + +// dpip vlan add dpdk0.102 link dpdk0 id 102 +func (h *putDeviceLinux) Handle(params apiDevice.PutDeviceNameLinuxParams) middleware.Responder { +} +*/ diff --git a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go new file mode 100644 index 000000000..ce1c644e4 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go @@ -0,0 +1,117 @@ +package device + +/* +// SIOCDIFADDR + +import ( + "net" + "strconv" + "strings" + "unsafe" + + "golang.org/x/sys/unix" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" +) + +type deleteDeviceNameLinuxAddr struct { + connPool *pool.ConnPool +} + +func NewDeleteDeviceNameLinuxAddr(cp *pool.ConnPool) *deleteDeviceNameLinuxAddr { + return &deleteDeviceNameLinuxAddr{connPool: cp} +} + +func (h *deleteDeviceNameLinuxAddr) Handler(params *apiDevice.DeleteDeviceNameLinuxAddrParams) middleware.Responder { + if len(params.Spec.Addr) == 0 { + return apiDevice.NewDeleteDeviceNameLinuxAddrInternalServerError() + } + + items := strings.Split(params.Spec.Addr, "/") + + addr := net.ParseIP(items[0]) + if addr == nil { + return apiDevice.NewDeleteDeviceNameLinuxAddrInternalServerError() + } + + if addr.To4() != nil { + mask := 32 + if len(items) > 1 { + m, err := strconv.Atoi(items[1]) + if err == nil { + mask = m + } + } + if err := delAddr4(params.Name, addr, mask); err != nil { + return apiDevice.NewDeleteDeviceNameLinuxAddrInternalServerError() + } + } else { + mask := 128 + if len(items) > 1 { + m, err := strconv.Atoi(items[1]) + if err == nil { + mask = m + } + } + if err := setAddr6(params.Name, addr, mask); err != nil { + return apiDevice.NewDeleteDeviceNameLinuxAddrInternalServerError() + } + } + return apiDevice.NewDeleteDeviceNameLinuxAddrOK() +} + +func delAddr4(name string, ip net.IP, mask int) error { + fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0) + if err != nil { + return err + } + + defer unix.Close(fd) + sa := socketAddr4Request{} + sa.addr.Family = unix.AF_INET + copy(sa.name[:], name) + + buf, err := ip.MarshalText() + if err != nil { + return err + } + + copy(sa.addr.Addr[:], buf) + // delete address + if err := ioctl(fd, unix.SIOCDIFADDR, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + return nil +} + +func delAddr6(name string, ip net.IP, mask int) error { + fd, err := unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0) + if err != nil { + return err + } + + defer unix.Close(fd) + sa := socketAddr6Request{} + sa.addr.Family = unix.AF_INET6 + copy(sa.name[:], name) + + buf, err := ip.MarshalText() + if err != nil { + return err + } + + copy(sa.addr.Addr[:], buf) + // delete address + if err := ioctl(fd, unix.SIOCDIFADDR, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + return nil +} +*/ diff --git a/tools/dpvs-agent/cmd/device/todo_get_device.go b/tools/dpvs-agent/cmd/device/todo_get_device.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go new file mode 100644 index 000000000..76a9bfa32 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go @@ -0,0 +1 @@ +package device diff --git a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go new file mode 100644 index 000000000..a1f95a889 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go @@ -0,0 +1,3 @@ +package device + +// http://blog.pytool.com/language/clang/socket/linux-socket-ifreq/ diff --git a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go new file mode 100644 index 000000000..b56f455b6 --- /dev/null +++ b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go @@ -0,0 +1,132 @@ +package device + +/* +import ( + "net" + "strconv" + "strings" + "unsafe" + + "golang.org/x/sys/unix" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + + apiDevice "github.com/dpvs-agent/restapi/operations/device" + + "github.com/go-openapi/runtime/middleware" +) + +// ip addr add 192.168.88.68/32 dev dpdk0.102.kni + +type putDeviceNameLinuxAddr struct { + connPool *pool.ConnPool +} + +func NewPutDeviceNameLinux(cp *pool.ConnPool) *putDeviceNameLinuxAddr { + return &putDeviceNameLinuxAddr{connPool: cp} +} + +func (h *putDeviceNameLinuxAddr) Handler(params *apiDevice.PutDeviceNameLinuxAddrParams) middleware.Responder { + if len(params.Spec.Addr) == 0 { + return apiDevice.NewPutDeviceNameLinuxAddrInternalServerError() + } + + items := strings.Split(params.Spec.Addr, "/") + + addr := net.ParseIP(items[0]) + if addr == nil { + return apiDevice.NewPutDeviceNameLinuxAddrInternalServerError() + } + + if addr.To4() != nil { + mask := 32 + if len(items) > 1 { + m, err := strconv.Atoi(items[1]) + if err == nil { + mask = m + } + } + if err := setAddr4(params.Name, addr, mask); err != nil { + return apiDevice.NewPutDeviceNameLinuxAddrInternalServerError() + } + } else { + mask := 128 + if len(items) > 1 { + m, err := strconv.Atoi(items[1]) + if err == nil { + mask = m + } + } + if err := setAddr6(params.Name, addr, mask); err != nil { + return apiDevice.NewPutDeviceNameLinuxAddrInternalServerError() + } + } + + return apiDevice.NewPutDeviceNameLinuxAddrOK() +} + +func setAddr4(name string, ip net.IP, mask int) error { + fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, 0) + if err != nil { + return err + } + + defer unix.Close(fd) + sa := socketAddr4Request{} + sa.addr.Family = unix.AF_INET + copy(sa.name[:], name) + + buf, err := ip.MarshalText() + if err != nil { + return err + } + + copy(sa.addr.Addr[:], buf) + // Set address + if err := ioctl(fd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + // Set netmask + mbuf := net.CIDRMask(mask, 32) + copy(sa.addr.Addr[:], []byte(mbuf)) + if err := ioctl(fd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + return nil +} + +func setAddr6(name string, ip net.IP, mask int) error { + fd, err := unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, 0) + if err != nil { + return err + } + + defer unix.Close(fd) + sa := socketAddr6Request{} + sa.addr.Family = unix.AF_INET6 + copy(sa.name[:], name) + + buf, err := ip.MarshalText() + if err != nil { + return err + } + + copy(sa.addr.Addr[:], buf) + // Set address + if err := ioctl(fd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + // Set netmask + mbuf := net.CIDRMask(mask, 128) + copy(sa.addr.Addr[:], []byte(mbuf)) + if err := ioctl(fd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&sa))); err != nil { + return err + } + + return nil +} +*/ diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile b/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile new file mode 100644 index 000000000..9ba2dd914 --- /dev/null +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile @@ -0,0 +1,26 @@ +TARGET := dpvs-agent + +GO ?= go +LD_FLAGS = -ldflags="-s -w" +GO_BUILD = CGO_ENABLED=0 $(GO) build $(LD_FLAGS) +GO_CLEAN = $(GO) clean +INSTALL = install +RM = rm + +.PHONY: all $(TARGET) clean install + +all: $(TARGET) + +$(TARGET): + $(GO_BUILD) -o $@ + +clean: + $(GO_CLEAN) + -$(RM) $(TARGET) + +install: $(TARGET) + $(INSTALL) -m 0755 -d $(INSDIR) + $(INSTALL) -m 0744 $(TARGET) $(INSDIR) + +uninstall: + -$(RM) -f $(TARGET) $(INSDIR)/$(TARGET) diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go new file mode 100644 index 000000000..f4d5393e9 --- /dev/null +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go @@ -0,0 +1,181 @@ +package main + +import ( + "context" + "errors" + "net" + "os" + "strings" + "time" + + "github.com/hashicorp/go-hclog" + "github.com/lestrrat-go/file-rotatelogs" + + "github.com/dpvs-agent/cmd/device" + "github.com/dpvs-agent/cmd/ipvs" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/restapi" + "github.com/dpvs-agent/restapi/operations" +) + +var ( + IpcSocket string = "/var/run/dpvs.ipc" +) + +type DpvsAgentServer struct { + LogDir string `long:"log-dir" description:"default log dir is /var/log/ And log name dpvs-agent.log" default:"/var/log/"` + IpcSocketPath string `long:"ipc-sockopt-path" description:"default ipc socket path /var/run/dpvs.ipc" default:"/var/run/dpvs.ipc"` + restapi.Server +} + +func unixDialer(ctx context.Context) (net.Conn, error) { + retry := 0 + d := net.Dialer{Timeout: 10 * time.Second} + raddr := net.UnixAddr{Name: "/var/run/dpvs.ipc", Net: "unix"} + for { + conn, err := d.DialContext(ctx, "unix", raddr.String()) + if err == nil { + return conn, nil + } + // FIXME: A weird fact was observed in tests of large concurrency that the previous + // "DailContext" returned the error "resource temporarily unavailable" occasionally. + // No solution to it has found yet, thus just retry as a compromise. + if strings.Contains(err.Error(), "resource temporarily unavailable") != true { + return nil, err + } + retry++ + if retry > 10 { + return nil, err + } + } + return nil, errors.New("unknown error") +} + +func (agent *DpvsAgentServer) instantiateAPI(restAPI *operations.DpvsAgentAPI) { + if strings.HasSuffix(agent.IpcSocketPath, ".ipc") { + s, err := os.Stat(agent.IpcSocketPath) + if err == nil { + if !s.IsDir() { + IpcSocket = agent.IpcSocketPath + } + } + } + + cp := pool.NewConnPool(&pool.Options{ + Dialer: unixDialer, + PoolSize: 1024, + // PoolTimeout: -1, + // IdleTimeout: -1, + // IdleCheckFrequency: -1, + }) + + logDir := "/var/log/" + if len(agent.LogDir) > 1 { // avoid root path '/' set + s, err := os.Stat(agent.LogDir) + if err == nil { + if s.IsDir() { + logDir = agent.LogDir + } + } + } + + sep := "/" + if strings.HasSuffix(logDir, "/") { + sep = "" + } + + logFile := strings.Join([]string{logDir, "dpvs-agent.log"}, sep) + // logOpt := &hclog.LoggerOptions{Name: logFile} + var logOpt *hclog.LoggerOptions + logFileNamePattern := strings.Join([]string{logFile, "%Y%m%d%H%M"}, "-") + logRotationInterval := 1 * time.Hour + + logF, err := rotatelogs.New( + logFileNamePattern, + rotatelogs.WithLinkName(logFile), + rotatelogs.WithRotationTime(logRotationInterval), + ) + // f, err := os.Create(logFile) + if err == nil { + logOpt = &hclog.LoggerOptions{Name: logFile, Output: logF} + } else { + os.Exit(-1) + } + + hclog.SetDefault(hclog.New(logOpt)) + + logger := hclog.Default().Named("main") + + // delete + restAPI.VirtualserverDeleteVsVipPortHandler = ipvs.NewDelVsItem(cp, logger) + restAPI.VirtualserverDeleteVsVipPortLaddrHandler = ipvs.NewDelVsLaddr(cp, logger) + restAPI.VirtualserverDeleteVsVipPortRsHandler = ipvs.NewDelVsRs(cp, logger) + restAPI.VirtualserverDeleteVsVipPortDenyHandler = ipvs.NewDelVsDeny(cp, logger) + restAPI.VirtualserverDeleteVsVipPortAllowHandler = ipvs.NewDelVsAllow(cp, logger) + + // get + restAPI.VirtualserverGetVsHandler = ipvs.NewGetVs(cp, logger) + restAPI.VirtualserverGetVsVipPortHandler = ipvs.NewGetVsVipPort(cp, logger) + restAPI.VirtualserverGetVsVipPortLaddrHandler = ipvs.NewGetVsLaddr(cp, logger) + + // put + restAPI.VirtualserverPutVsVipPortHandler = ipvs.NewPutVsItem(cp, logger) + restAPI.VirtualserverPutVsVipPortLaddrHandler = ipvs.NewPutVsLaddr(cp, logger) + restAPI.VirtualserverPutVsVipPortRsHandler = ipvs.NewPutVsRs(cp, logger) + restAPI.VirtualserverPutVsVipPortDenyHandler = ipvs.NewPutVsDeny(cp, logger) + restAPI.VirtualserverPutVsVipPortAllowHandler = ipvs.NewPutVsAllow(cp, logger) + + // post + restAPI.VirtualserverPostVsVipPortRsHandler = ipvs.NewPostVsRs(cp, logger) + + // get + // restAPI.DeviceGetDeviceNameAddrHandler + // restAPI.DeviceGetDeviceNameRouteHandler + // restAPI.DeviceGetDeviceNameVlanHandler + restAPI.DeviceGetDeviceNameNicHandler = device.NewGetDeviceNameNic(cp, logger) + + // put + restAPI.DevicePutDeviceNameNetlinkHandler = device.NewSetDeviceNetlinkUp(cp, logger) + restAPI.DevicePutDeviceNameAddrHandler = device.NewPutDeviceAddr(cp, logger) + restAPI.DevicePutDeviceNameRouteHandler = device.NewPutDeviceRoute(cp, logger) + restAPI.DevicePutDeviceNameVlanHandler = device.NewPutDeviceVlan(cp, logger) + restAPI.DevicePutDeviceNameNetlinkAddrHandler = device.NewPutDeviceNetlinkAddr(cp, logger) + restAPI.DevicePutDeviceNameNicHandler = device.NewPutDeviceNameNic(cp, logger) + + // delete + restAPI.DeviceDeleteDeviceNameAddrHandler = device.NewDelDeviceAddr(cp, logger) + restAPI.DeviceDeleteDeviceNameRouteHandler = device.NewDelDeviceRoute(cp, logger) + restAPI.DeviceDeleteDeviceNameVlanHandler = device.NewDelDeviceVlan(cp, logger) + restAPI.DeviceDeleteDeviceNameNetlinkAddrHandler = device.NewDelDeviceNetlinkAddr(cp, logger) +} + +func (agent *DpvsAgentServer) InstantiateServer(api *operations.DpvsAgentAPI) *restapi.Server { + agent.instantiateAPI(api) + + server := restapi.NewServer(api) + server.ConfigureAPI() + + server.EnabledListeners = make([]string, len(agent.EnabledListeners)) + copy(server.EnabledListeners, agent.EnabledListeners) + server.CleanupTimeout = agent.CleanupTimeout + server.GracefulTimeout = agent.GracefulTimeout + server.MaxHeaderSize = agent.MaxHeaderSize + server.SocketPath = agent.SocketPath + server.Host = agent.Host + server.Port = agent.Port + server.ListenLimit = agent.ListenLimit + server.KeepAlive = agent.KeepAlive + server.ReadTimeout = agent.ReadTimeout + server.WriteTimeout = agent.WriteTimeout + server.TLSHost = agent.TLSHost + server.TLSPort = agent.TLSPort + server.TLSCertificate = agent.TLSCertificate + server.TLSCertificateKey = agent.TLSCertificateKey + server.TLSCACertificate = agent.TLSCACertificate + server.TLSListenLimit = agent.TLSListenLimit + server.TLSKeepAlive = agent.TLSKeepAlive + server.TLSReadTimeout = agent.TLSReadTimeout + server.TLSWriteTimeout = agent.TLSWriteTimeout + + return server +} diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/main.go b/tools/dpvs-agent/cmd/dpvs-agent-server/main.go new file mode 100644 index 000000000..11912e77e --- /dev/null +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/main.go @@ -0,0 +1,55 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package main + +import ( + "log" + "os" + + "github.com/go-openapi/loads" + flags "github.com/jessevdk/go-flags" + + "github.com/dpvs-agent/restapi" + "github.com/dpvs-agent/restapi/operations" +) + +// This file was generated by the swagger tool. +// Make sure not to overwrite this file after you generated it because all your edits would be lost! +func main() { + swaggerSpec, err := loads.Embedded(restapi.SwaggerJSON, restapi.FlatSwaggerJSON) + if err != nil { + log.Fatalln(err) + } + + api := operations.NewDpvsAgentAPI(swaggerSpec) + + agent := &DpvsAgentServer{} + + parser := flags.NewParser(agent, flags.Default) + parser.ShortDescription = "dpvs agent" + parser.LongDescription = "dpvs agent api" + for _, optsGroup := range api.CommandLineOptionsGroups { + _, err := parser.AddGroup(optsGroup.ShortDescription, optsGroup.LongDescription, optsGroup.Options) + if err != nil { + log.Fatalln(err) + } + } + + if _, err := parser.Parse(); err != nil { + code := 1 + if fe, ok := err.(*flags.Error); ok { + if fe.Type == flags.ErrHelp { + code = 0 + } + } + os.Exit(code) + } + + server := agent.InstantiateServer(api) + defer server.Shutdown() + + if err := server.Serve(); err != nil { + log.Fatalln(err) + } + +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go new file mode 100644 index 000000000..f9c4a645c --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go @@ -0,0 +1,45 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsItem struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsItem(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsItem { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPort") + } + return &delVsItem{connPool: cp, logger: logger} +} + +func (h *delVsItem) Handle(params apiVs.DeleteVsVipPortParams) middleware.Responder { + vs := types.NewVirtualServerSpec() + if err := vs.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortFailure() + } + + result := vs.Del(h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Del virtual server success.", "VipPort", params.VipPort) + return apiVs.NewDeleteVsVipPortOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Del a not exist virtual server done.", "VipPort", params.VipPort, "result", result.String()) + return apiVs.NewDeleteVsVipPortNotFound() + default: + h.logger.Error("Del virtual server failed.", "VipPort", params.VipPort, "result", result.String()) + } + return apiVs.NewDeleteVsVipPortFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go new file mode 100644 index 000000000..0d8678f2b --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +package ipvs + +import ( + "net" + + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsAllow struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsAllow(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsAllow { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPortAllow") + } + return &delVsAllow{connPool: cp, logger: logger} +} + +func (h *delVsAllow) Handle(params apiVs.DeleteVsVipPortAllowParams) middleware.Responder { + spec := types.NewCertificateAuthoritySpec() + if err := spec.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortAllowInvalidFrontend() + } + + failed := false + for _, allow := range params.ACL.Items { + if net.ParseIP(allow.Addr) == nil { + h.logger.Error("Invalid ip addr del.", "VipPort", params.VipPort, "Addr", allow.Addr) + return apiVs.NewDeleteVsVipPortAllowInvalidFrontend() + } + spec.SetSrc(allow.Addr) + + if result := spec.Del(h.connPool, false, h.logger); result != types.EDPVS_OK { + failed = true + h.logger.Error("IP Addr delete from white list failed.", "VipPort", params.VipPort, "Addr", allow.Addr, "result", result.String()) + continue + } + h.logger.Info("IP Addr delete from white list success.", "VipPort", params.VipPort, "Addr", allow.Addr) + } + + if failed { + return apiVs.NewDeleteVsVipPortAllowInvalidBackend() + } + + return apiVs.NewDeleteVsVipPortAllowOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go new file mode 100644 index 000000000..1352386d8 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +package ipvs + +import ( + "net" + + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsDeny struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsDeny(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsDeny { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPortDeny") + } + return &delVsDeny{connPool: cp, logger: logger} +} + +func (h *delVsDeny) Handle(params apiVs.DeleteVsVipPortDenyParams) middleware.Responder { + spec := types.NewCertificateAuthoritySpec() + if err := spec.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortDenyInvalidFrontend() + } + + failed := false + for _, deny := range params.ACL.Items { + if net.ParseIP(deny.Addr) == nil { + h.logger.Error("Invalid ip addr del.", "VipPort", params.VipPort, "Addr", deny.Addr) + return apiVs.NewDeleteVsVipPortDenyInvalidFrontend() + } + spec.SetSrc(deny.Addr) + + if result := spec.Del(h.connPool, true, h.logger); result != types.EDPVS_OK { + h.logger.Error("IP Addr delete from black list failed.", "VipPort", params.VipPort, "Addr", deny.Addr, "result", result.String()) + failed = true + continue + } + h.logger.Info("IP Addr delete from black list success.", "VipPort", params.VipPort, "Addr", deny.Addr) + } + + if failed { + return apiVs.NewDeleteVsVipPortDenyInvalidBackend() + } + + return apiVs.NewDeleteVsVipPortDenyOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go new file mode 100644 index 000000000..4780c7424 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go @@ -0,0 +1,52 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsLaddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsLaddr(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsLaddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPortLaddr") + } + return &delVsLaddr{connPool: cp, logger: logger} +} + +func (h *delVsLaddr) Handle(params apiVs.DeleteVsVipPortLaddrParams) middleware.Responder { + laddr := types.NewLocalAddrFront() + if err := laddr.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortLaddrInvalidFrontend() + } + + lds := make([]*types.LocalAddrDetail, 1) + lds[0] = types.NewLocalAddrDetail() + lds[0].SetAfByAddr(params.Spec.Addr) + lds[0].SetAddr(params.Spec.Addr) + lds[0].SetIfName(params.Spec.Device) + + result := laddr.Del(lds, h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Delete local ip from virtual server success.", "VipPort", params.VipPort, "Addr", params.Spec.Addr, "Device", params.Spec.Device) + return apiVs.NewDeleteVsVipPortLaddrOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("Delete not exist local ip from virtual server done.", "VipPort", params.VipPort, "Addr", params.Spec.Addr, "Device", params.Spec.Device) + return apiVs.NewDeleteVsVipPortLaddrOK() + default: + h.logger.Error("Delete local ip from virtual server failed.", "VipPort", params.VipPort, "Addr", params.Spec.Addr, "Device", params.Spec.Device, "result", result.String()) + } + + return apiVs.NewDeleteVsVipPortLaddrFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go new file mode 100644 index 000000000..222635645 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type delVsRs struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewDelVsRs(cp *pool.ConnPool, parentLogger hclog.Logger) *delVsRs { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("DelVsVipPortRs") + } + return &delVsRs{connPool: cp, logger: logger} +} + +func (h *delVsRs) Handle(params apiVs.DeleteVsVipPortRsParams) middleware.Responder { + rs := types.NewRealServerFront() + if err := rs.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewDeleteVsVipPortRsInvalidFrontend() + } + + rss := make([]*types.RealServerSpec, len(params.Rss.Items)) + for i, s := range params.Rss.Items { + rss[i] = types.NewRealServerSpec() + rss[i].SetAf(rs.GetAf()) + rss[i].SetProto(rs.GetProto()) + rss[i].SetPort(s.Port) + rss[i].SetAddr(s.IP) + rss[i].SetWeight(uint32(s.Weight)) + // rss[i].SetConnFlags(types.DPVS_FWD_MODE_FNAT) + } + result := rs.Del(rss, h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Del rs from virtual server success.", "VipPort", params.VipPort, "rss", rss) + return apiVs.NewDeleteVsVipPortRsOK() + case types.EDPVS_NOTEXIST: + h.logger.Warn("There is some not exist rs with virtual server delete done.", "VipPort", params.VipPort, "rss", rss) + return apiVs.NewDeleteVsVipPortRsOK() + default: + h.logger.Error("Del rs from virtual server failed.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + } + + return apiVs.NewDeleteVsVipPortRsFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs.go b/tools/dpvs-agent/cmd/ipvs/get_vs.go new file mode 100644 index 000000000..a6d8c1025 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/get_vs.go @@ -0,0 +1,71 @@ +package ipvs + +import ( + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type getVs struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewGetVs(cp *pool.ConnPool, parentLogger hclog.Logger) *getVs { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("GetVs") + } + return &getVs{connPool: cp, logger: logger} +} + +func (h *getVs) Handle(params apiVs.GetVsParams) middleware.Responder { + front := types.NewVirtualServerFront() + vss, err := front.Get(h.connPool, h.logger) + if err != nil { + h.logger.Error("Get virtual server list failed.", "Error", err.Error()) + // FIXME: Invalid + return apiVs.NewGetVsOK() + } + + h.logger.Info("Get all virtual server done.", "vss", vss) + vsModels := new(models.VirtualServerList) + vsModels.Items = make([]*models.VirtualServerSpecExpand, len(vss)) + for i, vs := range vss { + front := types.NewRealServerFront() + + err := front.ParseVipPortProto(vs.ID()) + if err != nil { + h.logger.Error("Convert to virtual server failed. virtual server", "ID", vs.ID(), "Error", err.Error()) + continue + } + front.SetNumDests(vs.GetNumDests()) + + rss, err := front.Get(h.connPool, h.logger) + if err != nil { + h.logger.Error("Get real server list of virtual server failed.", "ID", vs.ID(), "Error", err.Error()) + continue + } + + h.logger.Info("Get real server list of virtual server success.", "ID", vs.ID(), "rss", rss) + + vsModels.Items[i] = vs.GetModel() + vsStats := (*types.ServerStats)(vsModels.Items[i].Stats) + vsModels.Items[i].RSs = new(models.RealServerExpandList) + vsModels.Items[i].RSs.Items = make([]*models.RealServerSpecExpand, len(rss)) + + for j, rs := range rss { + rsModel := rs.GetModel() + rsStats := (*types.ServerStats)(rsModel.Stats) + vsModels.Items[i].RSs.Items[j] = rsModel + vsStats.Increase(rsStats) + } + } + + return apiVs.NewGetVsOK().WithPayload(vsModels) +} diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go new file mode 100644 index 000000000..873e6d533 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go @@ -0,0 +1,79 @@ +package ipvs + +import ( + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type getVsVipPort struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewGetVsVipPort(cp *pool.ConnPool, parentLogger hclog.Logger) *getVsVipPort { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("GetVsVipPort") + } + return &getVsVipPort{connPool: cp, logger: logger} +} + +func (h *getVsVipPort) Handle(params apiVs.GetVsVipPortParams) middleware.Responder { + var vss []*types.VirtualServerSpec + spec := types.NewVirtualServerSpec() + err := spec.ParseVipPortProto(params.VipPort) + if err != nil { + h.logger.Warn("Convert to virtual server failed. Get All virtual server.", "VipPort", params.VipPort, "Error", err.Error()) + front := types.NewVirtualServerFront() + vss, err = front.Get(h.connPool, h.logger) + } else { + vss, err = spec.Get(h.connPool, h.logger) + } + + if err != nil { + h.logger.Error("Get virtual server list failed.", "Error", err.Error()) + return apiVs.NewGetVsVipPortNotFound() + } + + vsModels := new(models.VirtualServerList) + vsModels.Items = make([]*models.VirtualServerSpecExpand, len(vss)) + + for i, vs := range vss { + front := types.NewRealServerFront() + + err := front.ParseVipPortProto(vs.ID()) + if err != nil { + h.logger.Error("Convert to virtual server failed. virtual server", "ID", vs.ID(), "Error", err.Error()) + continue + } + front.SetNumDests(vs.GetNumDests()) + + rss, err := front.Get(h.connPool, h.logger) + if err != nil { + h.logger.Error("Get real server list of virtual server failed.", "ID", vs.ID(), "Error", err.Error()) + continue + } + + h.logger.Info("Get real server list of virtual server success.", "ID", vs.ID(), "rss", rss) + + vsModels.Items[i] = vs.GetModel() + vsStats := (*types.ServerStats)(vsModels.Items[i].Stats) + vsModels.Items[i].RSs = new(models.RealServerExpandList) + vsModels.Items[i].RSs.Items = make([]*models.RealServerSpecExpand, len(rss)) + + for j, rs := range rss { + rsModel := rs.GetModel() + rsStats := (*types.ServerStats)(rsModel.Stats) + vsModels.Items[i].RSs.Items[j] = rsModel + vsStats.Increase(rsStats) + } + } + + return apiVs.NewGetVsVipPortOK().WithPayload(vsModels) +} diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go new file mode 100644 index 000000000..adac60936 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go @@ -0,0 +1,50 @@ +package ipvs + +import ( + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type getVsLaddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewGetVsLaddr(cp *pool.ConnPool, parentLogger hclog.Logger) *getVsLaddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("GetVsVipPortLaddr") + } + return &getVsLaddr{connPool: cp, logger: logger} +} + +func (h *getVsLaddr) Handle(params apiVs.GetVsVipPortLaddrParams) middleware.Responder { + laddr := types.NewLocalAddrFront() + if err := laddr.ParseVipPortProto(params.VipPort); err != nil { + // FIXME: return all laddr + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewGetVsVipPortLaddrNotFound() + } + + lds, err := laddr.Get(h.connPool, h.logger) + if err != nil { + h.logger.Error("Get virtual server laddr failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewGetVsVipPortLaddrNotFound() + } + + h.logger.Info("Get virtual server laddr success.", "VipPort", params.VipPort, "local addr details", "lds", lds) + laddrModels := new(models.LocalAddressExpandList) + laddrModels.Items = make([]*models.LocalAddressSpecExpand, len(lds)) + for i, detail := range lds { + h.logger.Info("Virtual Server", "VipPort", params.VipPort, "detail", detail) + laddrModels.Items[i] = detail.GetModel() + } + + return apiVs.NewGetVsVipPortLaddrOK().WithPayload(laddrModels) +} diff --git a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go new file mode 100644 index 000000000..4f577cca0 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go @@ -0,0 +1,59 @@ +package ipvs + +import ( + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type postVsRs struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPostVsRs(cp *pool.ConnPool, parentLogger hclog.Logger) *postVsRs { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PostVsVipPortRs") + } + return &postVsRs{connPool: cp, logger: logger} +} + +func (h *postVsRs) Handle(params apiVs.PostVsVipPortRsParams) middleware.Responder { + front := types.NewRealServerFront() + if err := front.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPostVsVipPortRsInvalidFrontend() + } + + rss := make([]*types.RealServerSpec, len(params.Rss.Items)) + for i, rs := range params.Rss.Items { + var fwdmode types.DpvsFwdMode + fwdmode.FromString(rs.Mode) + rss[i] = types.NewRealServerSpec() + rss[i].SetAf(front.GetAf()) + rss[i].SetPort(rs.Port) + rss[i].SetWeight(uint32(rs.Weight)) + rss[i].SetProto(front.GetProto()) + rss[i].SetAddr(rs.IP) + rss[i].SetInhibited(rs.Inhibited) + rss[i].SetOverloaded(rs.Inhibited) + rss[i].SetFwdMode(fwdmode) + } + + result := front.Update(rss, h.connPool, h.logger) + switch result { + case types.EDPVS_EXIST, types.EDPVS_OK: + h.logger.Info("Set real server to virtual server success.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPostVsVipPortRsOK() + default: + h.logger.Error("Set real server to virtual server failed.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPostVsVipPortRsFailure() + } + return apiVs.NewPostVsVipPortRsInvalidBackend() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go new file mode 100644 index 000000000..c6c09f285 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go @@ -0,0 +1,96 @@ +package ipvs + +import ( + "strings" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + "golang.org/x/sys/unix" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsItem struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsItem(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsItem { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPort") + } + return &putVsItem{connPool: cp, logger: logger} +} + +// ipvsadm -A vip:port -s wrr +func (h *putVsItem) Handle(params apiVs.PutVsVipPortParams) middleware.Responder { + vs := types.NewVirtualServerSpec() + err := vs.ParseVipPortProto(params.VipPort) + if err != nil { + h.logger.Error("Convert to virtual server failed", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortInvalidFrontend() + } + + schedName := "" + + if params.Spec != nil { + schedName = params.Spec.SchedName + + vs.SetFwmark(params.Spec.Fwmark) + vs.SetConnTimeout(params.Spec.ConnTimeout) // establish time out + vs.SetBps(params.Spec.Bps) + vs.SetLimitProportion(params.Spec.LimitProportion) + + if params.Spec.Timeout != 0 { + vs.SetTimeout(params.Spec.Timeout) // persistence time out + vs.SetFlagsPersistent() + } + + if params.Spec.ExpireQuiescent != nil && *params.Spec.ExpireQuiescent { + vs.SetFlagsExpireQuiescent() + } + + if params.Spec.SyncProxy != nil && *params.Spec.SyncProxy { + vs.SetFlagsSyncProxy() + } + } + + vs.SetSchedName(schedName) + if strings.EqualFold(vs.GetSchedName(), "conhash") { + vs.SetFlagsHashSrcIP() + + if vs.GetProto() == unix.IPPROTO_UDP { + // if strings.EqualFold(strings.ToLower(params.Spec.HashTaget), "qid") {vs.SetFlagsHashQuicID()} + } + } + + result := vs.Add(h.connPool, h.logger) + h.logger.Info("Add virtual server done.", "vs", vs, "result", result.String()) + switch result { + case types.EDPVS_OK: + // return 201 + h.logger.Info("Created new virtual server success.", "VipPort", params.VipPort) + return apiVs.NewPutVsVipPortCreated() + case types.EDPVS_EXIST: + h.logger.Info("The virtual server already exist! Try to update.", "VipPort", params.VipPort) + reason := vs.Update(h.connPool, h.logger) + if reason != types.EDPVS_OK { + // return 461 + h.logger.Error("Update virtual server failed.", "VipPort", params.VipPort, "reason", reason.String()) + return apiVs.NewPutVsVipPortInvalidBackend() + } + h.logger.Info("Update virtual server success.", "VipPort", params.VipPort) + // return 200 + return apiVs.NewPutVsVipPortOK() + default: + h.logger.Error("Add virtual server failed.", "result", result.String()) + return apiVs.NewPutVsVipPortInvalidBackend() + } + + return apiVs.NewPutVsVipPortOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go new file mode 100644 index 000000000..dabcc000b --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go @@ -0,0 +1,58 @@ +package ipvs + +import ( + // "fmt" + "net" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsAllow struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsAllow(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsAllow { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPortAllow") + } + return &putVsAllow{connPool: cp, logger: logger} +} + +func (h *putVsAllow) Handle(params apiVs.PutVsVipPortAllowParams) middleware.Responder { + spec := types.NewCertificateAuthoritySpec() + if err := spec.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortAllowInvalidFrontend() + } + + failed := false + for _, allow := range params.ACL.Items { + if net.ParseIP(allow.Addr) == nil { + h.logger.Error("Invalid ip addr add.", "VipPort", params.VipPort, "Addr", allow.Addr) + return apiVs.NewPutVsVipPortAllowInvalidFrontend() + } + spec.SetSrc(allow.Addr) + + if result := spec.Add(h.connPool, false, h.logger); result != types.EDPVS_OK { + failed = true + h.logger.Error("Add ip addr to white list failed.", "VipPort", params.VipPort, "Addr", allow.Addr, "result", result.String()) + continue + } + h.logger.Info("Add ip addr to white list success.", "VipPort", params.VipPort, "Addr", allow.Addr) + } + + if failed { + return apiVs.NewPutVsVipPortAllowInvalidBackend() + } + + return apiVs.NewPutVsVipPortAllowOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go new file mode 100644 index 000000000..984dff17a --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go @@ -0,0 +1,58 @@ +package ipvs + +import ( + // "fmt" + "net" + + // "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsDeny struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsDeny(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsDeny { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPortDeny") + } + return &putVsDeny{connPool: cp, logger: logger} +} + +func (h *putVsDeny) Handle(params apiVs.PutVsVipPortDenyParams) middleware.Responder { + spec := types.NewCertificateAuthoritySpec() + if err := spec.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortDenyInvalidFrontend() + } + + failed := false + for _, deny := range params.ACL.Items { + if net.ParseIP(deny.Addr) == nil { + h.logger.Error("Invalid ip addr add.", "VipPort", params.VipPort, "Addr", deny.Addr) + return apiVs.NewPutVsVipPortDenyInvalidFrontend() + } + spec.SetSrc(deny.Addr) + + if result := spec.Add(h.connPool, true, h.logger); result != types.EDPVS_OK { + h.logger.Error("Add ip addr to black list failed.", "VipPort", params.VipPort, "Addr", deny.Addr, "result", result.String()) + failed = true + continue + } + h.logger.Info("Add ip addr to black list success.", "VipPort", params.VipPort, "Addr", deny.Addr) + } + + if failed { + return apiVs.NewPutVsVipPortDenyInvalidBackend() + } + + return apiVs.NewPutVsVipPortDenyOK() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go new file mode 100644 index 000000000..6551abea3 --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go @@ -0,0 +1,55 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsLaddr struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsLaddr(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsLaddr { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPortLaddr") + } + return &putVsLaddr{connPool: cp, logger: logger} +} + +func (h *putVsLaddr) Handle(params apiVs.PutVsVipPortLaddrParams) middleware.Responder { + laddr := types.NewLocalAddrFront() + + err := laddr.ParseVipPortProto(params.VipPort) + if err != nil { + h.logger.Error("Convert to virtual server failed.", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortLaddrInvalidFrontend() + } + + lds := make([]*types.LocalAddrDetail, 1) + + lds[0] = types.NewLocalAddrDetail() + lds[0].SetAf(laddr.GetAf()) + lds[0].SetAddr(params.Spec.Addr) + lds[0].SetIfName(params.Spec.Device) + + result := laddr.Add(lds, h.connPool, h.logger) + switch result { + case types.EDPVS_OK: + h.logger.Info("Set virtual server Local IP success.", "VipPort", params.VipPort, "Local Addr", params.Spec.Addr) + return apiVs.NewPutVsVipPortLaddrOK() + case types.EDPVS_EXIST: + h.logger.Warn("Local IP already exist.", "VipPort", params.VipPort, "Local Addr", params.Spec.Addr, "result", result.String()) + return apiVs.NewPutVsVipPortLaddrOK() + default: + h.logger.Error("Set virtual server Local IP failed.", "VipPort", params.VipPort, "Local Addr", params.Spec.Addr, "result", result.String()) + } + + return apiVs.NewPutVsVipPortLaddrFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go new file mode 100644 index 000000000..05380108c --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go @@ -0,0 +1,74 @@ +package ipvs + +import ( + "github.com/dpvs-agent/pkg/ipc/pool" + "github.com/dpvs-agent/pkg/ipc/types" + + apiVs "github.com/dpvs-agent/restapi/operations/virtualserver" + + "github.com/go-openapi/runtime/middleware" + "github.com/hashicorp/go-hclog" +) + +type putVsRs struct { + connPool *pool.ConnPool + logger hclog.Logger +} + +func NewPutVsRs(cp *pool.ConnPool, parentLogger hclog.Logger) *putVsRs { + logger := hclog.Default() + if parentLogger != nil { + logger = parentLogger.Named("PutVsVipPortRs") + } + return &putVsRs{connPool: cp, logger: logger} +} + +func (h *putVsRs) Handle(params apiVs.PutVsVipPortRsParams) middleware.Responder { + front := types.NewRealServerFront() + if err := front.ParseVipPortProto(params.VipPort); err != nil { + h.logger.Error("Convert to virtual server failed", "VipPort", params.VipPort, "Error", err.Error()) + return apiVs.NewPutVsVipPortRsInvalidFrontend() + } + + var rss []*types.RealServerSpec + if params.Rss != nil { + rss = make([]*types.RealServerSpec, len(params.Rss.Items)) + for i, rs := range params.Rss.Items { + var fwdmode types.DpvsFwdMode + fwdmode.FromString(rs.Mode) + rss[i] = types.NewRealServerSpec() + rss[i].SetAf(front.GetAf()) + rss[i].SetAddr(rs.IP) + rss[i].SetPort(rs.Port) + rss[i].SetProto(front.GetProto()) + rss[i].SetWeight(uint32(rs.Weight)) + rss[i].SetFwdMode(fwdmode) + rss[i].SetInhibited(rs.Inhibited) + rss[i].SetOverloaded(rs.Inhibited) + } + } + + healthCheck := false + if params.Healthcheck != nil { + healthCheck = *params.Healthcheck + } + + result := front.Edit(healthCheck, rss, h.connPool, h.logger) + + // h.logger.Info("Set real server sets done.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + switch result { + case types.EDPVS_EXIST, types.EDPVS_OK: + h.logger.Info("Set real server sets success.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPutVsVipPortRsOK() + case types.EDPVS_NOTEXIST: + if healthCheck { + h.logger.Error("Edit not exist real server.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPutVsVipPortRsInvalidFrontend() + } + h.logger.Error("Unreachable branch") + default: + h.logger.Error("Set real server sets failed.", "VipPort", params.VipPort, "rss", rss, "result", result.String()) + return apiVs.NewPutVsVipPortRsInvalidBackend() + } + return apiVs.NewPutVsVipPortRsFailure() +} diff --git a/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go new file mode 100644 index 000000000..91ce6808a --- /dev/null +++ b/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go @@ -0,0 +1 @@ +package ipvs diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml new file mode 100644 index 000000000..230751c80 --- /dev/null +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -0,0 +1,1373 @@ +swagger: "2.0" +info: + description: "dpvs agent api" + version: "1.0.0" + title: "dpvs agent" +host: "petstore.swagger.io" +basePath: "/v2" +tags: +- name: "virtualserver" + description: "virtualserver" +- name: "route" + description: "route" +- name: "laddr" + description: "laddr" +- name: "tunnel" + description: "tunnel" +- name: "inetaddr" + description: "inet addr" +- name: "white_list" + description: "white list" +- name: "black_list" + description: "black list" +- name: "arp" + description: "arp" +schemes: +- "http" +parameters: + service-id: + name: VipPort + in: path + type: string + required: true + realserver-id: + name: RipPort + in: path + type: string + required: true + device-name: + name: name + in: path + type: string + required: true + vs-config: + name: spec + in: body + schema: + "$ref": "#/definitions/VirtualServerSpecTiny" + rs-config: + name: spec + in: body + schema: + "$ref": "#/definitions/RealServerSpecTiny" + rss-config: + name: rss + in: body + schema: + "$ref": "#/definitions/RealServerTinyList" + acl-config: + name: acl + in: body + schema: + "$ref": "#/definitions/AclAddrList" + laddr-config: + name: spec + in: body + schema: + "$ref": "#/definitions/LocalAddressSpecTiny" + route-config: + name: spec + in: body + schema: + "$ref": "#/definitions/RouteSpec" + vlan-config: + name: spec + in: body + schema: + "$ref": "#/definitions/VlanSpec" + device-addr: + name: spec + in: body + schema: + "$ref": "#/definitions/InetAddrSpec" + healthcheck: + name: healthcheck + in: query + type: boolean + default: false + required: false + stats: + name: stats + in: query + type: boolean + default: false + required: false + verbose: + name: verbose + in: query + type: boolean + default: false + required: false + sapool: + name: sapool + in: query + type: boolean + default: false + required: false + promisc: + name: promisc + in: query + type: string + enum: + - unset + - on + - off + default: unset + required: false + link: + name: link + in: query + type: string + enum: + - unset + - up + - down + default: unset + required: false + forward2kni: + name: forward2Kni + in: query + type: string + enum: + - unset + - on + - off + default: unset + required: false +definitions: + CertAuthSpec: + properties: + addr: + type: string + InetAddrSpec: + properties: + addr: + type: string + broadcast: + type: string + scope: + type: string + VlanSpec: + properties: + name: + type: string + device: + type: string + id: + type: string + RouteSpec: + properties: + src: + type: string + dst: + type: string + gateway: + type: string + prefixSrc: + type: string + device: + type: string + scope: + type: string + mtu: + type: integer + format: uint32 + metric: + type: integer + format: uint32 + LocalAddressSpecExpand: + type: object + properties: + af: + type: integer + format: uint32 + conns: + type: integer + format: uint32 + portConflict: + type: integer + format: uint64 + addr: + type: string + device: + type: string + LocalAddressSpecTiny: + properties: + addr: + type: string + device: + type: string + AclAddrList: + type: object + properties: + Items: + type: array + items: + "$ref": "#/definitions/CertAuthSpec" + LocalAddressExpandList: + properties: + Items: + type: array + items: + "$ref": "#/definitions/LocalAddressSpecExpand" + LocalAddressTinyList: + properties: + Items: + type: array + items: + "$ref": "#/definitions/LocalAddressSpecTiny" + RealServerTinyList: + type: object + properties: + Items: + type: array + items: + "$ref": "#/definitions/RealServerSpecTiny" + RealServerExpandList: + type: "object" + properties: + Items: + type: array + items: + "$ref": "#/definitions/RealServerSpecExpand" + RealServerSpecExpand: + type: object + properties: + Spec: + "$ref": "#/definitions/RealServerSpecTiny" + Stats: + "$ref": "#/definitions/ServerStats" + RealServerSpecTiny: + type: object + properties: + ip: + type: "string" + port: + type: "integer" + format: "uint16" + x-omitempty: false + weight: + type: "integer" + format: "uint16" + x-omitempty: false + mode: + type: "string" + enum: + - "FNAT" + - "SNAT" + - "DR" + - "TUNNEL" + - "NAT" + inhibited: + type: "boolean" + default: false + overloaded: + type: "boolean" + default: false + NicDeviceSpecList: + type: object + properties: + Items: + type: array + items: + "$ref": "#/definitions/NicDeviceSpec" + NicDeviceSpec: + type: object + properties: + detail: + "$ref": "#/definitions/NicDeviceDetail" + stats: + "$ref": "#/definitions/NicDeviceStats" + #extra: + # "$ref": "#/definitions/NicDeviceStats" + #NicDeviceExtra: padding + NicDeviceDetail: + type: object + properties: + name: + type: string + addr: + type: string + status: + type: string + enum: + - "UP" + - "DOWN" + duplex: + type: string + enum: + - "half-duplex" + - "full-duplex" + autoneg: + type: string + enum: + - "fixed-nego" + - "auto-nego" + speed: + type: integer + format: uint32 + nRxQ: + type: integer + format: uint8 + nTxQ: + type: integer + format: uint8 + socketID: + type: integer + format: uint8 + ID: + type: integer + format: uint16 + MTU: + type: integer + format: uint16 + Flags: + type: integer + format: uint16 + NicDeviceStats: + type: object + properties: + id: + type: integer + format: "uint16" + bufAvail: + type: integer + format: "uint32" + bufInuse: + type: integer + format: "uint32" + inPkts: + type: integer + format: "uint64" + outPkts: + type: integer + format: "uint64" + inBytes: + type: integer + format: "uint64" + outBytes: + type: integer + format: "uint64" + inMissed: + type: integer + format: "uint64" + inErrors: + type: integer + format: "uint64" + outErrors: + type: integer + format: "uint64" + rxNoMbuf: + type: integer + format: "uint64" + inPktsQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + outPktsQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + inBytesQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + outBytesQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + errorBytesQ: + type: array + items: + "$ref": "#/definitions/NicDeviceQueueData" + NicDeviceQueueData: + type: integer + format: "uint64" + Error: + type: "string" + Status: + description: Status of an individual component + type: object + properties: + state: + type: string + description: State the component is in + enum: + - Ok + - Warning + - Failure + - Disabled + msg: + type: string + description: Human readable status/error/warning message + ServerStats: + type: "object" + properties: + Conns: + type: "integer" + format: "uint64" + InPkts: + type: "integer" + format: "uint64" + InBytes: + type: "integer" + format: "uint64" + OutPkts: + type: "integer" + format: "uint64" + OutBytes: + type: "integer" + format: "uint64" + Cps: + type: "integer" + format: "uint32" + InPps: + type: "integer" + format: "uint32" + InBps: + type: "integer" + format: "uint32" + OutPps: + type: "integer" + format: "uint32" + OutBps: + type: "integer" + format: "uint32" + AddrRange: + type: "object" + properties: + Start: + type: "string" + End: + type: "string" + MatchSpec: + type: "object" + properties: + Src: + "$ref": "#/definitions/AddrRange" + Dest: + "$ref": "#/definitions/AddrRange" + InIfName: + type: string + OutIfName: + type: string + DestCheckSpec: + type: "string" + enum: + - passive + - tcp + - udp + - ping + + VirtualServerList: + type: object + properties: + Items: + type: array + items: + "$ref": "#/definitions/VirtualServerSpecExpand" + VirtualServerSpecExpand: + type: "object" + properties: + Af: + type: "integer" + format: "uint32" + Proto: + type: "integer" + format: "uint16" + Port: + type: "integer" + format: "uint16" + Fwmark: + type: "integer" + format: "uint32" + Flags: + type: "string" + SyncProxy: + type: "string" + enum: + - "true" + - "false" + ExpireQuiescent: + type: "string" + enum: + - "true" + - "false" + Timeout: + type: "integer" + format: "uint32" + ConnTimeout: + type: "integer" + format: "uint32" + Netmask: + type: "integer" + format: "uint32" + Bps: + type: "integer" + format: "uint32" + LimitProportion: + type: "integer" + format: "uint32" + Addr: + type: "string" + SchedName: + type: "string" + enum: + - rr + - wrr + - wlc + - connhash + DestCheck: + type: array + items: + "$ref": "#/definitions/DestCheckSpec" + Stats: + "$ref": "#/definitions/ServerStats" + RSs: + "$ref": "#/definitions/RealServerExpandList" + Match: + "$ref": "#/definitions/MatchSpec" + VirtualServerSpecTiny: + type: "object" + properties: + #Af: + # type: "integer" + # format: "uint16" + #Port: + # type: "integer" + # format: "uint16" + Fwmark: + type: "integer" + format: "uint32" + #Flags: + # type: "integer" + # format: "uint32" + SyncProxy: + type: "boolean" + default: false + ExpireQuiescent: + type: "boolean" + default: false + Timeout: + type: "integer" + format: "uint32" + ConnTimeout: + type: "integer" + format: "uint32" + #Netmask: + # type: "integer" + # format: "uint32" + Bps: + type: "integer" + format: "uint32" + LimitProportion: + type: "integer" + format: "uint32" + #Addr: + # type: "string" + SchedName: + type: "string" + enum: + - rr + - wrr + - wlc + - connhash + Match: + "$ref": "#/definitions/MatchSpec" +paths: + /device: + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/stats" + summary: "display all net device list" + responses: + '200': + description: Success + schema: + type: string + /device/{name}/addr: + #description: dpip addr add 192.168.88.16/32 dev dpdk0.102 + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/stats" + - "$ref": "#/parameters/verbose" + - "$ref": "#/parameters/device-name" + summary: "display special net device ip addr" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/sapool" + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/device-addr" + summary: "add/update special net device ip addr" + responses: + '200': + description: Update exist ip addr Success + schema: + type: string + '201': + description: Add new ip addr Success + schema: + type: string + '500': + description: Failed + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/sapool" + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/device-addr" + summary: "delete special net device ip addr" + responses: + '200': + description: delete ip addr from device Success + schema: + type: string + '500': + description: Failed + schema: + type: string + /device/{name}/route: + #description: dpip route add 192.168.88.16/32 dev dpdk0.102 scope kni_host + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/stats" + - "$ref": "#/parameters/device-name" + summary: "display special net device route" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/route-config" + summary: "add/update special net device route" + responses: + '200': + description: Update exist route Success + schema: + type: string + '201': + description: Add new route Success + schema: + type: string + '500': + description: Failed + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/route-config" + summary: "delete special net device route" + responses: + '200': + description: delete route Success + schema: + type: string + '500': + description: Failed + schema: + type: string + /device/{name}/netlink: + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/stats" + summary: "ip link show dev ${name}" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + summary: "ip link set ${name} up" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Not Found + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + summary: "ip link set ${name} down" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Not Found + schema: + type: string + /device/{name}/netlink/addr: + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/stats" + summary: "ip addr show lo: Display special linux net device addr detail" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/device-addr" + summary: "ip addr add 10.0.0.1/32 dev eth0: Set ip cird to linux net device" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Not Found + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/device-addr" + summary: "ip addr del 10.0.0.1/32 dev eth0: Delete ip cird fron linux net device" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Not Found + schema: + type: string + #/device/{name}/cpu + /device/{name}/nic: + #description: dpip link show + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/verbose" + - "$ref": "#/parameters/stats" + summary: "dpip link show ${nic-name} -s -v" + responses: + '200': + description: Success + schema: + #type: string + "$ref": "#/definitions/NicDeviceSpecList" + '500': + description: Failure + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/forward2kni" + - "$ref": "#/parameters/link" + - "$ref": "#/parameters/promisc" + summary: "dpip link set ${nic-name} [forward2kni,link,promisc,tc-ingress,tc-egress] [on/up,off/down]" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Failure + schema: + type: string + /device/{name}/vlan: + #description: dpip vlan add dpdk0.102 link dpdk0 id 102 + get: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/stats" + summary: "display all net device list" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Not Found + schema: + type: string + put: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + - "$ref": "#/parameters/vlan-config" + summary: "add/update special net device " + responses: + '200': + description: Success + schema: + type: string + '500': + description: Failed + schema: + type: string + delete: + tags: + - "device" + parameters: + - "$ref": "#/parameters/device-name" + summary: "delete special net device" + responses: + '200': + description: Success + schema: + type: string + '500': + description: Failed + schema: + type: string + /vs: + get: + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/stats" + summary: "display all vip:port:proto and rsip:port list" + responses: + '200': + description: Success + schema: + "$ref": "#/definitions/VirtualServerList" + # items: + # "$ref": "#/definitions/VirtualServer" + /vs/{VipPort}: + get: + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/stats" + summary: "get a specific virtual server" + responses: + '200': + description: Success + schema: + # type: string + # items: + "$ref": "#/definitions/VirtualServerList" + '404': + description: Service not found + schema: + type: string + delete: + summary: "Delete a vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + responses: + '200': + description: Success + schema: + type: string + '404': + description: Service not found + schema: + type: string + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + put: + summary: "create or update virtual server" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/vs-config" + responses: + '200': + description: Updated + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: "Error while creating virtual server" + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + /vs/{VipPort}/laddr: + get: + tags: + - "virtualserver" + parameters: + #- "$ref": "#/parameters/realserver-id" + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/stats" + responses: + '200': + description: Success + schema: + "$ref": "#/definitions/LocalAddressExpandList" + #type: string + #items: + # "$ref": "#/definitions/VirtualServer" + '404': + description: Service not found + schema: + type: string + put: + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/laddr-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: "Error while creating virtual server" + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + delete: + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/laddr-config" + responses: + '200': + description: Success + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: "Error while creating virtual server" + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + /vs/{VipPort}/rs: + get: + tags: + - "virtualserver" + parameters: + #- "$ref": "#/parameters/realserver-id" + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/stats" + responses: + '200': + description: Success + schema: + type: string + #items: + # "$ref": "#/definitions/VirtualServer" + '404': + description: Service not found + schema: + type: string + delete: + summary: "Delete a set of real server from vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/rss-config" + responses: + '200': + description: Success + '404': + description: Service not found + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + put: + summary: "Add a set of real server to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/rss-config" + - "$ref": "#/parameters/healthcheck" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + post: + summary: "Update fully real server list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/rss-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + /vs/{VipPort}/deny: + get: + tags: + - "virtualserver" + parameters: + #- "$ref": "#/parameters/realserver-id" + - "$ref": "#/parameters/service-id" + responses: + '200': + description: Success + schema: + type: string + #items: + # "$ref": "#/definitions/VirtualServer" + '404': + description: Service not found + schema: + type: string + delete: + summary: "Delete a set of ip form black list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + '404': + description: Service not found + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + put: + summary: "Add a set of ip from black list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + post: + summary: "Update a fully black ip list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + /vs/{VipPort}/allow: + get: + tags: + - "virtualserver" + parameters: + #- "$ref": "#/parameters/realserver-id" + - "$ref": "#/parameters/service-id" + responses: + '200': + description: Success + schema: + type: string + #items: + # "$ref": "#/definitions/VirtualServer" + '404': + description: Service not found + schema: + type: string + delete: + summary: "Delete a set of ip form white list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + '404': + description: Service not found + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + put: + summary: "Add a set of ip from white list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" + post: + summary: "Update a fully white ip list to vip:port:proto" + tags: + - "virtualserver" + parameters: + - "$ref": "#/parameters/service-id" + - "$ref": "#/parameters/acl-config" + responses: + '200': + description: Success + schema: + type: string + '201': + description: Created + schema: + type: string + '460': + description: Invalid frontend in service configuration + x-go-name: InvalidFrontend + schema: + "$ref": "#/definitions/Error" + '461': + description: Invalid backend in service configuration + x-go-name: InvalidBackend + schema: + "$ref": "#/definitions/Error" + '500': + description: Service deletion failed + x-go-name: Failure + schema: + "$ref": "#/definitions/Error" diff --git a/tools/dpvs-agent/go.mod b/tools/dpvs-agent/go.mod new file mode 100644 index 000000000..b5198bfc6 --- /dev/null +++ b/tools/dpvs-agent/go.mod @@ -0,0 +1,40 @@ +module github.com/dpvs-agent + +go 1.20 + +require ( + github.com/go-openapi/errors v0.20.3 + github.com/go-openapi/loads v0.21.2 + github.com/go-openapi/runtime v0.26.0 + github.com/go-openapi/spec v0.20.9 + github.com/go-openapi/strfmt v0.21.7 + github.com/go-openapi/swag v0.22.3 + github.com/go-openapi/validate v0.22.1 + github.com/hashicorp/go-hclog v1.5.0 + github.com/jessevdk/go-flags v1.5.0 + github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible + github.com/vishvananda/netlink v1.1.0 + golang.org/x/net v0.10.0 + golang.org/x/sys v0.8.0 +) + +require ( + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/go-openapi/analysis v0.21.4 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/jonboulle/clockwork v0.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/lestrrat-go/strftime v1.0.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/oklog/ulid v1.3.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df // indirect + go.mongodb.org/mongo-driver v1.11.3 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/tools/dpvs-agent/go.sum b/tools/dpvs-agent/go.sum new file mode 100644 index 000000000..f6f0a32b6 --- /dev/null +++ b/tools/dpvs-agent/go.sum @@ -0,0 +1,232 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= +github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= +github.com/go-openapi/analysis v0.21.4/go.mod h1:4zQ35W4neeZTqh3ol0rv/O8JBbka9QyAgQRPp9y3pfo= +github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= +github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc= +github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g= +github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro= +github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw= +github.com/go-openapi/runtime v0.26.0 h1:HYOFtG00FM1UvqrcxbEJg/SwvDRvYLQKGhw2zaQjTcc= +github.com/go-openapi/runtime v0.26.0/go.mod h1:QgRGeZwrUcSHdeh4Ka9Glvo0ug1LC5WyE+EV88plZrQ= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= +github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg= +github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k= +github.com/go-openapi/strfmt v0.21.3/go.mod h1:k+RzNO0Da+k3FrrynSNN8F7n/peCmQQqbbXjtDfvmGg= +github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k= +github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/validate v0.22.1 h1:G+c2ub6q47kfX1sOBLwIQwzBVt8qmOAARyo/9Fqs9NU= +github.com/go-openapi/validate v0.22.1/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= +github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= +github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ= +github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7ZovXvuNyL3XQl8UFofeikI1NW1Gypu7k= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= +go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= +go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= +go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y= +go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/dpvs-agent/models/acl_addr_list.go b/tools/dpvs-agent/models/acl_addr_list.go new file mode 100644 index 000000000..06f092792 --- /dev/null +++ b/tools/dpvs-agent/models/acl_addr_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// ACLAddrList Acl addr list +// +// swagger:model AclAddrList +type ACLAddrList struct { + + // items + Items []*CertAuthSpec `json:"Items"` +} + +// Validate validates this Acl addr list +func (m *ACLAddrList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *ACLAddrList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this Acl addr list based on the context it is used +func (m *ACLAddrList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *ACLAddrList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *ACLAddrList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ACLAddrList) UnmarshalBinary(b []byte) error { + var res ACLAddrList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/addr_range.go b/tools/dpvs-agent/models/addr_range.go new file mode 100644 index 000000000..4324dde7a --- /dev/null +++ b/tools/dpvs-agent/models/addr_range.go @@ -0,0 +1,53 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// AddrRange addr range +// +// swagger:model AddrRange +type AddrRange struct { + + // end + End string `json:"End,omitempty"` + + // start + Start string `json:"Start,omitempty"` +} + +// Validate validates this addr range +func (m *AddrRange) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this addr range based on context it is used +func (m *AddrRange) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *AddrRange) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *AddrRange) UnmarshalBinary(b []byte) error { + var res AddrRange + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/cert_auth_spec.go b/tools/dpvs-agent/models/cert_auth_spec.go new file mode 100644 index 000000000..61648012e --- /dev/null +++ b/tools/dpvs-agent/models/cert_auth_spec.go @@ -0,0 +1,50 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// CertAuthSpec cert auth spec +// +// swagger:model CertAuthSpec +type CertAuthSpec struct { + + // addr + Addr string `json:"addr,omitempty"` +} + +// Validate validates this cert auth spec +func (m *CertAuthSpec) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this cert auth spec based on context it is used +func (m *CertAuthSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *CertAuthSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *CertAuthSpec) UnmarshalBinary(b []byte) error { + var res CertAuthSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/dest_check_spec.go b/tools/dpvs-agent/models/dest_check_spec.go new file mode 100644 index 000000000..2e2e9cf9a --- /dev/null +++ b/tools/dpvs-agent/models/dest_check_spec.go @@ -0,0 +1,84 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// DestCheckSpec dest check spec +// +// swagger:model DestCheckSpec +type DestCheckSpec string + +func NewDestCheckSpec(value DestCheckSpec) *DestCheckSpec { + return &value +} + +// Pointer returns a pointer to a freshly-allocated DestCheckSpec. +func (m DestCheckSpec) Pointer() *DestCheckSpec { + return &m +} + +const ( + + // DestCheckSpecPassive captures enum value "passive" + DestCheckSpecPassive DestCheckSpec = "passive" + + // DestCheckSpecTCP captures enum value "tcp" + DestCheckSpecTCP DestCheckSpec = "tcp" + + // DestCheckSpecUDP captures enum value "udp" + DestCheckSpecUDP DestCheckSpec = "udp" + + // DestCheckSpecPing captures enum value "ping" + DestCheckSpecPing DestCheckSpec = "ping" +) + +// for schema +var destCheckSpecEnum []interface{} + +func init() { + var res []DestCheckSpec + if err := json.Unmarshal([]byte(`["passive","tcp","udp","ping"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + destCheckSpecEnum = append(destCheckSpecEnum, v) + } +} + +func (m DestCheckSpec) validateDestCheckSpecEnum(path, location string, value DestCheckSpec) error { + if err := validate.EnumCase(path, location, value, destCheckSpecEnum, true); err != nil { + return err + } + return nil +} + +// Validate validates this dest check spec +func (m DestCheckSpec) Validate(formats strfmt.Registry) error { + var res []error + + // value enum + if err := m.validateDestCheckSpecEnum("", "body", m); err != nil { + return err + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// ContextValidate validates this dest check spec based on context it is used +func (m DestCheckSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} diff --git a/tools/dpvs-agent/models/error.go b/tools/dpvs-agent/models/error.go new file mode 100644 index 000000000..f0f02dcac --- /dev/null +++ b/tools/dpvs-agent/models/error.go @@ -0,0 +1,27 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" +) + +// Error error +// +// swagger:model Error +type Error string + +// Validate validates this error +func (m Error) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this error based on context it is used +func (m Error) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} diff --git a/tools/dpvs-agent/models/inet_addr_spec.go b/tools/dpvs-agent/models/inet_addr_spec.go new file mode 100644 index 000000000..9a4e53e75 --- /dev/null +++ b/tools/dpvs-agent/models/inet_addr_spec.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// InetAddrSpec inet addr spec +// +// swagger:model InetAddrSpec +type InetAddrSpec struct { + + // addr + Addr string `json:"addr,omitempty"` + + // broadcast + Broadcast string `json:"broadcast,omitempty"` + + // scope + Scope string `json:"scope,omitempty"` +} + +// Validate validates this inet addr spec +func (m *InetAddrSpec) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this inet addr spec based on context it is used +func (m *InetAddrSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *InetAddrSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *InetAddrSpec) UnmarshalBinary(b []byte) error { + var res InetAddrSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/local_address_expand_list.go b/tools/dpvs-agent/models/local_address_expand_list.go new file mode 100644 index 000000000..c4e52dca9 --- /dev/null +++ b/tools/dpvs-agent/models/local_address_expand_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// LocalAddressExpandList local address expand list +// +// swagger:model LocalAddressExpandList +type LocalAddressExpandList struct { + + // items + Items []*LocalAddressSpecExpand `json:"Items"` +} + +// Validate validates this local address expand list +func (m *LocalAddressExpandList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LocalAddressExpandList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this local address expand list based on the context it is used +func (m *LocalAddressExpandList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LocalAddressExpandList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *LocalAddressExpandList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LocalAddressExpandList) UnmarshalBinary(b []byte) error { + var res LocalAddressExpandList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/local_address_spec_expand.go b/tools/dpvs-agent/models/local_address_spec_expand.go new file mode 100644 index 000000000..0b25fb723 --- /dev/null +++ b/tools/dpvs-agent/models/local_address_spec_expand.go @@ -0,0 +1,62 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// LocalAddressSpecExpand local address spec expand +// +// swagger:model LocalAddressSpecExpand +type LocalAddressSpecExpand struct { + + // addr + Addr string `json:"addr,omitempty"` + + // af + Af uint32 `json:"af,omitempty"` + + // conns + Conns uint32 `json:"conns,omitempty"` + + // device + Device string `json:"device,omitempty"` + + // port conflict + PortConflict uint64 `json:"portConflict,omitempty"` +} + +// Validate validates this local address spec expand +func (m *LocalAddressSpecExpand) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this local address spec expand based on context it is used +func (m *LocalAddressSpecExpand) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *LocalAddressSpecExpand) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LocalAddressSpecExpand) UnmarshalBinary(b []byte) error { + var res LocalAddressSpecExpand + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/local_address_spec_tiny.go b/tools/dpvs-agent/models/local_address_spec_tiny.go new file mode 100644 index 000000000..79806b25e --- /dev/null +++ b/tools/dpvs-agent/models/local_address_spec_tiny.go @@ -0,0 +1,53 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// LocalAddressSpecTiny local address spec tiny +// +// swagger:model LocalAddressSpecTiny +type LocalAddressSpecTiny struct { + + // addr + Addr string `json:"addr,omitempty"` + + // device + Device string `json:"device,omitempty"` +} + +// Validate validates this local address spec tiny +func (m *LocalAddressSpecTiny) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this local address spec tiny based on context it is used +func (m *LocalAddressSpecTiny) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *LocalAddressSpecTiny) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LocalAddressSpecTiny) UnmarshalBinary(b []byte) error { + var res LocalAddressSpecTiny + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/local_address_tiny_list.go b/tools/dpvs-agent/models/local_address_tiny_list.go new file mode 100644 index 000000000..3c04085a4 --- /dev/null +++ b/tools/dpvs-agent/models/local_address_tiny_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// LocalAddressTinyList local address tiny list +// +// swagger:model LocalAddressTinyList +type LocalAddressTinyList struct { + + // items + Items []*LocalAddressSpecTiny `json:"Items"` +} + +// Validate validates this local address tiny list +func (m *LocalAddressTinyList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LocalAddressTinyList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this local address tiny list based on the context it is used +func (m *LocalAddressTinyList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *LocalAddressTinyList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *LocalAddressTinyList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *LocalAddressTinyList) UnmarshalBinary(b []byte) error { + var res LocalAddressTinyList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/match_spec.go b/tools/dpvs-agent/models/match_spec.go new file mode 100644 index 000000000..8d78ed4ca --- /dev/null +++ b/tools/dpvs-agent/models/match_spec.go @@ -0,0 +1,156 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// MatchSpec match spec +// +// swagger:model MatchSpec +type MatchSpec struct { + + // dest + Dest *AddrRange `json:"Dest,omitempty"` + + // in if name + InIfName string `json:"InIfName,omitempty"` + + // out if name + OutIfName string `json:"OutIfName,omitempty"` + + // src + Src *AddrRange `json:"Src,omitempty"` +} + +// Validate validates this match spec +func (m *MatchSpec) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateDest(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSrc(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *MatchSpec) validateDest(formats strfmt.Registry) error { + if swag.IsZero(m.Dest) { // not required + return nil + } + + if m.Dest != nil { + if err := m.Dest.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Dest") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Dest") + } + return err + } + } + + return nil +} + +func (m *MatchSpec) validateSrc(formats strfmt.Registry) error { + if swag.IsZero(m.Src) { // not required + return nil + } + + if m.Src != nil { + if err := m.Src.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Src") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Src") + } + return err + } + } + + return nil +} + +// ContextValidate validate this match spec based on the context it is used +func (m *MatchSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateDest(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateSrc(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *MatchSpec) contextValidateDest(ctx context.Context, formats strfmt.Registry) error { + + if m.Dest != nil { + if err := m.Dest.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Dest") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Dest") + } + return err + } + } + + return nil +} + +func (m *MatchSpec) contextValidateSrc(ctx context.Context, formats strfmt.Registry) error { + + if m.Src != nil { + if err := m.Src.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Src") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Src") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *MatchSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *MatchSpec) UnmarshalBinary(b []byte) error { + var res MatchSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_detail.go b/tools/dpvs-agent/models/nic_device_detail.go new file mode 100644 index 000000000..ee0a65216 --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_detail.go @@ -0,0 +1,232 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// NicDeviceDetail nic device detail +// +// swagger:model NicDeviceDetail +type NicDeviceDetail struct { + + // flags + Flags uint16 `json:"Flags,omitempty"` + + // ID + ID uint16 `json:"ID,omitempty"` + + // m t u + MTU uint16 `json:"MTU,omitempty"` + + // addr + Addr string `json:"addr,omitempty"` + + // autoneg + // Enum: [fixed-nego auto-nego] + Autoneg string `json:"autoneg,omitempty"` + + // duplex + // Enum: [half-duplex full-duplex] + Duplex string `json:"duplex,omitempty"` + + // n rx q + NRxQ uint8 `json:"nRxQ,omitempty"` + + // n tx q + NTxQ uint8 `json:"nTxQ,omitempty"` + + // name + Name string `json:"name,omitempty"` + + // socket ID + SocketID uint8 `json:"socketID,omitempty"` + + // speed + Speed uint32 `json:"speed,omitempty"` + + // status + // Enum: [UP DOWN] + Status string `json:"status,omitempty"` +} + +// Validate validates this nic device detail +func (m *NicDeviceDetail) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateAutoneg(formats); err != nil { + res = append(res, err) + } + + if err := m.validateDuplex(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStatus(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var nicDeviceDetailTypeAutonegPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["fixed-nego","auto-nego"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + nicDeviceDetailTypeAutonegPropEnum = append(nicDeviceDetailTypeAutonegPropEnum, v) + } +} + +const ( + + // NicDeviceDetailAutonegFixedDashNego captures enum value "fixed-nego" + NicDeviceDetailAutonegFixedDashNego string = "fixed-nego" + + // NicDeviceDetailAutonegAutoDashNego captures enum value "auto-nego" + NicDeviceDetailAutonegAutoDashNego string = "auto-nego" +) + +// prop value enum +func (m *NicDeviceDetail) validateAutonegEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, nicDeviceDetailTypeAutonegPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *NicDeviceDetail) validateAutoneg(formats strfmt.Registry) error { + if swag.IsZero(m.Autoneg) { // not required + return nil + } + + // value enum + if err := m.validateAutonegEnum("autoneg", "body", m.Autoneg); err != nil { + return err + } + + return nil +} + +var nicDeviceDetailTypeDuplexPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["half-duplex","full-duplex"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + nicDeviceDetailTypeDuplexPropEnum = append(nicDeviceDetailTypeDuplexPropEnum, v) + } +} + +const ( + + // NicDeviceDetailDuplexHalfDashDuplex captures enum value "half-duplex" + NicDeviceDetailDuplexHalfDashDuplex string = "half-duplex" + + // NicDeviceDetailDuplexFullDashDuplex captures enum value "full-duplex" + NicDeviceDetailDuplexFullDashDuplex string = "full-duplex" +) + +// prop value enum +func (m *NicDeviceDetail) validateDuplexEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, nicDeviceDetailTypeDuplexPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *NicDeviceDetail) validateDuplex(formats strfmt.Registry) error { + if swag.IsZero(m.Duplex) { // not required + return nil + } + + // value enum + if err := m.validateDuplexEnum("duplex", "body", m.Duplex); err != nil { + return err + } + + return nil +} + +var nicDeviceDetailTypeStatusPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["UP","DOWN"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + nicDeviceDetailTypeStatusPropEnum = append(nicDeviceDetailTypeStatusPropEnum, v) + } +} + +const ( + + // NicDeviceDetailStatusUP captures enum value "UP" + NicDeviceDetailStatusUP string = "UP" + + // NicDeviceDetailStatusDOWN captures enum value "DOWN" + NicDeviceDetailStatusDOWN string = "DOWN" +) + +// prop value enum +func (m *NicDeviceDetail) validateStatusEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, nicDeviceDetailTypeStatusPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *NicDeviceDetail) validateStatus(formats strfmt.Registry) error { + if swag.IsZero(m.Status) { // not required + return nil + } + + // value enum + if err := m.validateStatusEnum("status", "body", m.Status); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this nic device detail based on context it is used +func (m *NicDeviceDetail) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *NicDeviceDetail) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NicDeviceDetail) UnmarshalBinary(b []byte) error { + var res NicDeviceDetail + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_queue_data.go b/tools/dpvs-agent/models/nic_device_queue_data.go new file mode 100644 index 000000000..ac8deb299 --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_queue_data.go @@ -0,0 +1,27 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" +) + +// NicDeviceQueueData nic device queue data +// +// swagger:model NicDeviceQueueData +type NicDeviceQueueData uint64 + +// Validate validates this nic device queue data +func (m NicDeviceQueueData) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this nic device queue data based on context it is used +func (m NicDeviceQueueData) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_spec.go b/tools/dpvs-agent/models/nic_device_spec.go new file mode 100644 index 000000000..ee30a33d5 --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_spec.go @@ -0,0 +1,150 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NicDeviceSpec nic device spec +// +// swagger:model NicDeviceSpec +type NicDeviceSpec struct { + + // detail + Detail *NicDeviceDetail `json:"detail,omitempty"` + + // stats + Stats *NicDeviceStats `json:"stats,omitempty"` +} + +// Validate validates this nic device spec +func (m *NicDeviceSpec) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateDetail(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStats(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceSpec) validateDetail(formats strfmt.Registry) error { + if swag.IsZero(m.Detail) { // not required + return nil + } + + if m.Detail != nil { + if err := m.Detail.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("detail") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("detail") + } + return err + } + } + + return nil +} + +func (m *NicDeviceSpec) validateStats(formats strfmt.Registry) error { + if swag.IsZero(m.Stats) { // not required + return nil + } + + if m.Stats != nil { + if err := m.Stats.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("stats") + } + return err + } + } + + return nil +} + +// ContextValidate validate this nic device spec based on the context it is used +func (m *NicDeviceSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateDetail(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateStats(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceSpec) contextValidateDetail(ctx context.Context, formats strfmt.Registry) error { + + if m.Detail != nil { + if err := m.Detail.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("detail") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("detail") + } + return err + } + } + + return nil +} + +func (m *NicDeviceSpec) contextValidateStats(ctx context.Context, formats strfmt.Registry) error { + + if m.Stats != nil { + if err := m.Stats.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("stats") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *NicDeviceSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NicDeviceSpec) UnmarshalBinary(b []byte) error { + var res NicDeviceSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_spec_list.go b/tools/dpvs-agent/models/nic_device_spec_list.go new file mode 100644 index 000000000..47ed4981f --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_spec_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NicDeviceSpecList nic device spec list +// +// swagger:model NicDeviceSpecList +type NicDeviceSpecList struct { + + // items + Items []*NicDeviceSpec `json:"Items"` +} + +// Validate validates this nic device spec list +func (m *NicDeviceSpecList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceSpecList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this nic device spec list based on the context it is used +func (m *NicDeviceSpecList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceSpecList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *NicDeviceSpecList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NicDeviceSpecList) UnmarshalBinary(b []byte) error { + var res NicDeviceSpecList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/nic_device_stats.go b/tools/dpvs-agent/models/nic_device_stats.go new file mode 100644 index 000000000..27e518db6 --- /dev/null +++ b/tools/dpvs-agent/models/nic_device_stats.go @@ -0,0 +1,342 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NicDeviceStats nic device stats +// +// swagger:model NicDeviceStats +type NicDeviceStats struct { + + // buf avail + BufAvail uint32 `json:"bufAvail,omitempty"` + + // buf inuse + BufInuse uint32 `json:"bufInuse,omitempty"` + + // error bytes q + ErrorBytesQ []NicDeviceQueueData `json:"errorBytesQ"` + + // id + ID uint16 `json:"id,omitempty"` + + // in bytes + InBytes uint64 `json:"inBytes,omitempty"` + + // in bytes q + InBytesQ []NicDeviceQueueData `json:"inBytesQ"` + + // in errors + InErrors uint64 `json:"inErrors,omitempty"` + + // in missed + InMissed uint64 `json:"inMissed,omitempty"` + + // in pkts + InPkts uint64 `json:"inPkts,omitempty"` + + // in pkts q + InPktsQ []NicDeviceQueueData `json:"inPktsQ"` + + // out bytes + OutBytes uint64 `json:"outBytes,omitempty"` + + // out bytes q + OutBytesQ []NicDeviceQueueData `json:"outBytesQ"` + + // out errors + OutErrors uint64 `json:"outErrors,omitempty"` + + // out pkts + OutPkts uint64 `json:"outPkts,omitempty"` + + // out pkts q + OutPktsQ []NicDeviceQueueData `json:"outPktsQ"` + + // rx no mbuf + RxNoMbuf uint64 `json:"rxNoMbuf,omitempty"` +} + +// Validate validates this nic device stats +func (m *NicDeviceStats) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateErrorBytesQ(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInBytesQ(formats); err != nil { + res = append(res, err) + } + + if err := m.validateInPktsQ(formats); err != nil { + res = append(res, err) + } + + if err := m.validateOutBytesQ(formats); err != nil { + res = append(res, err) + } + + if err := m.validateOutPktsQ(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceStats) validateErrorBytesQ(formats strfmt.Registry) error { + if swag.IsZero(m.ErrorBytesQ) { // not required + return nil + } + + for i := 0; i < len(m.ErrorBytesQ); i++ { + + if err := m.ErrorBytesQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("errorBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("errorBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) validateInBytesQ(formats strfmt.Registry) error { + if swag.IsZero(m.InBytesQ) { // not required + return nil + } + + for i := 0; i < len(m.InBytesQ); i++ { + + if err := m.InBytesQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("inBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("inBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) validateInPktsQ(formats strfmt.Registry) error { + if swag.IsZero(m.InPktsQ) { // not required + return nil + } + + for i := 0; i < len(m.InPktsQ); i++ { + + if err := m.InPktsQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("inPktsQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("inPktsQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) validateOutBytesQ(formats strfmt.Registry) error { + if swag.IsZero(m.OutBytesQ) { // not required + return nil + } + + for i := 0; i < len(m.OutBytesQ); i++ { + + if err := m.OutBytesQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("outBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("outBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) validateOutPktsQ(formats strfmt.Registry) error { + if swag.IsZero(m.OutPktsQ) { // not required + return nil + } + + for i := 0; i < len(m.OutPktsQ); i++ { + + if err := m.OutPktsQ[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("outPktsQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("outPktsQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +// ContextValidate validate this nic device stats based on the context it is used +func (m *NicDeviceStats) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateErrorBytesQ(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateInBytesQ(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateInPktsQ(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateOutBytesQ(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateOutPktsQ(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *NicDeviceStats) contextValidateErrorBytesQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.ErrorBytesQ); i++ { + + if err := m.ErrorBytesQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("errorBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("errorBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) contextValidateInBytesQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.InBytesQ); i++ { + + if err := m.InBytesQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("inBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("inBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) contextValidateInPktsQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.InPktsQ); i++ { + + if err := m.InPktsQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("inPktsQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("inPktsQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) contextValidateOutBytesQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.OutBytesQ); i++ { + + if err := m.OutBytesQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("outBytesQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("outBytesQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *NicDeviceStats) contextValidateOutPktsQ(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.OutPktsQ); i++ { + + if err := m.OutPktsQ[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("outPktsQ" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("outPktsQ" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *NicDeviceStats) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *NicDeviceStats) UnmarshalBinary(b []byte) error { + var res NicDeviceStats + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/real_server_expand_list.go b/tools/dpvs-agent/models/real_server_expand_list.go new file mode 100644 index 000000000..4593c3b21 --- /dev/null +++ b/tools/dpvs-agent/models/real_server_expand_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// RealServerExpandList real server expand list +// +// swagger:model RealServerExpandList +type RealServerExpandList struct { + + // items + Items []*RealServerSpecExpand `json:"Items"` +} + +// Validate validates this real server expand list +func (m *RealServerExpandList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerExpandList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this real server expand list based on the context it is used +func (m *RealServerExpandList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerExpandList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *RealServerExpandList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RealServerExpandList) UnmarshalBinary(b []byte) error { + var res RealServerExpandList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/real_server_spec_expand.go b/tools/dpvs-agent/models/real_server_spec_expand.go new file mode 100644 index 000000000..ba2a517db --- /dev/null +++ b/tools/dpvs-agent/models/real_server_spec_expand.go @@ -0,0 +1,150 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// RealServerSpecExpand real server spec expand +// +// swagger:model RealServerSpecExpand +type RealServerSpecExpand struct { + + // spec + Spec *RealServerSpecTiny `json:"Spec,omitempty"` + + // stats + Stats *ServerStats `json:"Stats,omitempty"` +} + +// Validate validates this real server spec expand +func (m *RealServerSpecExpand) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateSpec(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStats(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerSpecExpand) validateSpec(formats strfmt.Registry) error { + if swag.IsZero(m.Spec) { // not required + return nil + } + + if m.Spec != nil { + if err := m.Spec.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Spec") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Spec") + } + return err + } + } + + return nil +} + +func (m *RealServerSpecExpand) validateStats(formats strfmt.Registry) error { + if swag.IsZero(m.Stats) { // not required + return nil + } + + if m.Stats != nil { + if err := m.Stats.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Stats") + } + return err + } + } + + return nil +} + +// ContextValidate validate this real server spec expand based on the context it is used +func (m *RealServerSpecExpand) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateSpec(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateStats(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerSpecExpand) contextValidateSpec(ctx context.Context, formats strfmt.Registry) error { + + if m.Spec != nil { + if err := m.Spec.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Spec") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Spec") + } + return err + } + } + + return nil +} + +func (m *RealServerSpecExpand) contextValidateStats(ctx context.Context, formats strfmt.Registry) error { + + if m.Stats != nil { + if err := m.Stats.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Stats") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *RealServerSpecExpand) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RealServerSpecExpand) UnmarshalBinary(b []byte) error { + var res RealServerSpecExpand + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/real_server_spec_tiny.go b/tools/dpvs-agent/models/real_server_spec_tiny.go new file mode 100644 index 000000000..592c97d95 --- /dev/null +++ b/tools/dpvs-agent/models/real_server_spec_tiny.go @@ -0,0 +1,129 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// RealServerSpecTiny real server spec tiny +// +// swagger:model RealServerSpecTiny +type RealServerSpecTiny struct { + + // inhibited + Inhibited *bool `json:"inhibited,omitempty"` + + // ip + IP string `json:"ip,omitempty"` + + // mode + // Enum: [FNAT SNAT DR TUNNEL NAT] + Mode string `json:"mode,omitempty"` + + // overloaded + Overloaded *bool `json:"overloaded,omitempty"` + + // port + Port uint16 `json:"port"` + + // weight + Weight uint16 `json:"weight"` +} + +// Validate validates this real server spec tiny +func (m *RealServerSpecTiny) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateMode(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var realServerSpecTinyTypeModePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["FNAT","SNAT","DR","TUNNEL","NAT"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + realServerSpecTinyTypeModePropEnum = append(realServerSpecTinyTypeModePropEnum, v) + } +} + +const ( + + // RealServerSpecTinyModeFNAT captures enum value "FNAT" + RealServerSpecTinyModeFNAT string = "FNAT" + + // RealServerSpecTinyModeSNAT captures enum value "SNAT" + RealServerSpecTinyModeSNAT string = "SNAT" + + // RealServerSpecTinyModeDR captures enum value "DR" + RealServerSpecTinyModeDR string = "DR" + + // RealServerSpecTinyModeTUNNEL captures enum value "TUNNEL" + RealServerSpecTinyModeTUNNEL string = "TUNNEL" + + // RealServerSpecTinyModeNAT captures enum value "NAT" + RealServerSpecTinyModeNAT string = "NAT" +) + +// prop value enum +func (m *RealServerSpecTiny) validateModeEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, realServerSpecTinyTypeModePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *RealServerSpecTiny) validateMode(formats strfmt.Registry) error { + if swag.IsZero(m.Mode) { // not required + return nil + } + + // value enum + if err := m.validateModeEnum("mode", "body", m.Mode); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this real server spec tiny based on context it is used +func (m *RealServerSpecTiny) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *RealServerSpecTiny) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RealServerSpecTiny) UnmarshalBinary(b []byte) error { + var res RealServerSpecTiny + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/real_server_tiny_list.go b/tools/dpvs-agent/models/real_server_tiny_list.go new file mode 100644 index 000000000..3d6780b77 --- /dev/null +++ b/tools/dpvs-agent/models/real_server_tiny_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// RealServerTinyList real server tiny list +// +// swagger:model RealServerTinyList +type RealServerTinyList struct { + + // items + Items []*RealServerSpecTiny `json:"Items"` +} + +// Validate validates this real server tiny list +func (m *RealServerTinyList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerTinyList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this real server tiny list based on the context it is used +func (m *RealServerTinyList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *RealServerTinyList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *RealServerTinyList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RealServerTinyList) UnmarshalBinary(b []byte) error { + var res RealServerTinyList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/route_spec.go b/tools/dpvs-agent/models/route_spec.go new file mode 100644 index 000000000..2a7b401b1 --- /dev/null +++ b/tools/dpvs-agent/models/route_spec.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// RouteSpec route spec +// +// swagger:model RouteSpec +type RouteSpec struct { + + // device + Device string `json:"device,omitempty"` + + // dst + Dst string `json:"dst,omitempty"` + + // gateway + Gateway string `json:"gateway,omitempty"` + + // metric + Metric uint32 `json:"metric,omitempty"` + + // mtu + Mtu uint32 `json:"mtu,omitempty"` + + // prefix src + PrefixSrc string `json:"prefixSrc,omitempty"` + + // scope + Scope string `json:"scope,omitempty"` + + // src + Src string `json:"src,omitempty"` +} + +// Validate validates this route spec +func (m *RouteSpec) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this route spec based on context it is used +func (m *RouteSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *RouteSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *RouteSpec) UnmarshalBinary(b []byte) error { + var res RouteSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/server_stats.go b/tools/dpvs-agent/models/server_stats.go new file mode 100644 index 000000000..e2ba38b74 --- /dev/null +++ b/tools/dpvs-agent/models/server_stats.go @@ -0,0 +1,77 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// ServerStats server stats +// +// swagger:model ServerStats +type ServerStats struct { + + // conns + Conns uint64 `json:"Conns,omitempty"` + + // cps + Cps uint32 `json:"Cps,omitempty"` + + // in bps + InBps uint32 `json:"InBps,omitempty"` + + // in bytes + InBytes uint64 `json:"InBytes,omitempty"` + + // in pkts + InPkts uint64 `json:"InPkts,omitempty"` + + // in pps + InPps uint32 `json:"InPps,omitempty"` + + // out bps + OutBps uint32 `json:"OutBps,omitempty"` + + // out bytes + OutBytes uint64 `json:"OutBytes,omitempty"` + + // out pkts + OutPkts uint64 `json:"OutPkts,omitempty"` + + // out pps + OutPps uint32 `json:"OutPps,omitempty"` +} + +// Validate validates this server stats +func (m *ServerStats) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this server stats based on context it is used +func (m *ServerStats) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *ServerStats) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *ServerStats) UnmarshalBinary(b []byte) error { + var res ServerStats + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/status.go b/tools/dpvs-agent/models/status.go new file mode 100644 index 000000000..4b4f3a97d --- /dev/null +++ b/tools/dpvs-agent/models/status.go @@ -0,0 +1,114 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// Status Status of an individual component +// +// swagger:model Status +type Status struct { + + // Human readable status/error/warning message + Msg string `json:"msg,omitempty"` + + // State the component is in + // Enum: [Ok Warning Failure Disabled] + State string `json:"state,omitempty"` +} + +// Validate validates this status +func (m *Status) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateState(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +var statusTypeStatePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["Ok","Warning","Failure","Disabled"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + statusTypeStatePropEnum = append(statusTypeStatePropEnum, v) + } +} + +const ( + + // StatusStateOk captures enum value "Ok" + StatusStateOk string = "Ok" + + // StatusStateWarning captures enum value "Warning" + StatusStateWarning string = "Warning" + + // StatusStateFailure captures enum value "Failure" + StatusStateFailure string = "Failure" + + // StatusStateDisabled captures enum value "Disabled" + StatusStateDisabled string = "Disabled" +) + +// prop value enum +func (m *Status) validateStateEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, statusTypeStatePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *Status) validateState(formats strfmt.Registry) error { + if swag.IsZero(m.State) { // not required + return nil + } + + // value enum + if err := m.validateStateEnum("state", "body", m.State); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this status based on context it is used +func (m *Status) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *Status) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *Status) UnmarshalBinary(b []byte) error { + var res Status + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/virtual_server_list.go b/tools/dpvs-agent/models/virtual_server_list.go new file mode 100644 index 000000000..1880596b5 --- /dev/null +++ b/tools/dpvs-agent/models/virtual_server_list.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// VirtualServerList virtual server list +// +// swagger:model VirtualServerList +type VirtualServerList struct { + + // items + Items []*VirtualServerSpecExpand `json:"Items"` +} + +// Validate validates this virtual server list +func (m *VirtualServerList) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateItems(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerList) validateItems(formats strfmt.Registry) error { + if swag.IsZero(m.Items) { // not required + return nil + } + + for i := 0; i < len(m.Items); i++ { + if swag.IsZero(m.Items[i]) { // not required + continue + } + + if m.Items[i] != nil { + if err := m.Items[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this virtual server list based on the context it is used +func (m *VirtualServerList) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateItems(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerList) contextValidateItems(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.Items); i++ { + + if m.Items[i] != nil { + if err := m.Items[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Items" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Items" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// MarshalBinary interface implementation +func (m *VirtualServerList) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *VirtualServerList) UnmarshalBinary(b []byte) error { + var res VirtualServerList + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/virtual_server_spec_expand.go b/tools/dpvs-agent/models/virtual_server_spec_expand.go new file mode 100644 index 000000000..dd887a72d --- /dev/null +++ b/tools/dpvs-agent/models/virtual_server_spec_expand.go @@ -0,0 +1,438 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// VirtualServerSpecExpand virtual server spec expand +// +// swagger:model VirtualServerSpecExpand +type VirtualServerSpecExpand struct { + + // addr + Addr string `json:"Addr,omitempty"` + + // af + Af uint32 `json:"Af,omitempty"` + + // bps + Bps uint32 `json:"Bps,omitempty"` + + // conn timeout + ConnTimeout uint32 `json:"ConnTimeout,omitempty"` + + // dest check + DestCheck []DestCheckSpec `json:"DestCheck"` + + // expire quiescent + // Enum: [true false] + ExpireQuiescent string `json:"ExpireQuiescent,omitempty"` + + // flags + Flags string `json:"Flags,omitempty"` + + // fwmark + Fwmark uint32 `json:"Fwmark,omitempty"` + + // limit proportion + LimitProportion uint32 `json:"LimitProportion,omitempty"` + + // match + Match *MatchSpec `json:"Match,omitempty"` + + // netmask + Netmask uint32 `json:"Netmask,omitempty"` + + // port + Port uint16 `json:"Port,omitempty"` + + // proto + Proto uint16 `json:"Proto,omitempty"` + + // r ss + RSs *RealServerExpandList `json:"RSs,omitempty"` + + // sched name + // Enum: [rr wrr wlc connhash] + SchedName string `json:"SchedName,omitempty"` + + // stats + Stats *ServerStats `json:"Stats,omitempty"` + + // sync proxy + // Enum: [true false] + SyncProxy string `json:"SyncProxy,omitempty"` + + // timeout + Timeout uint32 `json:"Timeout,omitempty"` +} + +// Validate validates this virtual server spec expand +func (m *VirtualServerSpecExpand) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateDestCheck(formats); err != nil { + res = append(res, err) + } + + if err := m.validateExpireQuiescent(formats); err != nil { + res = append(res, err) + } + + if err := m.validateMatch(formats); err != nil { + res = append(res, err) + } + + if err := m.validateRSs(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSchedName(formats); err != nil { + res = append(res, err) + } + + if err := m.validateStats(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSyncProxy(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerSpecExpand) validateDestCheck(formats strfmt.Registry) error { + if swag.IsZero(m.DestCheck) { // not required + return nil + } + + for i := 0; i < len(m.DestCheck); i++ { + + if err := m.DestCheck[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("DestCheck" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("DestCheck" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +var virtualServerSpecExpandTypeExpireQuiescentPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["true","false"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecExpandTypeExpireQuiescentPropEnum = append(virtualServerSpecExpandTypeExpireQuiescentPropEnum, v) + } +} + +const ( + + // VirtualServerSpecExpandExpireQuiescentTrue captures enum value "true" + VirtualServerSpecExpandExpireQuiescentTrue string = "true" + + // VirtualServerSpecExpandExpireQuiescentFalse captures enum value "false" + VirtualServerSpecExpandExpireQuiescentFalse string = "false" +) + +// prop value enum +func (m *VirtualServerSpecExpand) validateExpireQuiescentEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeExpireQuiescentPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecExpand) validateExpireQuiescent(formats strfmt.Registry) error { + if swag.IsZero(m.ExpireQuiescent) { // not required + return nil + } + + // value enum + if err := m.validateExpireQuiescentEnum("ExpireQuiescent", "body", m.ExpireQuiescent); err != nil { + return err + } + + return nil +} + +func (m *VirtualServerSpecExpand) validateMatch(formats strfmt.Registry) error { + if swag.IsZero(m.Match) { // not required + return nil + } + + if m.Match != nil { + if err := m.Match.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Match") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Match") + } + return err + } + } + + return nil +} + +func (m *VirtualServerSpecExpand) validateRSs(formats strfmt.Registry) error { + if swag.IsZero(m.RSs) { // not required + return nil + } + + if m.RSs != nil { + if err := m.RSs.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("RSs") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("RSs") + } + return err + } + } + + return nil +} + +var virtualServerSpecExpandTypeSchedNamePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["rr","wrr","wlc","connhash"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecExpandTypeSchedNamePropEnum = append(virtualServerSpecExpandTypeSchedNamePropEnum, v) + } +} + +const ( + + // VirtualServerSpecExpandSchedNameRr captures enum value "rr" + VirtualServerSpecExpandSchedNameRr string = "rr" + + // VirtualServerSpecExpandSchedNameWrr captures enum value "wrr" + VirtualServerSpecExpandSchedNameWrr string = "wrr" + + // VirtualServerSpecExpandSchedNameWlc captures enum value "wlc" + VirtualServerSpecExpandSchedNameWlc string = "wlc" + + // VirtualServerSpecExpandSchedNameConnhash captures enum value "connhash" + VirtualServerSpecExpandSchedNameConnhash string = "connhash" +) + +// prop value enum +func (m *VirtualServerSpecExpand) validateSchedNameEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeSchedNamePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecExpand) validateSchedName(formats strfmt.Registry) error { + if swag.IsZero(m.SchedName) { // not required + return nil + } + + // value enum + if err := m.validateSchedNameEnum("SchedName", "body", m.SchedName); err != nil { + return err + } + + return nil +} + +func (m *VirtualServerSpecExpand) validateStats(formats strfmt.Registry) error { + if swag.IsZero(m.Stats) { // not required + return nil + } + + if m.Stats != nil { + if err := m.Stats.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Stats") + } + return err + } + } + + return nil +} + +var virtualServerSpecExpandTypeSyncProxyPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["true","false"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecExpandTypeSyncProxyPropEnum = append(virtualServerSpecExpandTypeSyncProxyPropEnum, v) + } +} + +const ( + + // VirtualServerSpecExpandSyncProxyTrue captures enum value "true" + VirtualServerSpecExpandSyncProxyTrue string = "true" + + // VirtualServerSpecExpandSyncProxyFalse captures enum value "false" + VirtualServerSpecExpandSyncProxyFalse string = "false" +) + +// prop value enum +func (m *VirtualServerSpecExpand) validateSyncProxyEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeSyncProxyPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecExpand) validateSyncProxy(formats strfmt.Registry) error { + if swag.IsZero(m.SyncProxy) { // not required + return nil + } + + // value enum + if err := m.validateSyncProxyEnum("SyncProxy", "body", m.SyncProxy); err != nil { + return err + } + + return nil +} + +// ContextValidate validate this virtual server spec expand based on the context it is used +func (m *VirtualServerSpecExpand) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateDestCheck(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateMatch(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateRSs(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateStats(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerSpecExpand) contextValidateDestCheck(ctx context.Context, formats strfmt.Registry) error { + + for i := 0; i < len(m.DestCheck); i++ { + + if err := m.DestCheck[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("DestCheck" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("DestCheck" + "." + strconv.Itoa(i)) + } + return err + } + + } + + return nil +} + +func (m *VirtualServerSpecExpand) contextValidateMatch(ctx context.Context, formats strfmt.Registry) error { + + if m.Match != nil { + if err := m.Match.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Match") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Match") + } + return err + } + } + + return nil +} + +func (m *VirtualServerSpecExpand) contextValidateRSs(ctx context.Context, formats strfmt.Registry) error { + + if m.RSs != nil { + if err := m.RSs.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("RSs") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("RSs") + } + return err + } + } + + return nil +} + +func (m *VirtualServerSpecExpand) contextValidateStats(ctx context.Context, formats strfmt.Registry) error { + + if m.Stats != nil { + if err := m.Stats.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Stats") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Stats") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *VirtualServerSpecExpand) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *VirtualServerSpecExpand) UnmarshalBinary(b []byte) error { + var res VirtualServerSpecExpand + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/virtual_server_spec_tiny.go b/tools/dpvs-agent/models/virtual_server_spec_tiny.go new file mode 100644 index 000000000..3ebfd849c --- /dev/null +++ b/tools/dpvs-agent/models/virtual_server_spec_tiny.go @@ -0,0 +1,183 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "encoding/json" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// VirtualServerSpecTiny virtual server spec tiny +// +// swagger:model VirtualServerSpecTiny +type VirtualServerSpecTiny struct { + + // bps + Bps uint32 `json:"Bps,omitempty"` + + // conn timeout + ConnTimeout uint32 `json:"ConnTimeout,omitempty"` + + // expire quiescent + ExpireQuiescent *bool `json:"ExpireQuiescent,omitempty"` + + // fwmark + Fwmark uint32 `json:"Fwmark,omitempty"` + + // limit proportion + LimitProportion uint32 `json:"LimitProportion,omitempty"` + + // match + Match *MatchSpec `json:"Match,omitempty"` + + // sched name + // Enum: [rr wrr wlc connhash] + SchedName string `json:"SchedName,omitempty"` + + // sync proxy + SyncProxy *bool `json:"SyncProxy,omitempty"` + + // timeout + Timeout uint32 `json:"Timeout,omitempty"` +} + +// Validate validates this virtual server spec tiny +func (m *VirtualServerSpecTiny) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateMatch(formats); err != nil { + res = append(res, err) + } + + if err := m.validateSchedName(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerSpecTiny) validateMatch(formats strfmt.Registry) error { + if swag.IsZero(m.Match) { // not required + return nil + } + + if m.Match != nil { + if err := m.Match.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Match") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Match") + } + return err + } + } + + return nil +} + +var virtualServerSpecTinyTypeSchedNamePropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["rr","wrr","wlc","connhash"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecTinyTypeSchedNamePropEnum = append(virtualServerSpecTinyTypeSchedNamePropEnum, v) + } +} + +const ( + + // VirtualServerSpecTinySchedNameRr captures enum value "rr" + VirtualServerSpecTinySchedNameRr string = "rr" + + // VirtualServerSpecTinySchedNameWrr captures enum value "wrr" + VirtualServerSpecTinySchedNameWrr string = "wrr" + + // VirtualServerSpecTinySchedNameWlc captures enum value "wlc" + VirtualServerSpecTinySchedNameWlc string = "wlc" + + // VirtualServerSpecTinySchedNameConnhash captures enum value "connhash" + VirtualServerSpecTinySchedNameConnhash string = "connhash" +) + +// prop value enum +func (m *VirtualServerSpecTiny) validateSchedNameEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecTinyTypeSchedNamePropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecTiny) validateSchedName(formats strfmt.Registry) error { + if swag.IsZero(m.SchedName) { // not required + return nil + } + + // value enum + if err := m.validateSchedNameEnum("SchedName", "body", m.SchedName); err != nil { + return err + } + + return nil +} + +// ContextValidate validate this virtual server spec tiny based on the context it is used +func (m *VirtualServerSpecTiny) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := m.contextValidateMatch(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *VirtualServerSpecTiny) contextValidateMatch(ctx context.Context, formats strfmt.Registry) error { + + if m.Match != nil { + if err := m.Match.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("Match") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("Match") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (m *VirtualServerSpecTiny) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *VirtualServerSpecTiny) UnmarshalBinary(b []byte) error { + var res VirtualServerSpecTiny + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/models/vlan_spec.go b/tools/dpvs-agent/models/vlan_spec.go new file mode 100644 index 000000000..ef77bf716 --- /dev/null +++ b/tools/dpvs-agent/models/vlan_spec.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package models + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// VlanSpec vlan spec +// +// swagger:model VlanSpec +type VlanSpec struct { + + // device + Device string `json:"device,omitempty"` + + // id + ID string `json:"id,omitempty"` + + // name + Name string `json:"name,omitempty"` +} + +// Validate validates this vlan spec +func (m *VlanSpec) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this vlan spec based on context it is used +func (m *VlanSpec) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *VlanSpec) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *VlanSpec) UnmarshalBinary(b []byte) error { + var res VlanSpec + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/tools/dpvs-agent/pkg/ipc/pool/conn.go b/tools/dpvs-agent/pkg/ipc/pool/conn.go new file mode 100644 index 000000000..6f7034653 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/pool/conn.go @@ -0,0 +1,316 @@ +package pool + +import ( + "bufio" + "context" + "net" + "sync/atomic" + "time" + + "github.com/dpvs-agent/pkg/ipc/proto" +) + +type BadConnError struct { + wrapped error +} + +var _ error = (*BadConnError)(nil) + +func (e BadConnError) Error() string { + s := "dpvs: Conn is in a bad state" + if e.wrapped != nil { + s += ": " + e.wrapped.Error() + } + return s +} + +func (e BadConnError) Unwrap() error { + return e.wrapped +} + +//-------------------------------------- + +var noDeadline = time.Time{} + +type Conn struct { + usedAt int64 // atomic + netConn net.Conn + + rd *proto.Reader + bw *bufio.Writer + wr *proto.Writer + + Inited bool + pooled bool + createdAt time.Time +} + +func NewConn(netConn net.Conn) *Conn { + cn := &Conn{ + netConn: netConn, + createdAt: time.Now(), + } + cn.rd = proto.NewReader(netConn) + cn.bw = bufio.NewWriter(netConn) + cn.wr = proto.NewWriter(cn.bw) + cn.SetUsedAt(time.Now()) + return cn +} + +func (cn *Conn) UsedAt() time.Time { + unix := atomic.LoadInt64(&cn.usedAt) + return time.Unix(unix, 0) +} + +func (cn *Conn) SetUsedAt(tm time.Time) { + atomic.StoreInt64(&cn.usedAt, tm.Unix()) +} + +func (cn *Conn) SetNetConn(netConn net.Conn) { + cn.netConn = netConn + cn.rd.Reset(netConn) + cn.bw.Reset(netConn) +} + +/* +func (cn *Conn) Write(b []byte) (int, error) { + offset := 0 + left := len(b) + for left > 0 { + written, err := cn.write(b[offset:]) + if err != nil { + return offset, err + } + left -= written + offset += written + } + return offset, nil +} +*/ + +type ConnWriteIf interface { + Sizeof() uint64 +} + +func (cn *Conn) Write(o ConnWriteIf) error { + buf := Package(o) + _, err := cn.writeN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (cn *Conn) WriteN(b []byte, n int) (int, error) { + return cn.writeN(b, n) +} + +func (cn *Conn) writeN(b []byte, n int) (int, error) { + if n > 0 && n <= len(b) { + if err := cn.SetWriteBuffer(n); err != nil { + return 0, err + } + } + + return cn.write(b) +} + +/* +func (cn *Conn) Read(b []byte) (int, error) { + offset := 0 + left := len(b) + for left > 0 { + readed, err := cn.read(b[offset:]) + if err != nil { + return offset, err + } + offset += readed + left -= readed + } + return offset, nil +} +*/ + +type ConnReadIf interface { + Sizeof() uint64 + Dump([]byte) bool +} + +func (cn *Conn) Read(o ConnReadIf) error { + buf, err := cn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +func (cn *Conn) Release(n int) { + cn.ReadN(n) +} + +func (cn *Conn) ReadN(n int) ([]byte, error) { + return cn.readN(n) +} + +func (cn *Conn) readN(n int) ([]byte, error) { + if err := cn.SetReadBuffer(n); err != nil { + return nil, err + } + + b := make([]byte, n) + readed, err := cn.read(b) + if err != nil || readed != n { + return nil, err + } + return b, nil +} + +func (cn *Conn) write(b []byte) (int, error) { + return cn.netConn.Write(b) +} + +func (cn *Conn) read(b []byte) (int, error) { + return cn.netConn.Read(b) +} + +func (cn *Conn) SetWriteBuffer(bytes int) error { + conn := cn.netConn + if unix, ok := conn.(*net.UnixConn); ok { + return unix.SetWriteBuffer(bytes) + } + if tc, ok := conn.(*net.TCPConn); ok { + return tc.SetWriteBuffer(bytes) + } + if uc, ok := conn.(*net.UDPConn); ok { + return uc.SetWriteBuffer(bytes) + } + if ic, ok := conn.(*net.IPConn); ok { + return ic.SetWriteBuffer(bytes) + } + return nil +} + +func (cn *Conn) SetReadBuffer(bytes int) error { + conn := cn.netConn + if unix, ok := conn.(*net.UnixConn); ok { + return unix.SetReadBuffer(bytes) + } + if tc, ok := conn.(*net.TCPConn); ok { + return tc.SetReadBuffer(bytes) + } + if uc, ok := conn.(*net.UDPConn); ok { + return uc.SetReadBuffer(bytes) + } + if ic, ok := conn.(*net.IPConn); ok { + return ic.SetReadBuffer(bytes) + } + return nil +} + +func (cn *Conn) RemoteAddr() net.Addr { + if cn.netConn != nil { + return cn.netConn.RemoteAddr() + } + return nil +} + +func (cn *Conn) Close() error { + return cn.netConn.Close() +} + +func (cn *Conn) deadline(ctx context.Context, timeout time.Duration) time.Time { + tm := time.Now() + cn.SetUsedAt(tm) + + if timeout > 0 { + tm = tm.Add(timeout) + } + + if ctx != nil { + deadline, ok := ctx.Deadline() + if ok { + if timeout == 0 { + return deadline + } + if deadline.Before(tm) { + return deadline + } + return tm + } + } + + if timeout > 0 { + return tm + } + + return noDeadline +} + +func (cn *Conn) WithWriter(ctx context.Context, timeout time.Duration, fn func(wr *proto.Writer) error) error { + if err := cn.netConn.SetDeadline(cn.deadline(ctx, timeout)); err != nil { + return err + } + + if cn.bw.Buffered() > 0 { + cn.bw.Reset(cn.netConn) + } + + if err := fn(cn.wr); err != nil { + return err + } + + if err := cn.bw.Flush(); err != nil { + return err + } + + return nil + /* + return internal.WithSpan(ctx, "dpvs-agent.with_writer", func(ctx context.Context, span trace.Span) error { + if err := cn.netConn.SetWriteDeadline(cn.deadline(ctx, timeout)); err != nil { + return internal.RecordError(ctx, span, err) + } + + if cn.bw.Buffered() > 0 { + cn.bw.Reset(cn.netConn) + } + + if err := fn(cn.wr); err != nil { + return internal.RecordError(ctx, span, err) + } + + if err := cn.bw.Flush(); err != nil { + return internal.RecordError(ctx, span, err) + } + + internal.WritesCounter.Add(ctx, 1) + + return nil + }) + */ +} + +func (cn *Conn) WithReader(ctx context.Context, timeout time.Duration, fn func(rd *proto.Reader) error) error { + if err := cn.netConn.SetDeadline(cn.deadline(ctx, timeout)); err != nil { + return err + } + + if err := fn(cn.rd); err != nil { + return err + } + + return nil + /* + return internal.WithSpan(ctx, "dpvs-agent.with_reader", func(ctx context.Context, span trace.Span) error { + if err := cn.netConn.SetReadDeadline(cn.deadline(ctx, timeout)); err != nil { + return internal.RecordError(ctx, span, err) + } + if err := fn(cn.rd); err != nil { + return internal.RecordError(ctx, span, err) + } + return nil + }) + */ +} diff --git a/tools/dpvs-agent/pkg/ipc/pool/pool.go b/tools/dpvs-agent/pkg/ipc/pool/pool.go new file mode 100644 index 000000000..c88d9d82d --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/pool/pool.go @@ -0,0 +1,523 @@ +package pool + +import ( + "context" + "errors" + "net" + "sync" + "sync/atomic" + "time" +) + +var ( + ErrClosed = errors.New("client is closed") + ErrPoolTimeout = errors.New("connection pool timeout") +) + +var timers = sync.Pool{ + New: func() interface{} { + t := time.NewTimer(time.Hour) + t.Stop() + return t + }, +} + +// Stats contains pool state information and accumulated stats. +type Stats struct { + Hits uint32 // number of times free connection was found in the pool + Misses uint32 // number of times free connection was NOT found in the pool + Timeouts uint32 // number of times a wait timeout occurred + + TotalConns uint32 // number of total connections in the pool + IdleConns uint32 // number of idle connections in the pool + StaleConns uint32 // number of stale connections removed from the pool +} + +type Pooler interface { + NewConn(context.Context) (*Conn, error) + CloseConn(*Conn) error + + Get(context.Context) (*Conn, error) + Put(context.Context, *Conn) + Remove(context.Context, *Conn, error) + + Len() int + IdleLen() int + Stats() *Stats + + Close() error +} + +type Options struct { + Dialer func(context.Context) (net.Conn, error) + OnClose func(*Conn) error + + PoolSize int + MinIdleConns int + MaxConnAge time.Duration + PoolTimeout time.Duration + IdleTimeout time.Duration + IdleCheckFrequency time.Duration +} + +type lastDialErrorWrap struct { + err error +} + +type ConnPool struct { + opt *Options + + dialErrorsNum uint32 // atomic + + lastDialError atomic.Value + + queue chan struct{} + + connsMu sync.Mutex + conns []*Conn + idleConns []*Conn + poolSize int + idleConnsLen int + + stats Stats + + _closed uint32 // atomic + closedCh chan struct{} +} + +var _ Pooler = (*ConnPool)(nil) + +func NewConnPool(opt *Options) *ConnPool { + p := &ConnPool{ + opt: opt, + + queue: make(chan struct{}, opt.PoolSize), + conns: make([]*Conn, 0, opt.PoolSize), + idleConns: make([]*Conn, 0, opt.PoolSize), + closedCh: make(chan struct{}), + } + + p.connsMu.Lock() + p.checkMinIdleConns() + p.connsMu.Unlock() + + if opt.IdleTimeout > 0 && opt.IdleCheckFrequency > 0 { + go p.reaper(opt.IdleCheckFrequency) + } + + return p +} + +func (p *ConnPool) checkMinIdleConns() { + if p.opt.MinIdleConns == 0 { + return + } + for p.poolSize < p.opt.PoolSize && p.idleConnsLen < p.opt.MinIdleConns { + p.poolSize++ + p.idleConnsLen++ + go func() { + err := p.addIdleConn() + if err != nil { + p.connsMu.Lock() + p.poolSize-- + p.idleConnsLen-- + p.connsMu.Unlock() + } + }() + } +} + +func (p *ConnPool) addIdleConn() error { + cn, err := p.dialConn(context.TODO(), true) + if err != nil { + return err + } + + p.connsMu.Lock() + p.conns = append(p.conns, cn) + p.idleConns = append(p.idleConns, cn) + p.connsMu.Unlock() + return nil +} + +func (p *ConnPool) NewConn(ctx context.Context) (*Conn, error) { + return p.newConn(ctx, false) +} + +func (p *ConnPool) newConn(ctx context.Context, pooled bool) (*Conn, error) { + cn, err := p.dialConn(ctx, pooled) + if err != nil { + return nil, err + } + + p.connsMu.Lock() + p.conns = append(p.conns, cn) + if pooled { + // If pool is full remove the cn on next Put. + if p.poolSize >= p.opt.PoolSize { + cn.pooled = false + } else { + p.poolSize++ + } + } + p.connsMu.Unlock() + + return cn, nil +} + +func (p *ConnPool) dialConn(ctx context.Context, pooled bool) (*Conn, error) { + if p.closed() { + return nil, ErrClosed + } + + if atomic.LoadUint32(&p.dialErrorsNum) >= uint32(p.opt.PoolSize) { + return nil, p.getLastDialError() + } + + netConn, err := p.opt.Dialer(ctx) + if err != nil { + p.setLastDialError(err) + if atomic.AddUint32(&p.dialErrorsNum, 1) == uint32(p.opt.PoolSize) { + go p.tryDial() + } + return nil, err + } + + // internal.NewConnectionsCounter.Add(ctx, 1) + cn := NewConn(netConn) + cn.pooled = pooled + return cn, nil +} + +func (p *ConnPool) tryDial() { + for { + if p.closed() { + return + } + + conn, err := p.opt.Dialer(context.Background()) + if err != nil { + p.setLastDialError(err) + time.Sleep(time.Second) + continue + } + + atomic.StoreUint32(&p.dialErrorsNum, 0) + _ = conn.Close() + return + } +} + +func (p *ConnPool) setLastDialError(err error) { + p.lastDialError.Store(&lastDialErrorWrap{err: err}) +} + +func (p *ConnPool) getLastDialError() error { + err, _ := p.lastDialError.Load().(*lastDialErrorWrap) + if err != nil { + return err.err + } + return nil +} + +// Get returns existed connection from the pool or creates a new one. +func (p *ConnPool) Get(ctx context.Context) (*Conn, error) { + if p.closed() { + return nil, ErrClosed + } + + err := p.waitTurn(ctx) + if err != nil { + return nil, err + } + + for { + p.connsMu.Lock() + cn := p.popIdle() + p.connsMu.Unlock() + + if cn == nil { + break + } + + if p.isStaleConn(cn) { + _ = p.CloseConn(cn) + continue + } + + atomic.AddUint32(&p.stats.Hits, 1) + return cn, nil + } + + atomic.AddUint32(&p.stats.Misses, 1) + + newcn, err := p.newConn(ctx, true) + if err != nil { + p.freeTurn() + return nil, err + } + + return newcn, nil +} + +func (p *ConnPool) getTurn() { + p.queue <- struct{}{} +} + +func (p *ConnPool) waitTurn(ctx context.Context) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + select { + case p.queue <- struct{}{}: + return nil + default: + } + + timer := timers.Get().(*time.Timer) + timer.Reset(p.opt.PoolTimeout) + + select { + case <-ctx.Done(): + if !timer.Stop() { + <-timer.C + } + timers.Put(timer) + return ctx.Err() + case p.queue <- struct{}{}: + if !timer.Stop() { + <-timer.C + } + timers.Put(timer) + return nil + case <-timer.C: + timers.Put(timer) + atomic.AddUint32(&p.stats.Timeouts, 1) + return ErrPoolTimeout + } +} + +func (p *ConnPool) freeTurn() { + <-p.queue +} + +func (p *ConnPool) popIdle() *Conn { + if len(p.idleConns) == 0 { + return nil + } + + idx := len(p.idleConns) - 1 + cn := p.idleConns[idx] + p.idleConns = p.idleConns[:idx] + p.idleConnsLen-- + p.checkMinIdleConns() + return cn +} + +func (p *ConnPool) Put(ctx context.Context, cn *Conn) { + if cn.rd.Buffered() > 0 { + // internal.Logger.Printf(ctx, "Conn has unread data") + p.Remove(ctx, cn, BadConnError{}) + return + } + + if !cn.pooled { + p.Remove(ctx, cn, nil) + return + } + + p.connsMu.Lock() + p.idleConns = append(p.idleConns, cn) + p.idleConnsLen++ + p.connsMu.Unlock() + p.freeTurn() +} + +func (p *ConnPool) Remove(ctx context.Context, cn *Conn, reason error) { + p.removeConnWithLock(cn) + p.freeTurn() + _ = p.closeConn(cn) +} + +func (p *ConnPool) CloseConn(cn *Conn) error { + p.removeConnWithLock(cn) + return p.closeConn(cn) +} + +func (p *ConnPool) removeConnWithLock(cn *Conn) { + p.connsMu.Lock() + p.removeConn(cn) + p.connsMu.Unlock() +} + +func (p *ConnPool) removeConn(cn *Conn) { + for i, c := range p.conns { + if c == cn { + p.conns = append(p.conns[:i], p.conns[i+1:]...) + if cn.pooled { + p.poolSize-- + p.checkMinIdleConns() + } + return + } + } +} + +func (p *ConnPool) closeConn(cn *Conn) error { + if p.opt.OnClose != nil { + _ = p.opt.OnClose(cn) + } + return cn.Close() +} + +// Len returns total number of connections. +func (p *ConnPool) Len() int { + p.connsMu.Lock() + n := len(p.conns) + p.connsMu.Unlock() + return n +} + +// IdleLen returns number of idle connections. +func (p *ConnPool) IdleLen() int { + p.connsMu.Lock() + n := p.idleConnsLen + p.connsMu.Unlock() + return n +} + +func (p *ConnPool) Stats() *Stats { + idleLen := p.IdleLen() + return &Stats{ + Hits: atomic.LoadUint32(&p.stats.Hits), + Misses: atomic.LoadUint32(&p.stats.Misses), + Timeouts: atomic.LoadUint32(&p.stats.Timeouts), + + TotalConns: uint32(p.Len()), + IdleConns: uint32(idleLen), + StaleConns: atomic.LoadUint32(&p.stats.StaleConns), + } +} + +func (p *ConnPool) closed() bool { + return atomic.LoadUint32(&p._closed) == 1 +} + +func (p *ConnPool) Filter(fn func(*Conn) bool) error { + p.connsMu.Lock() + defer p.connsMu.Unlock() + + var firstErr error + for _, cn := range p.conns { + if fn(cn) { + if err := p.closeConn(cn); err != nil && firstErr == nil { + firstErr = err + } + } + } + return firstErr +} + +func (p *ConnPool) Close() error { + if !atomic.CompareAndSwapUint32(&p._closed, 0, 1) { + return ErrClosed + } + close(p.closedCh) + + var firstErr error + p.connsMu.Lock() + for _, cn := range p.conns { + if err := p.closeConn(cn); err != nil && firstErr == nil { + firstErr = err + } + } + p.conns = nil + p.poolSize = 0 + p.idleConns = nil + p.idleConnsLen = 0 + p.connsMu.Unlock() + + return firstErr +} + +func (p *ConnPool) reaper(frequency time.Duration) { + ticker := time.NewTicker(frequency) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + // It is possible that ticker and closedCh arrive together, + // and select pseudo-randomly pick ticker case, we double + // check here to prevent being executed after closed. + if p.closed() { + return + } + _, err := p.ReapStaleConns() + if err != nil { + // internal.Logger.Printf(context.Background(), "ReapStaleConns failed: %s", err) + continue + } + case <-p.closedCh: + return + } + } +} + +func (p *ConnPool) ReapStaleConns() (int, error) { + var n int + for { + p.getTurn() + + p.connsMu.Lock() + cn := p.reapStaleConn() + p.connsMu.Unlock() + + p.freeTurn() + + if cn != nil { + _ = p.closeConn(cn) + n++ + } else { + break + } + } + atomic.AddUint32(&p.stats.StaleConns, uint32(n)) + return n, nil +} + +func (p *ConnPool) reapStaleConn() *Conn { + if len(p.idleConns) == 0 { + return nil + } + + cn := p.idleConns[0] + if !p.isStaleConn(cn) { + return nil + } + + p.idleConns = append(p.idleConns[:0], p.idleConns[1:]...) + p.idleConnsLen-- + p.removeConn(cn) + + return cn +} + +func (p *ConnPool) isStaleConn(cn *Conn) bool { + if p.opt.IdleTimeout == 0 && p.opt.MaxConnAge == 0 { + return false + } + + now := time.Now() + if p.opt.IdleTimeout > 0 && now.Sub(cn.UsedAt()) >= p.opt.IdleTimeout { + return true + } + if p.opt.MaxConnAge > 0 && now.Sub(cn.createdAt) >= p.opt.MaxConnAge { + return true + } + + return false +} diff --git a/tools/dpvs-agent/pkg/ipc/pool/util.go b/tools/dpvs-agent/pkg/ipc/pool/util.go new file mode 100644 index 000000000..3bd67fbed --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/pool/util.go @@ -0,0 +1,12 @@ +package pool + +import ( + "bytes" + "encoding/binary" +) + +func Package(o ConnWriteIf) []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} diff --git a/tools/dpvs-agent/pkg/ipc/proto/reader.go b/tools/dpvs-agent/pkg/ipc/proto/reader.go new file mode 100644 index 000000000..b77dee8d1 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/proto/reader.go @@ -0,0 +1,335 @@ +package proto + +import ( + "bufio" + "fmt" + "io" +) + +const ( + ErrorReply = '-' + StatusReply = '+' + IntReply = ':' + StringReply = '$' + ArrayReply = '*' +) + +//------------------------------------------------------------------------------ + +const Nil = DpvsError("dpvs: nil") + +type DpvsError string + +func (e DpvsError) Error() string { return string(e) } + +func (DpvsError) DpvsError() {} + +//------------------------------------------------------------------------------ + +type MultiBulkParse func(*Reader, int64) (interface{}, error) + +type Reader struct { + rd *bufio.Reader + _buf []byte +} + +func NewReader(rd io.Reader) *Reader { + return &Reader{ + rd: bufio.NewReader(rd), + _buf: make([]byte, 64), + } +} + +func (r *Reader) Buffered() int { + return r.rd.Buffered() +} + +func (r *Reader) Peek(n int) ([]byte, error) { + return r.rd.Peek(n) +} + +func (r *Reader) Reset(rd io.Reader) { + r.rd.Reset(rd) +} + +func (r *Reader) buf(n int) []byte { + if n <= cap(r._buf) { + return r._buf[:n] + } + d := n - cap(r._buf) + r._buf = append(r._buf, make([]byte, d)...) + return r._buf +} + +func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) { + /* + line, err := r.ReadLine() + + if err != nil { + return nil, err + } + + switch line[0] { + case ErrorReply: + return nil, ParseErrorReply(line) + case StatusReply: + return string(line[1:]), nil + case IntReply: + return util.ParseInt(line[1:], 10, 64) + case StringReply: + return r.readStringReply(line) + case ArrayReply: + n, err := parseArrayLen(line) + if err != nil { + return nil, err + } + if m == nil { + err := fmt.Errorf("dpvs: got %.100q, but multi bulk parser is nil", line) + return nil, err + } + return m(r, n) + } + */ + return nil, fmt.Errorf("dpvs read failed") +} + +/* +func (r *Reader) ReadLine() ([]byte, error) { + line, err := r.readLine() + if err != nil { + return nil, err + } + if isNilReply(line) { + return nil, Nil + } + return line, nil +} + +// readLine that returns an error if: +// - there is a pending read error; +// - or line does not end with \r\n. +func (r *Reader) readLine() ([]byte, error) { + b, err := r.rd.ReadSlice('\n') + if err != nil { + if err != bufio.ErrBufferFull { + return nil, err + } + + full := make([]byte, len(b)) + copy(full, b) + + b, err = r.rd.ReadBytes('\n') + if err != nil { + return nil, err + } + + full = append(full, b...) + b = full + } + if len(b) <= 2 || b[len(b)-1] != '\n' || b[len(b)-2] != '\r' { + return nil, fmt.Errorf("dpvs: invalid reply: %q", b) + } + return b[:len(b)-2], nil +} + +func (r *Reader) ReadIntReply() (int64, error) { + line, err := r.ReadLine() + if err != nil { + return 0, err + } + switch line[0] { + case ErrorReply: + return 0, ParseErrorReply(line) + case IntReply: + return util.ParseInt(line[1:], 10, 64) + default: + return 0, fmt.Errorf("dpvs: can't parse int reply: %.100q", line) + } +} + +func (r *Reader) ReadString() (string, error) { + line, err := r.ReadLine() + if err != nil { + return "", err + } + switch line[0] { + case ErrorReply: + return "", ParseErrorReply(line) + case StringReply: + return r.readStringReply(line) + case StatusReply: + return string(line[1:]), nil + case IntReply: + return string(line[1:]), nil + default: + return "", fmt.Errorf("dpvs: can't parse reply=%.100q reading string", line) + } +} + +func (r *Reader) readStringReply(line []byte) (string, error) { + if isNilReply(line) { + return "", Nil + } + + replyLen, err := util.Atoi(line[1:]) + if err != nil { + return "", err + } + + b := make([]byte, replyLen+2) + _, err = io.ReadFull(r.rd, b) + if err != nil { + return "", err + } + + return util.BytesToString(b[:replyLen]), nil +} + +func (r *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) { + line, err := r.ReadLine() + if err != nil { + return nil, err + } + switch line[0] { + case ErrorReply: + return nil, ParseErrorReply(line) + case ArrayReply: + n, err := parseArrayLen(line) + if err != nil { + return nil, err + } + return m(r, n) + default: + return nil, fmt.Errorf("dpvs: can't parse array reply: %.100q", line) + } +} + +func (r *Reader) ReadArrayLen() (int, error) { + line, err := r.ReadLine() + if err != nil { + return 0, err + } + switch line[0] { + case ErrorReply: + return 0, ParseErrorReply(line) + case ArrayReply: + n, err := parseArrayLen(line) + if err != nil { + return 0, err + } + return int(n), nil + default: + return 0, fmt.Errorf("dpvs: can't parse array reply: %.100q", line) + } +} +func (r *Reader) ReadScanReply() ([]string, uint64, error) { + n, err := r.ReadArrayLen() + if err != nil { + return nil, 0, err + } + if n != 2 { + return nil, 0, fmt.Errorf("dpvs: got %d elements in scan reply, expected 2", n) + } + + cursor, err := r.ReadUint() + if err != nil { + return nil, 0, err + } + + n, err = r.ReadArrayLen() + if err != nil { + return nil, 0, err + } + + keys := make([]string, n) + + for i := 0; i < n; i++ { + key, err := r.ReadString() + if err != nil { + return nil, 0, err + } + keys[i] = key + } + + return keys, cursor, err +} +*/ +/* +func (r *Reader) ReadInt() (int64, error) { + b, err := r.readTmpBytesReply() + if err != nil { + return 0, err + } + return util.ParseInt(b, 10, 64) +} + +func (r *Reader) ReadUint() (uint64, error) { + b, err := r.readTmpBytesReply() + if err != nil { + return 0, err + } + return util.ParseUint(b, 10, 64) +} + +func (r *Reader) ReadFloatReply() (float64, error) { + b, err := r.readTmpBytesReply() + if err != nil { + return 0, err + } + return util.ParseFloat(b, 64) +} + +func (r *Reader) readTmpBytesReply() ([]byte, error) { + line, err := r.ReadLine() + if err != nil { + return nil, err + } + switch line[0] { + case ErrorReply: + return nil, ParseErrorReply(line) + case StringReply: + return r._readTmpBytesReply(line) + case StatusReply: + return line[1:], nil + default: + return nil, fmt.Errorf("dpvs: can't parse string reply: %.100q", line) + } +} + +func (r *Reader) _readTmpBytesReply(line []byte) ([]byte, error) { + if isNilReply(line) { + return nil, Nil + } + + replyLen, err := util.Atoi(line[1:]) + if err != nil { + return nil, err + } + + buf := r.buf(replyLen + 2) + _, err = io.ReadFull(r.rd, buf) + if err != nil { + return nil, err + } + + return buf[:replyLen], nil +} +*/ +/* +func isNilReply(b []byte) bool { + return len(b) == 3 && + (b[0] == StringReply || b[0] == ArrayReply) && + b[1] == '-' && b[2] == '1' +} + +func ParseErrorReply(line []byte) error { + return DpvsError(string(line[1:])) +} + +func parseArrayLen(line []byte) (int64, error) { + if isNilReply(line) { + return 0, Nil + } + return util.ParseInt(line[1:], 10, 64) +} +*/ diff --git a/tools/dpvs-agent/pkg/ipc/proto/writer.go b/tools/dpvs-agent/pkg/ipc/proto/writer.go new file mode 100644 index 000000000..a4aced90d --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/proto/writer.go @@ -0,0 +1,167 @@ +package proto + +import ( + "encoding" + "fmt" + "io" + "strconv" + "time" + "unsafe" +) + +// BytesToString converts byte slice to string. +func BytesToString(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} + +// StringToBytes converts string to byte slice. +func StringToBytes(s string) []byte { + return *(*[]byte)(unsafe.Pointer( + &struct { + string + Cap int + }{s, len(s)}, + )) +} + +type writer interface { + io.Writer + io.ByteWriter + // io.StringWriter + WriteString(s string) (n int, err error) +} + +type Writer struct { + writer + + lenBuf []byte + numBuf []byte +} + +func NewWriter(wr writer) *Writer { + return &Writer{ + writer: wr, + + lenBuf: make([]byte, 64), + numBuf: make([]byte, 64), + } +} + +func (w *Writer) WriteArgs(args []interface{}) error { + if err := w.WriteByte(ArrayReply); err != nil { + return err + } + + if err := w.writeLen(len(args)); err != nil { + return err + } + + for _, arg := range args { + if err := w.WriteArg(arg); err != nil { + return err + } + } + + return nil +} + +func (w *Writer) writeLen(n int) error { + w.lenBuf = strconv.AppendUint(w.lenBuf[:0], uint64(n), 10) + w.lenBuf = append(w.lenBuf, '\r', '\n') + _, err := w.Write(w.lenBuf) + return err +} + +func (w *Writer) WriteArg(v interface{}) error { + switch v := v.(type) { + case nil: + return w.string("") + case string: + return w.string(v) + case []byte: + return w.bytes(v) + case int: + return w.int(int64(v)) + case int8: + return w.int(int64(v)) + case int16: + return w.int(int64(v)) + case int32: + return w.int(int64(v)) + case int64: + return w.int(v) + case uint: + return w.uint(uint64(v)) + case uint8: + return w.uint(uint64(v)) + case uint16: + return w.uint(uint64(v)) + case uint32: + return w.uint(uint64(v)) + case uint64: + return w.uint(v) + case float32: + return w.float(float64(v)) + case float64: + return w.float(v) + case bool: + if v { + return w.int(1) + } + return w.int(0) + case time.Time: + w.numBuf = v.AppendFormat(w.numBuf[:0], time.RFC3339Nano) + return w.bytes(w.numBuf) + case encoding.BinaryMarshaler: + b, err := v.MarshalBinary() + if err != nil { + return err + } + return w.bytes(b) + default: + return fmt.Errorf( + "dpvs-agent: can't marshal %T (implement encoding.BinaryMarshaler)", v) + } +} + +func (w *Writer) bytes(b []byte) error { + if err := w.WriteByte(StringReply); err != nil { + return err + } + + if err := w.writeLen(len(b)); err != nil { + return err + } + + if _, err := w.Write(b); err != nil { + return err + } + + return w.crlf() +} + +func (w *Writer) string(s string) error { + return w.bytes(StringToBytes(s)) +} + +func (w *Writer) uint(n uint64) error { + w.numBuf = strconv.AppendUint(w.numBuf[:0], n, 10) + return w.bytes(w.numBuf) +} + +func (w *Writer) int(n int64) error { + w.numBuf = strconv.AppendInt(w.numBuf[:0], n, 10) + return w.bytes(w.numBuf) +} + +func (w *Writer) float(f float64) error { + w.numBuf = strconv.AppendFloat(w.numBuf[:0], f, 'f', -1, 64) + return w.bytes(w.numBuf) +} + +func (w *Writer) crlf() error { + if err := w.WriteByte('\r'); err != nil { + return err + } + return w.WriteByte('\n') +} diff --git a/tools/dpvs-agent/pkg/ipc/types/certificate.go b/tools/dpvs-agent/pkg/ipc/types/certificate.go new file mode 100644 index 000000000..b0b7b74a4 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/certificate.go @@ -0,0 +1,369 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type CertificateAuthoritySpec struct { + src [0x10]byte + dst [0x10]byte + af uint32 + fwmark uint32 + port uint16 + proto uint8 + padding uint8 +} + +type CertificateAuthorityFront struct { + count uint32 +} + +func NewCertificateAuthoritySpec() *CertificateAuthoritySpec { + return &CertificateAuthoritySpec{} +} + +func NewCertificateAuthorityFront() *CertificateAuthorityFront { + return &CertificateAuthorityFront{} +} + +func (o *CertificateAuthoritySpec) Copy(src *CertificateAuthoritySpec) bool { + o.af = src.af + o.fwmark = src.fwmark + o.port = src.port + o.proto = src.proto + copy(o.src[:], src.src[:]) + copy(o.dst[:], src.dst[:]) + return true +} + +func (o *CertificateAuthoritySpec) ParseVipPortProto(vipport string) error { + items := strings.Split(vipport, "-") + if len(items) != 3 { + return errors.New("invalid vip-port-proto string") + } + + proto := items[2] + + switch strings.ToLower(proto) { + case "udp": + o.proto = unix.IPPROTO_UDP + case "tcp": + fallthrough + default: + o.proto = unix.IPPROTO_TCP + } + + // port := items[1] + port, err := strconv.Atoi(items[1]) + if err != nil { + return err + } + o.SetPort(uint16(port)) + + vip := items[0] + if net.ParseIP(vip) == nil { + return errors.New(fmt.Sprintf("invalid ip addr: %s\n", vip)) + } + + o.SetDst(vip) + + return nil +} + +func (o *CertificateAuthorityFront) Copy(src *CertificateAuthorityFront) bool { + o.count = src.count + return true +} + +func (o *CertificateAuthoritySpec) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *CertificateAuthorityFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *CertificateAuthoritySpec) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *CertificateAuthoritySpec = *(**CertificateAuthoritySpec)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *CertificateAuthorityFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *CertificateAuthorityFront = *(**CertificateAuthorityFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *CertificateAuthoritySpec) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *CertificateAuthorityFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *CertificateAuthorityFront) SetCount(count uint32) { + o.count = count +} + +func (o *CertificateAuthorityFront) GetCount() uint32 { + return o.count +} + +func (o *CertificateAuthoritySpec) SetAf(af uint32) { + o.af = af +} + +func (o *CertificateAuthoritySpec) SetSrc(addr string) { + if strings.Contains(addr, ":") { + o.SetAf(unix.AF_INET6) + copy(o.src[:], net.ParseIP(addr)) + return + } + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.src[:], buf.Bytes()[12:]) +} + +func (o *CertificateAuthoritySpec) SetDst(addr string) { + if strings.Contains(addr, ":") { + o.SetAf(unix.AF_INET6) + copy(o.dst[:], net.ParseIP(addr)) + return + } + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.dst[:], buf.Bytes()[12:]) +} + +func (o *CertificateAuthoritySpec) SetFwmark(fwmark uint32) { + o.fwmark = fwmark +} + +func (o *CertificateAuthoritySpec) SetPort(port uint16) { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(port)) + o.port = binary.BigEndian.Uint16(buf.Bytes()) +} + +func (o *CertificateAuthoritySpec) SetProto(proto string) { + switch strings.ToLower(proto) { + case "udp": + o.proto = unix.IPPROTO_UDP + default: + o.proto = unix.IPPROTO_TCP + } +} + +func (o *CertificateAuthorityFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*CertificateAuthorityFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to CertificateAuthorityFront") + } + + fronts := make([]*CertificateAuthorityFront, cnt) + + for i := 0; i < int(cnt); i++ { + fronts[i] = NewCertificateAuthorityFront() + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *CertificateAuthoritySpec) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*CertificateAuthoritySpec, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to CertificateAuthoritySpec") + } + + calst := make([]*CertificateAuthoritySpec, cnt) + for i := 0; i < int(cnt); i++ { + calst[i] = NewCertificateAuthoritySpec() + + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + calst[i].Dump(buf) + } + + return calst, nil +} + +func (o *CertificateAuthoritySpec) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (o *CertificateAuthoritySpec) Add(cp *pool.ConnPool, blk bool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var ADD uint32 + SOCKOPT_STRING := "SOCKOPT_SET_BLKLST_ADD" + ADD = SOCKOPT_SET_BLKLST_ADD + if !blk { + SOCKOPT_STRING = "SOCKOPT_SET_WHTLST_ADD" + ADD = SOCKOPT_SET_WHTLST_ADD + } + + msg := NewSockMsg(SOCKOPT_VERSION, ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write proto header Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + err = o.write(conn, logger) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write specific auth user Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s reply msg Read Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + logger.Info(fmt.Sprintf("Sockopt %s Done:%s", SOCKOPT_STRING, errCode.String())) + return errCode +} + +func (o *CertificateAuthoritySpec) Del(cp *pool.ConnPool, blk bool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var DEL uint32 + SOCKOPT_STRING := "SOCKOPT_SET_BLKLST_DEL" + DEL = SOCKOPT_SET_BLKLST_DEL + if !blk { + SOCKOPT_STRING = "SOCKOPT_SET_WHTLST_DEL" + DEL = SOCKOPT_SET_WHTLST_DEL + } + + msg := NewSockMsg(SOCKOPT_VERSION, DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write proto header Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + err = o.write(conn, logger) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write specific auth user Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s reply msg Read Error: %s", SOCKOPT_STRING, err.Error())) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + logger.Info(fmt.Sprintf("Sockopt %s Done:%s", SOCKOPT_STRING, errCode.String())) + return errCode +} + +func (o *CertificateAuthoritySpec) Get(cp *pool.ConnPool, blk bool, logger hclog.Logger) ([]*CertificateAuthoritySpec, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + var GET uint32 + SOCKOPT_STRING := "SOCKOPT_GET_BLKLST_GETALL" + GET = SOCKOPT_GET_BLKLST_GETALL + if !blk { + GET = SOCKOPT_GET_WHTLST_GETALL + SOCKOPT_STRING = "SOCKOPT_GET_WHTLST_GETALL" + } + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write proto header Error: %s", SOCKOPT_STRING, err.Error())) + return nil, err + } + + if err := o.write(conn, logger); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write specific auth user Error: %s", SOCKOPT_STRING, err.Error())) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s reply msg Read Error: %s", SOCKOPT_STRING, err.Error())) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + err = fmt.Errorf("Sockopt %s reply ErrorCode: %s", SOCKOPT_STRING, reply.GetErrStr()) + logger.Error(err.Error()) + return nil, err + } + + front := NewCertificateAuthorityFront() + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error(fmt.Sprintf("Sockopt %s read auth user table header Error: %s", SOCKOPT_STRING, err.Error())) + return nil, err + } + + return o.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} diff --git a/tools/dpvs-agent/pkg/ipc/types/const.go b/tools/dpvs-agent/pkg/ipc/types/const.go new file mode 100644 index 000000000..9cbc3d49a --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/const.go @@ -0,0 +1,334 @@ +package types + +import ( + "strings" +) + +type lcoreid_t uint8 +type SockoptType uint32 +type DpvsErrType int32 +type DpvsFwdMode uint32 + +const ( + DPVS_FWD_MASQ DpvsFwdMode = iota + DPVS_FWD_LOCALNODE + DPVS_FWD_MODE_TUNNEL + DPVS_FWD_MODE_DR + DPVS_FWD_MODE_BYPASS + DPVS_FWD_MODE_FNAT + DPVS_FWD_MODE_SNAT +) +const DPVS_FWD_MODE_NAT DpvsFwdMode = DPVS_FWD_MASQ + +const ( + DPVS_SVC_F_PERSISTENT = 0x1 << iota + DPVS_SVC_F_HASHED + DPVS_SVC_F_ONEPACKET + DPVS_SVC_F_SCHED1 + DPVS_SVC_F_SCHED2 + DPVS_SVC_F_SCHED3 +) + +const ( + DPVS_SVC_F_SIP_HASH uint32 = 0x100 << iota + DPVS_SVC_F_QID_HASH + DPVS_SVC_F_MATCH +) + +const ( + DPVS_DEST_HC_PASSIVE = 0x1 << iota + DPVS_DEST_HC_TCP + DPVS_DEST_HC_UDP + DPVS_DEST_HC_PING +) + +const ( + DPVS_DEST_F_AVAILABLE = 0x1 << iota + DPVS_DEST_F_OVERLOAD + DPVS_DEST_F_INHIBITED +) + +const ( + DPVS_CONN_F_MASQ = iota + DPVS_CONN_F_LOCALNODE + DPVS_CONN_F_TUNNEL + DPVS_CONN_F_DROUTE + DPVS_CONN_F_BYPASS + DPVS_CONN_F_FULLNAT + DPVS_CONN_F_SNAT + DPVS_CONN_F_FWD_MASK +) + +const ( + DPVS_CONN_F_SYNPROXY = 0x10 << iota + DPVS_CONN_F_EXPIRE_QUIESCENT + _ + _ + DPVS_CONN_F_HASHED + DPVS_CONN_F_INACTIVE + DPVS_CONN_F_TEMPLATE + DPVS_CONN_F_ONE_PACKET + DPVS_CONN_F_IN_TIMER + DPVS_CONN_F_REDIRECT_HASHED + DPVS_CONN_F_NOFASTXMIT +) + +func (e *DpvsFwdMode) String() string { + switch *e { + case DPVS_FWD_MASQ: // DPVS_FWD_MASQ == DPVS_FWD_MODE_NAT + return "MASQ" + case DPVS_FWD_LOCALNODE: + return "LOCALNODE" + case DPVS_FWD_MODE_DR: + return "DR" + case DPVS_FWD_MODE_TUNNEL: + return "TUNNLE" + case DPVS_FWD_MODE_BYPASS: + return "BYPASS" + case DPVS_FWD_MODE_SNAT: + return "SNAT" + case DPVS_FWD_MODE_FNAT: + return "FNAT" + } + return "UNKNOW" +} + +func (e *DpvsFwdMode) FromString(name string) { + switch strings.ToUpper(name) { + case "MASQ": + *e = DPVS_FWD_MASQ + case "LOCALNODE": + *e = DPVS_FWD_LOCALNODE + case "DR": + *e = DPVS_FWD_MODE_DR + case "TUNNLE": + *e = DPVS_FWD_MODE_TUNNEL + case "BYPASS": + *e = DPVS_FWD_MODE_BYPASS + case "SNAT": + *e = DPVS_FWD_MODE_SNAT + case "NAT": + *e = DPVS_FWD_MODE_NAT + case "FNAT": + *e = DPVS_FWD_MODE_FNAT + default: + *e = DPVS_FWD_MODE_FNAT + } +} + +const ( + EDPVS_INPROGRESS DpvsErrType = 2 - iota + EDPVS_KNICONTINUE + EDPVS_OK + EDPVS_INVAL + EDPVS_NOMEM + EDPVS_EXIST + EDPVS_NOTEXIST + EDPVS_INVPKT + EDPVS_DROP + EDPVS_NOPROT + EDPVS_NOROUTE + EDPVS_DEFRAG + EDPVS_FRAG + EDPVS_DPDKAPIFAIL + EDPVS_IDLE + EDPVS_BUSY + EDPVS_NOTSUPP + EDPVS_RESOURCE + EDPVS_OVERLOAD + EDPVS_NOSERV + EDPVS_DISABLED + EDPVS_NOROOM + EDPVS_NONEALCORE + EDPVS_CALLBACKFAIL + EDPVS_IO + EDPVS_MSG_FAIL + EDPVS_MSG_DROP + EDPVS_PKTSTOLEN + EDPVS_SYSCALL + EDPVS_NODEV +) + +var dpvsErrNames = [...]string{"EDPVS_INPROGRESS", "EDPVS_KNICONTINUE", "EDPVS_OK", "EDPVS_INVAL", "EDPVS_NOMEM", "EDPVS_EXIST", "EDPVS_NOTEXIST", "EDPVS_INVPKT", "EDPVS_DROP", "EDPVS_NOPROT", "EDPVS_NOROUTE", "EDPVS_DEFRAG", "EDPVS_FRAG", "EDPVS_DPDKAPIFAIL", "EDPVS_IDLE", "EDPVS_BUSY", "EDPVS_NOTSUPP", "EDPVS_RESOURCE", "EDPVS_OVERLOAD", "EDPVS_NOSERV", "EDPVS_DISABLED", "EDPVS_NOROOM", "EDPVS_NONEALCORE", "EDPVS_CALLBACKFAIL", "EDPVS_IO", "EDPVS_MSG_FAIL", "EDPVS_MSG_DROP", "EDPVS_PKTSTOLEN", "EDPVS_SYSCALL", "EDPVS_NODEV"} + +func (e *DpvsErrType) String() string { + return dpvsErrNames[EDPVS_INPROGRESS-*e] +} + +const ( + SOCKOPT_VERSION = 0x10000 +) + +const ( + SOCKOPT_GET SockoptType = iota + SOCKOPT_SET + SOCKOPT_TYPE_MAX +) + +const ( + SOCKOPT_SET_LADDR_ADD = iota + SOCKOPT_SET_LADDR_DEL + SOCKOPT_SET_LADDR_FLUSH + SOCKOPT_GET_LADDR_GETALL + SOCKOPT_GET_LADDR_MAX + + DPVSAGENT_VS_GET_LADDR + DPVSAGENT_VS_ADD_LADDR + DPVSAGENT_VS_DEL_LADDR + + DPVS_SO_SET_FLUSH + DPVS_SO_SET_ZERO + DPVS_SO_SET_ADD + DPVS_SO_SET_EDIT + DPVS_SO_SET_DEL + DPVS_SO_SET_ADDDEST + DPVS_SO_SET_EDITDEST + DPVS_SO_SET_DELDEST + DPVS_SO_SET_GRATARP + DPVS_SO_GET_VERSION + DPVS_SO_GET_INFO + DPVS_SO_GET_SERVICES + DPVS_SO_GET_SERVICE + DPVS_SO_GET_DESTS + DPVSAGENT_SO_GET_SERVICES + SOCKOPT_SVC_MAX + + DPVSAGENT_VS_GET_DESTS + DPVSAGENT_VS_ADD_DESTS + DPVSAGENT_VS_EDIT_DESTS + DPVSAGENT_VS_DEL_DESTS + + SOCKOPT_SET_ROUTE_ADD + SOCKOPT_SET_ROUTE_DEL + SOCKOPT_SET_ROUTE_SET + SOCKOPT_SET_ROUTE_FLUSH + SOCKOPT_GET_ROUTE_SHOW + + SOCKOPT_SET_ROUTE6_ADD_DEL + SOCKOPT_SET_ROUTE6_FLUSH + SOCKOPT_GET_ROUTE6_SHOW + + DPVSAGENT_ROUTE_GET + DPVSAGENT_ROUTE_ADD + DPVSAGENT_ROUTE_DEL + DPVSAGENT_ROUTE6_GET + DPVSAGENT_ROUTE6_ADD + DPVSAGENT_ROUTE6_DEL + + DPVSAGENT_IFADDR_GET_BASE + DPVSAGENT_IFADDR_GET_STATS + DPVSAGENT_IFADDR_GET_VERBOSE + DPVSAGENT_IFADDR_ADD + DPVSAGENT_IFADDR_DEL + + SOCKOPT_SET_IFADDR_ADD + SOCKOPT_SET_IFADDR_DEL + SOCKOPT_SET_IFADDR_SET + SOCKOPT_SET_IFADDR_FLUSH + SOCKOPT_GET_IFADDR_SHOW + + SOCKOPT_NETIF_SET_LCORE + SOCKOPT_NETIF_SET_PORT + SOCKOPT_NETIF_SET_BOND + SOCKOPT_NETIF_SET_MAX + SOCKOPT_NETIF_GET_LCORE_MASK + SOCKOPT_NETIF_GET_LCORE_BASIC + SOCKOPT_NETIF_GET_LCORE_STATS + SOCKOPT_NETIF_GET_PORT_LIST + SOCKOPT_NETIF_GET_PORT_BASIC + SOCKOPT_NETIF_GET_PORT_STATS + SOCKOPT_NETIF_GET_PORT_XSTATS + SOCKOPT_NETIF_GET_PORT_EXT_INFO + SOCKOPT_NETIF_GET_BOND_STATUS + SOCKOPT_NETIF_GET_MAX + + SOCKOPT_SET_NEIGH_ADD + SOCKOPT_SET_NEIGH_DEL + SOCKOPT_GET_NEIGH_SHOW + + SOCKOPT_SET_BLKLST_ADD + SOCKOPT_SET_BLKLST_DEL + SOCKOPT_SET_BLKLST_FLUSH + SOCKOPT_GET_BLKLST_GETALL + + SOCKOPT_SET_WHTLST_ADD + SOCKOPT_SET_WHTLST_DEL + SOCKOPT_SET_WHTLST_FLUSH + SOCKOPT_GET_WHTLST_GETALL + + SOCKOPT_SET_VLAN_ADD + SOCKOPT_SET_VLAN_DEL + SOCKOPT_GET_VLAN_SHOW + + SOCKOPT_TC_ADD + SOCKOPT_TC_DEL + SOCKOPT_TC_CHANGE + SOCKOPT_TC_REPLACE + SOCKOPT_TC_SHOW + + SOCKOPT_SET_CONN + SOCKOPT_GET_CONN_ALL + SOCKOPT_GET_CONN_SPECIFIED + + SOCKOPT_IP6_SET + SOCKOPT_IP6_STATS + + SOCKOPT_TUNNEL_ADD + SOCKOPT_TUNNEL_DEL + SOCKOPT_TUNNEL_CHANGE + SOCKOPT_TUNNEL_REPLACE + SOCKOPT_TUNNEL_SHOW + + SOCKOPT_SET_KNI_ADD + SOCKOPT_SET_KNI_DEL + SOCKOPT_SET_KNI_FLUSH + SOCKOPT_GET_KNI_LIST + + SOCKOPT_SET_IPSET + SOCKOPT_GET_IPSET_TEST + SOCKOPT_GET_IPSET_LIST + + SOCKOPT_SET_IFTRAF_ADD + SOCKOPT_SET_IFTRAF_DEL + SOCKOPT_GET_IFTRAF_SHOW +) + +const ( + NETIF_NIC_PROMISC_ON = 1 << iota + NETIF_NIC_PROMISC_OFF + NETIF_NIC_LINK_UP + NETIF_NIC_LINK_DOWN + NETIF_NIC_FWD2KNI_ON + NETIF_NIC_FWD2KNI_OFF + NETIF_NIC_TC_EGRESS_ON + NETIF_NIC_TC_EGRESS_OFF + NETIF_NIC_TC_INGRESS_ON + NETIF_NIC_TC_INGRESS_OFF +) + +const ( + RTF_UP = 1 << iota + RTF_GATEWAY + RTF_HOST + RTF_REINSTATE + RTF_DYNAMIC + RTF_MODIFIED + RTF_MTU + RTF_WINDOW + RTF_IRTT + RTF_REJECT + + RTF_FORWARD + RTF_LOCALIN + RTF_DEFAULT + RTF_KNI + RTF_OUTWALL +) + +const ( + IFA_SCOPE_GLOBAL uint8 = iota + IFA_SCOPE_SITE + IFA_SCOPE_LINK + IFA_SCOPE_HOST + IFA_SCOPE_NONE = 255 +) diff --git a/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go b/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go new file mode 100644 index 000000000..97c180ce7 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go @@ -0,0 +1,56 @@ +package types + +type dpvsMatch struct { + af uint32 + srange ipRange + drange ipRange + iIfName [0x10]byte + oIfName [0x10]byte +} + +func (m *dpvsMatch) Copy(src *dpvsMatch) bool { + if src == nil { + return false + } + + m.af = src.af + + copy(m.iIfName[:], src.iIfName[:]) + copy(m.oIfName[:], src.oIfName[:]) + + if !m.srange.Copy(&src.srange) { + return false + } + if !m.drange.Copy(&src.drange) { + return false + } + return true +} + +func (m *dpvsMatch) SetAf(af uint32) { + m.af = af +} + +func (m *dpvsMatch) SetSrange(r *ipRange) { + m.srange.Copy(r) +} + +func (m *dpvsMatch) SetDrange(r *ipRange) { + m.drange.Copy(r) +} + +func (m *dpvsMatch) SetIifName(name []byte) { + copy(m.iIfName[:], name) +} + +func (m *dpvsMatch) SetOifName(name []byte) { + copy(m.oIfName[:], name) +} + +func (m *dpvsMatch) GetIifName() string { + return TrimRightZeros(string(m.iIfName[:])) +} + +func (m *dpvsMatch) GetOifName() string { + return TrimRightZeros(string(m.oIfName[:])) +} diff --git a/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go b/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go new file mode 100644 index 000000000..dfd02c1e0 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go @@ -0,0 +1,114 @@ +package types + +type dpvsStats struct { + conns uint64 + inPkts uint64 + inBytes uint64 + outPkts uint64 + outBytes uint64 + + cps uint32 + inPps uint32 + inBps uint32 + outPps uint32 + outBps uint32 + nop uint32 +} + +func (s *dpvsStats) Copy(src *dpvsStats) bool { + if src == nil { + return false + } + s.conns = src.conns + s.inPkts = src.inPkts + s.inBytes = src.inBytes + s.outPkts = src.outPkts + s.outBytes = src.outBytes + + s.cps = src.cps + s.inPps = src.inPps + s.inBps = src.inBps + s.outPps = src.outPps + s.outBps = src.outBps + return true +} + +func (s *dpvsStats) SetConns(c uint64) { + s.conns = c +} + +func (s *dpvsStats) SetInPkts(p uint64) { + s.inPkts = p +} + +func (s *dpvsStats) SetInBytes(b uint64) { + s.inBytes = b +} + +func (s *dpvsStats) SetOutPkts(p uint64) { + s.outPkts = p +} + +func (s *dpvsStats) SetOutBytes(b uint64) { + s.outBytes = b +} + +func (s *dpvsStats) SetCps(c uint32) { + s.cps = c +} + +func (s *dpvsStats) SetInPps(p uint32) { + s.inPps = p +} + +func (s *dpvsStats) SetInBps(b uint32) { + s.inBps = b +} + +func (s *dpvsStats) SetOutPps(p uint32) { + s.outPps = p +} + +func (s *dpvsStats) SetOutBps(b uint32) { + s.outBps = b +} + +func (s *dpvsStats) GetConns() uint64 { + return s.conns +} + +func (s *dpvsStats) GetInPkts() uint64 { + return s.inPkts +} + +func (s *dpvsStats) GetInBytes() uint64 { + return s.inBytes +} + +func (s *dpvsStats) GetOutPkts() uint64 { + return s.outPkts +} + +func (s *dpvsStats) GetOutBytes() uint64 { + return s.outBytes +} + +func (s *dpvsStats) GetCps() uint32 { + return s.cps +} + +func (s *dpvsStats) GetInPps() uint32 { + return s.inPps +} + +func (s *dpvsStats) GetInBps() uint32 { + return s.inBps +} + +func (s *dpvsStats) GetOutPps() uint32 { + return s.outPps +} + +func (s *dpvsStats) GetOutBps() uint32 { + return s.outBps +} diff --git a/tools/dpvs-agent/pkg/ipc/types/getmodel.go b/tools/dpvs-agent/pkg/ipc/types/getmodel.go new file mode 100644 index 000000000..6196594b2 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/getmodel.go @@ -0,0 +1,169 @@ +package types + +import ( + "github.com/dpvs-agent/models" +) + +func (vs *VirtualServerSpec) GetModel() *models.VirtualServerSpecExpand { + modelVs := &models.VirtualServerSpecExpand{ + Addr: vs.GetAddr(), + Af: vs.GetAf(), + Bps: vs.GetBps(), + ConnTimeout: vs.GetConnTimeout(), + LimitProportion: vs.GetLimitProportion(), + Netmask: vs.GetNetMask(), + Port: vs.GetPort(), + Proto: vs.GetProto(), + Fwmark: vs.GetFwmark(), + SyncProxy: "false", + ExpireQuiescent: "false", + SchedName: vs.GetSchedName(), + Timeout: vs.GetTimeout(), + Match: vs.match.GetModel(), + Stats: vs.stats.GetModel(), + DestCheck: vs.GetDestCheck(), + } + + flags := "" + if (vs.GetFlags() & DPVS_CONN_F_SYNPROXY) != 0 { + modelVs.SyncProxy = "true" + flags += "SynProxy|" + } + + if (vs.GetFlags() & DPVS_CONN_F_EXPIRE_QUIESCENT) != 0 { + modelVs.ExpireQuiescent = "true" + flags += "ExpireQuiescent|" + } + + if (vs.GetFlags() & DPVS_SVC_F_QID_HASH) != 0 { + flags += "ConHashByQuicID|" + } + if (vs.GetFlags() & DPVS_SVC_F_SIP_HASH) != 0 { + flags += "ConHashBySrcIP|" + } + + modelVs.Flags = flags + + return modelVs +} + +func (ir *ipRange) GetModel() *models.AddrRange { + return &models.AddrRange{ + Start: ir.GetMinAddr(), + End: ir.GetMaxAddr(), + } +} + +func (dm *dpvsMatch) GetModel() *models.MatchSpec { + return &models.MatchSpec{ + Dest: dm.drange.GetModel(), + Src: dm.srange.GetModel(), + InIfName: dm.GetIifName(), + OutIfName: dm.GetOifName(), + } +} + +func (rs *RealServerSpec) GetModel() *models.RealServerSpecExpand { + overloaded := rs.GetOverloaded() + inhibited := rs.GetInhibited() + return &models.RealServerSpecExpand{ + Spec: &models.RealServerSpecTiny{ + IP: rs.GetAddr(), + Mode: rs.GetFwdModeString(), + Port: rs.GetPort(), + Weight: (uint16)(rs.GetWeight()), + Overloaded: &overloaded, + Inhibited: &inhibited, + }, + Stats: rs.stats.GetModel(), + } +} + +type ServerStats models.ServerStats + +func (dst *ServerStats) Increase(src *ServerStats) { + dst.Conns += src.Conns + dst.InPkts += src.InPkts + dst.InBytes += src.InBytes + dst.OutPkts += src.OutPkts + dst.OutBytes += src.OutBytes + + dst.Cps += src.Cps + dst.InBps += src.InBps + dst.InPps += src.InPps + dst.OutBps += src.OutBps + dst.OutPps += src.OutPps +} + +func (stats *dpvsStats) GetModel() *models.ServerStats { + return &models.ServerStats{ + Conns: stats.GetConns(), + InPkts: stats.GetInPkts(), + InBytes: stats.GetInBytes(), + OutPkts: stats.GetOutPkts(), + OutBytes: stats.GetOutBytes(), + + Cps: stats.GetCps(), + InBps: stats.GetInBps(), + InPps: stats.GetInPps(), + OutBps: stats.GetOutBps(), + OutPps: stats.GetOutPps(), + } +} + +func (nic *NetifNicQueue) GetModel() []models.NicDeviceQueueData { + nicDataQueue := make([]models.NicDeviceQueueData, len(nic.queue)) + for i, data := range nic.queue { + nicDataQueue[i] = (models.NicDeviceQueueData)(data) + } + return nicDataQueue +} + +func (stats *NetifNicStats) GetModel() *models.NicDeviceStats { + nicStats := &models.NicDeviceStats{ + BufAvail: stats.GetMBufAvail(), + BufInuse: stats.GetMBufInuse(), + ID: stats.GetID(), + InBytes: stats.GetInBytes(), + InErrors: stats.GetInErrors(), + InMissed: stats.GetInMissed(), + InPkts: stats.GetInPkts(), + OutBytes: stats.GetOutBytes(), + OutPkts: stats.GetOutPkts(), + OutErrors: stats.GetOutErrors(), + RxNoMbuf: stats.GetRxNoMbuf(), + InBytesQ: stats.inBytesQ.GetModel(), + InPktsQ: stats.inPktsQ.GetModel(), + OutBytesQ: stats.outBytesQ.GetModel(), + OutPktsQ: stats.outPktsQ.GetModel(), + ErrorBytesQ: stats.errorQ.GetModel(), + } + return nicStats +} + +func (detail *NetifNicDetail) GetModel() *models.NicDeviceDetail { + return &models.NicDeviceDetail{ + Flags: detail.GetFlags(), + ID: detail.GetID(), + MTU: detail.GetMTU(), + Addr: detail.GetAddr(), + Autoneg: detail.GetLinkAutoNeg(), + Duplex: detail.GetLinkDuplex(), + NRxQ: detail.GetRxQueueCount(), + NTxQ: detail.GetTxQueueCount(), + Name: detail.GetName(), + SocketID: detail.GetSocketID(), + Speed: detail.GetSpeed(), + Status: detail.GetStatus(), + } +} + +func (laddr *LocalAddrDetail) GetModel() *models.LocalAddressSpecExpand { + return &models.LocalAddressSpecExpand{ + Af: laddr.GetAf(), + Addr: laddr.GetAddr(), + Conns: laddr.GetConns(), + Device: laddr.GetIfName(), + PortConflict: laddr.GetPortConflict(), + } +} diff --git a/tools/dpvs-agent/pkg/ipc/types/inetaddr.go b/tools/dpvs-agent/pkg/ipc/types/inetaddr.go new file mode 100644 index 000000000..661c31f09 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/inetaddr.go @@ -0,0 +1,571 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type InetAddrFront struct { + count uint32 +} + +func NewInetAddrFront() *InetAddrFront { + return &InetAddrFront{} +} + +func (o *InetAddrFront) GetCount() uint32 { + return o.count +} + +func (o *InetAddrFront) SetCount(c uint32) { + o.count = c +} + +func (o *InetAddrFront) Copy(src *InetAddrFront) bool { + o.count = src.count + return true +} + +func (o *InetAddrFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *InetAddrFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *InetAddrFront = *(**InetAddrFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *InetAddrFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *InetAddrFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*InetAddrFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to InetAddrFront") + } + + fronts := make([]*InetAddrFront, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i] = NewInetAddrFront() + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *InetAddrFront) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type InetAddrStats struct { + addr [0x10]byte + used uint32 + free uint32 + miss uint32 +} + +func NewInetAddrStats() *InetAddrStats { + return &InetAddrStats{} +} + +func (o *InetAddrStats) GetUsed() uint32 { + return o.used +} + +func (o *InetAddrStats) GetFree() uint32 { + return o.free +} + +func (o *InetAddrStats) GetMiss() uint32 { + return o.miss +} + +func (o *InetAddrStats) Copy(src *InetAddrStats) bool { + o.used = src.used + o.free = src.free + o.miss = src.miss + copy(o.addr[:], src.addr[:]) + return true +} + +func (o *InetAddrStats) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *InetAddrStats) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *InetAddrStats = *(**InetAddrStats)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *InetAddrStats) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *InetAddrStats) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*InetAddrStats, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to InetAddrStats") + } + + stats := make([]*InetAddrStats, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + stats[i] = NewInetAddrStats() + stats[i].Dump(buf) + } + + return stats, nil +} + +func (o *InetAddrStats) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type InetAddrDetail struct { + af uint32 + validLft uint32 + preferedLft uint32 + flags uint32 + ifName [0x10]byte + bcast [0x10]byte + addr [0x10]byte + plen uint8 + scope uint8 + cid uint8 + nop uint8 +} + +func NewInetAddrDetail() *InetAddrDetail { + return &InetAddrDetail{} +} + +func (o *InetAddrDetail) Copy(src *InetAddrDetail) bool { + o.af = src.af + o.validLft = src.validLft + o.preferedLft = src.preferedLft + o.flags = src.flags + o.plen = src.plen + o.scope = src.scope + o.cid = src.cid + + copy(o.ifName[:], src.ifName[:]) + copy(o.addr[:], src.addr[:]) + copy(o.bcast[:], src.bcast[:]) + + return true +} + +func (o *InetAddrDetail) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *InetAddrDetail) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *InetAddrDetail = *(**InetAddrDetail)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *InetAddrDetail) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *InetAddrDetail) GetAddr() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.addr[0], o.addr[1], o.addr[2], o.addr[3]) + return addr.String() + } + + addr = net.IP{o.addr[0x0], o.addr[0x1], o.addr[0x2], o.addr[0x3], + o.addr[0x4], o.addr[0x5], o.addr[0x6], o.addr[0x7], + o.addr[0x8], o.addr[0x9], o.addr[0xa], o.addr[0xb], + o.addr[0xc], o.addr[0xd], o.addr[0xe], o.addr[0xf], + } + return addr.String() +} + +func (o *InetAddrDetail) GetIfName() string { + return TrimRightZeros(string(o.ifName[:])) +} + +func (o *InetAddrDetail) SetAf(af uint32) { + o.af = af +} + +func (o *InetAddrDetail) SetValidLft(lft string) error { + if strings.EqualFold(strings.ToLower(lft), "forever") { + o.validLft = 0 + } else { + i, err := strconv.Atoi(lft) + if err != nil { + return err + } + o.validLft = uint32(i) + } + return nil +} + +func (o *InetAddrDetail) SetPreferedLft(lft string) error { + if strings.EqualFold(strings.ToLower(lft), "forever") { + o.preferedLft = 0 + } else { + i, err := strconv.Atoi(lft) + if err != nil { + return err + } + o.preferedLft = uint32(i) + } + return nil +} + +func (o *InetAddrDetail) SetPlen(len uint8) { + o.plen = len +} + +const ( + IFA_F_SAPOOL uint32 = 0x10000 + IFA_F_OPS_VERBOSE uint32 = 0x0001 + IFA_F_OPS_STATS uint32 = 0x0002 +) + +func (o *InetAddrDetail) SetFlags(flags string) { + switch strings.ToLower(flags) { + case "verbose": + o.flags |= IFA_F_OPS_VERBOSE + case "stats": + o.flags |= IFA_F_OPS_STATS + case "sapool": + o.flags |= IFA_F_SAPOOL + } +} + +func (o *InetAddrDetail) SetScope(scope string) { + value, err := strconv.ParseUint(scope, 10, 8) + if err == nil { + o.scope = uint8(value) + return + } + + switch strings.ToLower(scope) { + case "host": + o.scope = IFA_SCOPE_HOST + case "link": + o.scope = IFA_SCOPE_LINK + case "global": + fallthrough + default: + o.scope = IFA_SCOPE_GLOBAL + // o.scope = 255 + } +} + +func (o *InetAddrDetail) SetCid(cid uint8) { + o.cid = cid +} + +func (o *InetAddrDetail) SetIfName(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *InetAddrDetail) setAddr(addr string) { + if strings.Contains(addr, ":") { + copy(o.addr[:], net.ParseIP(addr)) + o.af = unix.AF_INET6 + return + } + + o.af = unix.AF_INET + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.addr[:], buf.Bytes()[12:]) +} + +func (o *InetAddrDetail) SetAddr(addr string) { + var plen, ip string + + if strings.Index(addr, "/") != -1 { + plen = addr[strings.Index(addr, "/")+1:] + ip = addr[:strings.Index(addr, "/")] + } else { + ip = addr + plen = "32" + + if strings.Contains(ip, ":") { + plen = "128" + } + } + + o.setAddr(ip) + + value, err := strconv.ParseUint(plen, 10, 8) + if err == nil { + o.SetPlen(uint8(value)) + } +} + +func (o *InetAddrDetail) SetBCast(addr string) { + if len(addr) == 0 { + return + } + if strings.Contains(addr, ":") { + copy(o.bcast[:], net.ParseIP(addr)) + } else { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.bcast[:], buf.Bytes()[12:]) + } +} + +func (o *InetAddrDetail) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*InetAddrDetail, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to InetAddrDetail") + } + + details := make([]*InetAddrDetail, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + details[i] = NewInetAddrDetail() + details[i].Dump(buf) + } + + return details, nil +} + +func (o *InetAddrDetail) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +/**************** +****************/ +func (o *InetAddrDetail) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*InetAddrDetail, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_IFADDR_GET_BASE, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE Write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE Write specific inetaddr failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE reply msg Read failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE failed", "result", result) + err = fmt.Errorf("Sockopt DPVSAGENT_IFADDR_GET_BASE reply ErrorCode: %s", result) + return nil, err + } + + front := NewInetAddrFront() + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_BASE read table header failed", "Error", err.Error()) + return nil, err + } + + return o.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +func (o *InetAddrDetail) Add(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + traceName := fmt.Sprintf("dpip addr add %s dev %s", o.GetAddr(), o.GetIfName()) + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_IFADDR_ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_ADD Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_ADD write inetaddr detail failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_ADD reply msg Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + addr := o.GetAddr() + logger.Info("Sockopt DPVSAGENT_IFADDR_ADD done", "addr", addr, "result", result) + return errCode +} + +func (o *InetAddrDetail) Del(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + traceName := fmt.Sprintf("dpip addr del %s dev %s", o.GetAddr(), o.GetIfName()) + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_IFADDR_DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_DEL Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_DEL write del inetaddr detail failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_DEL Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + addr := o.GetAddr() + logger.Info("Sockopt DPVSAGENT_IFADDR_DEL done", "addr", addr, "del", "result", result) + return errCode +} + +func (o *InetAddrStats) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*InetAddrStats, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_IFADDR_GET_STATS, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_STATS Write proto header failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_IFADDR_GET_STATS reply msg Read failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST failed", "result", result) + err = fmt.Errorf("Sockopt SOCKOPT_GET_KNI_LIST failed. ErrorCode: %s", reply.GetErrStr()) + return nil, err + } + + front := NewInetAddrFront() + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST read table header failed", "Error", err.Error()) + return nil, err + } + + return o.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} diff --git a/tools/dpvs-agent/pkg/ipc/types/iprange.go b/tools/dpvs-agent/pkg/ipc/types/iprange.go new file mode 100644 index 000000000..d35182498 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/iprange.go @@ -0,0 +1,43 @@ +package types + +type ipRange struct { + minAddr [0x10]byte + maxAddr [0x10]byte + minPort uint16 + maxPort uint16 +} + +func (r *ipRange) Copy(src *ipRange) bool { + if src == nil { + return false + } + copy(r.minAddr[:], src.minAddr[:]) + copy(r.maxAddr[:], src.maxAddr[:]) + r.minPort = src.minPort + r.maxPort = src.maxPort + return true +} + +func (r *ipRange) SetMinAddr(addr []byte) { + copy(r.minAddr[:], addr) +} + +func (r *ipRange) SetMaxAddr(addr []byte) { + copy(r.maxAddr[:], addr) +} + +func (r *ipRange) GetMinAddr() string { + return TrimRightZeros(string(r.minAddr[:])) +} + +func (r *ipRange) GetMaxAddr() string { + return TrimRightZeros(string(r.maxAddr[:])) +} + +func (r *ipRange) SetMinPort(port uint16) { + r.minPort = port +} + +func (r *ipRange) SetMaxPort(port uint16) { + r.maxPort = port +} diff --git a/tools/dpvs-agent/pkg/ipc/types/kni.go b/tools/dpvs-agent/pkg/ipc/types/kni.go new file mode 100644 index 000000000..afa2d0cff --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/kni.go @@ -0,0 +1,314 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type KniAddrFlowFront struct { + count uint32 +} + +type KniAddrFlowEntry struct { + af uint32 + addr [0x10]byte +} + +type KniAddrFlowSpec struct { + flags uint32 + ifName [0x10]byte + entry KniAddrFlowEntry +} + +func NewKniAddrFlowFront() *KniAddrFlowFront { + return &KniAddrFlowFront{} +} + +func NewKniAddrFlowSpec() *KniAddrFlowSpec { + return &KniAddrFlowSpec{flags: 1} +} + +func NewKniAddrFlowEntry() *KniAddrFlowEntry { + return &KniAddrFlowEntry{} +} + +func (o *KniAddrFlowSpec) Copy(src *KniAddrFlowSpec) bool { + o.flags = src.flags + copy(o.ifName[:], src.ifName[:]) + return o.entry.Copy(&src.entry) +} + +func (o *KniAddrFlowEntry) Copy(src *KniAddrFlowEntry) bool { + o.af = src.af + copy(o.addr[:], src.addr[:]) + return true +} + +func (o *KniAddrFlowFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *KniAddrFlowSpec) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *KniAddrFlowEntry) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *KniAddrFlowFront) Copy(src *KniAddrFlowFront) bool { + o.count = src.count + return true +} + +func (o *KniAddrFlowFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *KniAddrFlowFront = *(**KniAddrFlowFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *KniAddrFlowSpec) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *KniAddrFlowSpec = *(**KniAddrFlowSpec)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *KniAddrFlowEntry) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *KniAddrFlowEntry = *(**KniAddrFlowEntry)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *KniAddrFlowFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *KniAddrFlowSpec) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *KniAddrFlowEntry) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *KniAddrFlowSpec) SetFlags(flags uint32) { + o.flags = 1 // must be 1 +} + +func (o *KniAddrFlowSpec) SetDevice(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *KniAddrFlowEntry) SetAf(af uint32) { + o.af = af +} + +func (o *KniAddrFlowEntry) SetAddr(addr string) { + if strings.Contains(addr, ":") { + o.SetAf(unix.AF_INET6) + copy(o.addr[:], net.ParseIP(addr)) + return + } + + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.addr[:], buf.Bytes()[12:]) +} + +func (o *KniAddrFlowFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*KniAddrFlowFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("buffer may not convert to KniAddrFlowFront") + } + + fronts := make([]*KniAddrFlowFront, cnt) + for i := 0; i < int(cnt); i++ { + fronts[i] = NewKniAddrFlowFront() + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *KniAddrFlowSpec) write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (o *KniAddrFlowEntry) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*KniAddrFlowEntry, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("buffer may not convert to KniAddrFlowEntry") + } + + entries := make([]*KniAddrFlowEntry, cnt) + for i := 0; i < int(cnt); i++ { + entries[i] = NewKniAddrFlowEntry() + err := conn.Read(entries[i]) + if err != nil { + continue + } + } + + logger.Info("Get Kni Addr success", "entries", entries) + return entries, nil +} + +func (o *KniAddrFlowSpec) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*KniAddrFlowEntry, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, SOCKOPT_GET_KNI_LIST, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST Write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := o.write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST write spec kni failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST Read reply failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST failed", "result", result) + err = fmt.Errorf("Sockopt SOCKOPT_GET_KNI_LIST reply ErrorCode: %s", reply.GetErrStr()) + return nil, err + } + + front := NewKniAddrFlowFront() + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_GET_KNI_LIST read table header failed", "Error", err.Error()) + return nil, err + } + + entry := NewKniAddrFlowEntry() + return entry.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +func (o *KniAddrFlowSpec) Add(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var ADD uint32 + ADD = SOCKOPT_SET_KNI_ADD + + msg := NewSockMsg(SOCKOPT_VERSION, ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_ADD Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + err = o.write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_ADD write spec kni failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_ADD Read reply failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + logger.Info("Sockopt SOCKOPT_SET_KNI_ADD Done:", errCode.String()) + return errCode +} + +func (o *KniAddrFlowSpec) Del(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_DEL Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var DEL uint32 + DEL = SOCKOPT_SET_KNI_DEL + + msg := NewSockMsg(SOCKOPT_VERSION, DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_DEL Write spec kni failed", "Error", err.Error()) + return EDPVS_IO + } + err = o.write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_DEL write spec kni failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_KNI_DEL Read reply failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("Sockopt SOCKOPT_SET_KNI_DEL Done", "result", result) + return errCode +} diff --git a/tools/dpvs-agent/pkg/ipc/types/laddr.go b/tools/dpvs-agent/pkg/ipc/types/laddr.go new file mode 100644 index 000000000..7e16f8763 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/laddr.go @@ -0,0 +1,492 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type LocalAddrFront struct { + af uint32 + port uint32 + proto uint32 + fwmark uint32 + cid uint32 + count uint32 + addr [0x10]byte + match dpvsMatch + nop uint32 +} + +func NewLocalAddrFront() *LocalAddrFront { + return &LocalAddrFront{} +} + +func (o *LocalAddrFront) ID() string { + proto := "tcp" + if o.proto == unix.IPPROTO_UDP { + proto = "udp" + } + return fmt.Sprintf("%s-%d-%s", o.GetAddr(), o.GetPort(), proto) +} + +func (o *LocalAddrFront) GetPort() uint32 { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(o.port)) + port := binary.BigEndian.Uint16(buf.Bytes()) + return uint32(port) +} + +func (o *LocalAddrFront) GetAddr() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.addr[0], o.addr[1], o.addr[2], o.addr[3]) + return addr.String() + } + + addr = net.IP{o.addr[0x0], o.addr[0x1], o.addr[0x2], o.addr[0x3], + o.addr[0x4], o.addr[0x5], o.addr[0x6], o.addr[0x7], + o.addr[0x8], o.addr[0x9], o.addr[0xa], o.addr[0xb], + o.addr[0xc], o.addr[0xd], o.addr[0xe], o.addr[0xf], + } + return addr.String() +} + +func (o *LocalAddrFront) GetAf() uint32 { + return o.af +} + +func (o *LocalAddrFront) SetAf(af uint32) { + o.af = af +} +func (o *LocalAddrFront) SetAfByAddr(addr string) { + i := strings.Index(addr, "/") + if i != -1 { + i = len(addr) + } + + if strings.Count(addr[:i], ".") == 3 { + o.af = unix.AF_INET + } + if strings.Count(addr[:i], ":") >= 2 { + o.af = unix.AF_INET6 + } +} +func (o *LocalAddrFront) SetPort(port uint32) { + o.port = port +} +func (o *LocalAddrFront) SetProto(proto uint32) { + o.proto = proto +} +func (o *LocalAddrFront) SetFwmark(fwmark uint32) { + o.fwmark = fwmark +} + +func (o *LocalAddrFront) ParseVipPortProto(vipport string) error { + vip := strings.Split(vipport, "-")[0] + port := strings.Split(vipport, "-")[1] + proto := strings.Split(vipport, "-")[2] + + switch strings.ToLower(proto) { + case "udp": + o.proto = unix.IPPROTO_UDP + default: + o.proto = unix.IPPROTO_TCP + } + + value, err := strconv.Atoi(port) + if err != nil { + return err + } + + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(value)) + + o.port = uint32(binary.BigEndian.Uint16(buf.Bytes())) + if strings.Contains(vipport, ":") { + o.af = unix.AF_INET6 + copy(o.addr[:], net.ParseIP(vip)) + } else { + o.af = unix.AF_INET + + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(vip)) + copy(o.addr[:], buf.Bytes()[12:]) + } + + return nil +} + +func (o *LocalAddrFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *LocalAddrFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *LocalAddrFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *LocalAddrFront = *(**LocalAddrFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *LocalAddrFront) Copy(src *LocalAddrFront) bool { + if src == nil { + return false + } + + o.af = src.af + o.port = src.port + o.proto = src.proto + o.fwmark = src.fwmark + o.cid = src.cid + o.count = src.count + + copy(o.addr[:], src.addr[:]) + + return o.match.Copy(&src.match) +} + +func (o *LocalAddrFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*LocalAddrFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("buffer may not convert to LocalAddrFront") + } + + fronts := make([]*LocalAddrFront, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i] = NewLocalAddrFront() + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *LocalAddrFront) write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type LocalAddrDetail struct { + af uint32 + conns uint32 + portConflict uint64 + addr [0x10]byte + ifName [unix.IFNAMSIZ]byte +} + +func NewLocalAddrDetail() *LocalAddrDetail { + return &LocalAddrDetail{} +} + +func (o *LocalAddrDetail) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *LocalAddrDetail) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *LocalAddrDetail) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *LocalAddrDetail = *(**LocalAddrDetail)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *LocalAddrDetail) SetAf(af uint32) { + o.af = af +} + +func (o *LocalAddrDetail) GetAf() uint32 { + return o.af +} + +func (o *LocalAddrDetail) GetConns() uint32 { + return o.conns +} + +func (o *LocalAddrDetail) GetPortConflict() uint64 { + return o.portConflict +} + +func (o *LocalAddrDetail) SetAfByAddr(addr string) { + i := strings.Index(addr, "/") + if i != -1 { + i = len(addr) + } + + if strings.Count(addr[:i], ":") >= 2 { + o.af = unix.AF_INET6 + } + if strings.Count(addr[:i], ".") == 3 { + o.af = unix.AF_INET + } +} + +func (o *LocalAddrDetail) GetAddr() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.addr[0], o.addr[1], o.addr[2], o.addr[3]) + return addr.String() + } + + addr = net.IP{o.addr[0x0], o.addr[0x1], o.addr[0x2], o.addr[0x3], + o.addr[0x4], o.addr[0x5], o.addr[0x6], o.addr[0x7], + o.addr[0x8], o.addr[0x9], o.addr[0xa], o.addr[0xb], + o.addr[0xc], o.addr[0xd], o.addr[0xe], o.addr[0xf], + } + return addr.String() +} + +func (o *LocalAddrDetail) SetAddr(addr string) { + if strings.Contains(addr, ":") { + copy(o.addr[:], net.ParseIP(addr)) + } else { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.addr[:], buf.Bytes()[12:]) + } +} + +func (o *LocalAddrDetail) GetIfName() string { + return TrimRightZeros(string(o.ifName[:])) +} + +func (o *LocalAddrDetail) SetIfName(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *LocalAddrDetail) Copy(src *LocalAddrDetail) bool { + if src == nil { + return false + } + + o.af = src.af + o.conns = src.conns + o.portConflict = src.portConflict + + copy(o.addr[:], src.addr[:]) + copy(o.ifName[:], src.ifName[:]) + + return true +} + +func (o *LocalAddrDetail) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*LocalAddrDetail, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("buffer may not convert to LocalAddrEntry") + } + + details := make([]*LocalAddrDetail, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + // logger.Info(fmt.Sprintf("fetch RAW local address from dpvs (%d): %x", o.Sizeof(), buf)) + details[i] = NewLocalAddrDetail() + details[i].Dump(buf) + } + + logger.Info("Get Local Addr Done", "details", details) + return details, nil +} + +func (o *LocalAddrDetail) write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +/**************** +****************/ +func (o *LocalAddrFront) Get(cp *pool.ConnPool, parentLogger hclog.Logger) ([]*LocalAddrDetail, error) { + logger := hclog.Default().Named(o.ID()) + if parentLogger != nil { + logger = parentLogger.Named(o.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_GET_LADDR, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := o.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR write laddr table header failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR Read sockmsg failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR failed", "result", result) + err = fmt.Errorf("Sockopt DPVSAGENT_VS_GET_LADDR reply ErrorCode: %s", result) + return nil, err + } + + _, err = o.read(conn, o.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_LADDR read table header failed", "Error", err.Error()) + return nil, err + } + + detail := NewLocalAddrDetail() + return detail.read(conn, uint64(reply.GetLen())-o.Sizeof(), logger) +} + +func (o *LocalAddrFront) Add(details []*LocalAddrDetail, cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(o.ID()) + if parentLogger != nil { + logger = parentLogger.Named(o.ID()) + } + + if len(details) == 0 { + logger.Info("There are No laddr to set, return immediately") + return EDPVS_OK + } + o.count = uint32(len(details)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_ADD_LADDR, SOCKOPT_SET, o.Sizeof()+uint64(len(details))*details[0].Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_LADDR write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := o.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_LADDR write laddr table header failed", "Error", err.Error()) + return EDPVS_IO + } + + for _, detail := range details { + if err := detail.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_LADDR write spec laddr failed", "Error", err.Error()) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_LADDR Read reply failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVSAGENT_VS_ADD_LADDR Done", "details", details, "result", result) + return errCode +} + +func (o *LocalAddrFront) Del(details []*LocalAddrDetail, cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(o.ID()) + if parentLogger != nil { + logger = parentLogger.Named(o.ID()) + } + + if len(details) == 0 { + logger.Info("There are No laddr to del, return immediately") + return EDPVS_OK + } + o.count = uint32(len(details)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_DEL_LADDR, SOCKOPT_SET, o.Sizeof()+uint64(len(details))*details[0].Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_LADDR Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := o.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_LADDR write laddr table header failed", "Error", err.Error()) + return EDPVS_IO + } + + for _, detail := range details { + if err := detail.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_LADDR write spec laddr failed", "Error", err.Error()) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_LADDR Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVSAGENT_VS_DEL_LADDR", "details", details, " Done", "result", result) + return errCode +} diff --git a/tools/dpvs-agent/pkg/ipc/types/method.go b/tools/dpvs-agent/pkg/ipc/types/method.go new file mode 100644 index 000000000..ab1254f4c --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/method.go @@ -0,0 +1 @@ +package types diff --git a/tools/dpvs-agent/pkg/ipc/types/netif.go b/tools/dpvs-agent/pkg/ipc/types/netif.go new file mode 100644 index 000000000..f403ebb03 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/netif.go @@ -0,0 +1,728 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + // "errors" + "fmt" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type NetifNicDesc struct { + name [0x20]byte + mac [0x12]byte + flags uint16 +} + +func NewNetifNicDesc() *NetifNicDesc { + return &NetifNicDesc{} +} + +func (o *NetifNicDesc) Copy(src *NetifNicDesc) bool { + o.flags = src.flags + copy(o.name[:], src.name[:]) + copy(o.mac[:], src.mac[:]) + return true +} + +func (o *NetifNicDesc) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicDesc) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicDesc = *(**NetifNicDesc)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicDesc) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *NetifNicDesc) SetName(device string) { + copy(o.name[:], device[:]) +} + +func (o *NetifNicDesc) SetMac(mac string) { + // not set in user plane +} + +func (o *NetifNicDesc) SetPromisc(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("promisc_on") + return true + case "off", "down", "false": + o.setFlags("promisc_off") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) SetLink(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("link_status_up") + return true + case "off", "down", "false": + o.setFlags("link_status_down") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) SetFwd2Kni(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("forward2kni_on") + return true + case "off", "down", "false": + o.setFlags("forward2kni_off") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) SetTcEgress(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("tc_egress_on") + return true + case "off", "down", "false": + o.setFlags("tc_egress_off") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) SetTcIngress(device, flags string) bool { + o.SetName(device) + switch strings.ToLower(flags) { + case "on", "up", "true": + o.setFlags("tc_ingress_on") + return true + case "off", "down", "false": + o.setFlags("tc_ingress_off") + return true + case "unset": + return false + default: + return false + } + return false +} + +func (o *NetifNicDesc) setFlags(flags string) { + bak := o.flags + + o.flags = o.flags ^ o.flags + + switch strings.ToLower(flags) { + case "promisc_on": + o.flags |= NETIF_NIC_PROMISC_ON + case "promisc_off": + o.flags |= NETIF_NIC_PROMISC_OFF + case "link_status_up": + o.flags |= NETIF_NIC_LINK_UP + case "link_status_down": + o.flags |= NETIF_NIC_LINK_DOWN + case "forward2kni_on": + o.flags |= NETIF_NIC_FWD2KNI_ON + case "forward2kni_off": + o.flags |= NETIF_NIC_FWD2KNI_OFF + case "tc_egress_on": + o.flags |= NETIF_NIC_TC_EGRESS_ON + case "tc_egress_off": + o.flags |= NETIF_NIC_TC_EGRESS_OFF + case "tc_ingress_on": + o.flags |= NETIF_NIC_TC_INGRESS_ON + case "tc_ingress_off": + o.flags |= NETIF_NIC_TC_INGRESS_OFF + default: + o.flags |= bak + } +} + +func (o *NetifNicDesc) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (o *NetifNicDesc) Set(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var SET uint32 + SET = SOCKOPT_NETIF_SET_PORT + + msg := NewSockMsg(SOCKOPT_VERSION, SET, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_SET_PORT Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_SET_PORT write specific port failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_SET_PORT reply msg Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("Sockopt SOCKOPT_NETIF_SET_PORT Done", "result", result) + return errCode +} + +type NetifNicEntryFront struct { + count uint16 + phyBase uint16 + phyEnd uint16 + bondBase uint16 + bondEnd uint16 +} + +func NewNetifNicEntryFront() *NetifNicEntryFront { + return &NetifNicEntryFront{} +} + +func (o *NetifNicEntryFront) Copy(src *NetifNicEntryFront) bool { + o.count = src.count + o.phyBase = src.phyBase + o.phyEnd = src.phyEnd + o.bondBase = src.bondBase + o.bondEnd = src.bondEnd + return true +} + +func (o *NetifNicEntryFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicEntryFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicEntryFront = *(**NetifNicEntryFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicEntryFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *NetifNicEntryFront) read(conn *pool.Conn, logger hclog.Logger) error { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +type NetifNicEntry struct { + id uint16 + name [0x10]byte +} + +func (o *NetifNicEntry) GetID() uint16 { + return o.id +} + +func (o *NetifNicEntry) GetName() string { + return TrimRightZeros(string(o.name[:])) +} + +func NewNetifNicEntry() *NetifNicEntry { + return &NetifNicEntry{} +} + +func (o *NetifNicEntry) Copy(src *NetifNicEntry) bool { + copy(o.name[:], src.name[:]) + o.id = src.id + return true +} + +func (o *NetifNicEntry) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicEntry) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicEntry = *(**NetifNicEntry)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicEntry) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *NetifNicEntry) read(conn *pool.Conn, logger hclog.Logger) error { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +type NetifNicEntries struct { + Front *NetifNicEntryFront + Entries []*NetifNicEntry +} + +func NewNetifNicEntries() *NetifNicEntries { + return &NetifNicEntries{Front: NewNetifNicEntryFront()} +} + +func (o *NetifNicDesc) GetPortList(cp *pool.ConnPool, logger hclog.Logger) (*NetifNicEntries, DpvsErrType) { + var GET uint32 + GET = SOCKOPT_NETIF_GET_PORT_LIST + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST Write proto header failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST write specific port failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST reply msg Read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if reply.GetErrCode() != EDPVS_OK { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST failed.", "reply", reply.GetErrStr()) + return nil, reply.GetErrCode() + } + + nic := NewNetifNicEntries() + + err = nic.Front.read(conn, logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_LIST table header read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if nic.Front.count <= 0 { + return nic, EDPVS_OK + } + + entry := NewNetifNicEntry() + resLen := int(reply.GetLen()) - int(nic.Front.Sizeof()) + if resLen != int(entry.Sizeof())*int(nic.Front.count) { + conn.Release(resLen) + logger.Error(fmt.Sprintf("buffer may not convert to %d count NetifNicEntry", nic.Front.count)) + return nil, EDPVS_IO + } + + nic.Entries = make([]*NetifNicEntry, nic.Front.count) + + for i := 0; i < int(nic.Front.count); i++ { + nic.Entries[i] = NewNetifNicEntry() + nic.Entries[i].read(conn, logger) + } + return nic, EDPVS_OK +} + +type NetifNicDetail struct { + name [0x20]byte + addr [0x20]byte + status [0x10]byte + duplex [0x10]byte + autoneg [0x10]byte + speed uint32 + nrxq uint8 + ntxq uint8 + padding [0x3]uint8 + socketId uint8 + id uint16 + mtu uint16 + flags uint16 +} + +func NewNetifNicDetail() *NetifNicDetail { + return &NetifNicDetail{} +} + +func (o *NetifNicDetail) Copy(src *NetifNicDetail) bool { + o.speed = src.speed + o.nrxq = src.nrxq + o.ntxq = src.ntxq + o.socketId = src.socketId + o.id = src.id + o.mtu = src.mtu + o.flags = src.flags + copy(o.name[:], src.name[:]) + copy(o.addr[:], src.addr[:]) + copy(o.status[:], src.status[:]) + copy(o.duplex[:], src.duplex[:]) + copy(o.autoneg[:], src.autoneg[:]) + return true +} + +func (o *NetifNicDetail) GetSpeed() uint32 { + return o.speed +} + +func (o *NetifNicDetail) GetSocketID() uint8 { + return o.socketId +} + +func (o *NetifNicDetail) GetTxQueueCount() uint8 { + return o.ntxq +} + +func (o *NetifNicDetail) GetRxQueueCount() uint8 { + return o.nrxq +} + +func (o *NetifNicDetail) GetStatus() string { + return TrimRightZeros(string(o.status[:])) +} + +func (o *NetifNicDetail) GetName() string { + return TrimRightZeros(string(o.name[:])) +} + +func (o *NetifNicDetail) GetLinkDuplex() string { + return TrimRightZeros(string(o.duplex[:])) +} + +func (o *NetifNicDetail) GetLinkAutoNeg() string { + return TrimRightZeros(string(o.autoneg[:])) +} + +func (o *NetifNicDetail) GetAddr() string { + return TrimRightZeros(string(o.addr[:])) +} + +func (o *NetifNicDetail) GetMTU() uint16 { + return o.mtu +} + +func (o *NetifNicDetail) GetID() uint16 { + return o.id +} + +func (o *NetifNicDetail) GetFlags() uint16 { + return o.flags +} + +func (o *NetifNicDetail) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicDetail) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicDetail = *(**NetifNicDetail)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicDetail) read(conn *pool.Conn, logger hclog.Logger) error { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +func (o *NetifNicDesc) GetPortBasic(cp *pool.ConnPool, logger hclog.Logger) (*NetifNicDetail, DpvsErrType) { + var GET uint32 + GET = SOCKOPT_NETIF_GET_PORT_BASIC + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return nil, EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC Write proto header failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC write specific port failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC reply msg Read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if reply.GetErrCode() != EDPVS_OK { + logger.Error(fmt.Sprintf("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC reply ErrorCode: %s", reply.GetErrStr())) + return nil, reply.GetErrCode() + } + + detail := NewNetifNicDetail() + if err := detail.read(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC spec port read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + logger.Info("Sockopt SOCKOPT_NETIF_GET_PORT_BASIC read Done") + return detail, EDPVS_OK +} + +type NetifNicQueue struct { + queue [0x10]uint64 +} + +func (o *NetifNicQueue) Copy(src *NetifNicQueue) bool { + if src == nil { + return false + } + + for i := 0; i < len(o.queue); i++ { + o.queue[i] = src.queue[i] + } + + return true +} + +type NetifNicStats struct { + mBufAvail uint32 + mBufInuse uint32 + inPkts uint64 + outPkts uint64 + inBytes uint64 + outBytes uint64 + inMissed uint64 + inErrors uint64 + outErrors uint64 + rxNoMbuf uint64 + inPktsQ NetifNicQueue + outPktsQ NetifNicQueue + inBytesQ NetifNicQueue + outBytesQ NetifNicQueue + errorQ NetifNicQueue + padding [0x3]uint16 + id uint16 +} + +func NewNetifNicStats() *NetifNicStats { + return &NetifNicStats{} +} + +func (o *NetifNicStats) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *NetifNicStats) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *NetifNicStats = *(**NetifNicStats)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *NetifNicStats) Copy(src *NetifNicStats) bool { + o.id = src.id + o.mBufAvail = src.mBufAvail + o.mBufInuse = src.mBufInuse + o.inPkts = src.inPkts + o.outPkts = src.outPkts + o.inBytes = src.inBytes + o.outBytes = src.outBytes + o.inMissed = src.inMissed + o.inErrors = src.inErrors + o.outErrors = src.outErrors + o.rxNoMbuf = src.rxNoMbuf + o.inPktsQ.Copy(&src.inPktsQ) + o.outPktsQ.Copy(&src.outPktsQ) + o.inBytesQ.Copy(&src.inBytesQ) + o.outBytesQ.Copy(&src.outBytesQ) + o.errorQ.Copy(&src.errorQ) + return true +} + +func (o *NetifNicStats) GetID() uint16 { + return o.id +} + +func (o *NetifNicStats) GetRxNoMbuf() uint64 { + return o.rxNoMbuf +} + +func (o *NetifNicStats) GetOutErrors() uint64 { + return o.outErrors +} + +func (o *NetifNicStats) GetInErrors() uint64 { + return o.inErrors +} + +func (o *NetifNicStats) GetInMissed() uint64 { + return o.inMissed +} + +func (o *NetifNicStats) GetOutBytes() uint64 { + return o.outBytes +} + +func (o *NetifNicStats) GetInBytes() uint64 { + return o.inBytes +} + +func (o *NetifNicStats) GetOutPkts() uint64 { + return o.outPkts +} + +func (o *NetifNicStats) GetInPkts() uint64 { + return o.inPkts +} + +func (o *NetifNicStats) GetMBufInuse() uint32 { + return o.mBufInuse +} + +func (o *NetifNicStats) GetMBufAvail() uint32 { + return o.mBufAvail +} + +func (o *NetifNicStats) read(conn *pool.Conn, logger hclog.Logger) error { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + o.Dump(buf) + + return nil +} + +func (o *NetifNicDesc) GetPortStats(cp *pool.ConnPool, logger hclog.Logger) (*NetifNicStats, DpvsErrType) { + var GET uint32 + GET = SOCKOPT_NETIF_GET_PORT_STATS + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_STATS Write proto header failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_STATS Write specific port failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_STATS reply msg Read failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + stats := NewNetifNicStats() + if err := stats.read(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_NETIF_GET_PORT_STATS read port stats failed", "Error", err.Error()) + return nil, EDPVS_IO + } + + logger.Info("Sockopt SOCKOPT_NETIF_GET_PORT_STATS read Done") + return stats, EDPVS_OK +} + +/* +func (o *NetifNicDesc) GetPortExtra(cp *pool.ConnPool) DpvsErrType { + var GET uint32 + GET = SOCKOPT_NETIF_GET_PORT_EXT_INFO +} +*/ diff --git a/tools/dpvs-agent/pkg/ipc/types/realserver.go b/tools/dpvs-agent/pkg/ipc/types/realserver.go new file mode 100644 index 000000000..bd56a7eb6 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/realserver.go @@ -0,0 +1,633 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type RealServerSpec struct { + af uint32 + port uint16 + proto uint16 + weight uint32 + addr [0x10]byte + connFlags uint16 + flags uint16 + fwdmode DpvsFwdMode + maxConn uint32 + minConn uint32 + actConns uint32 + inActConns uint32 + presistConns uint32 + stats dpvsStats +} + +func NewRealServerSpec() *RealServerSpec { + return &RealServerSpec{} +} + +func (rs *RealServerSpec) SetAf(af uint32) { + rs.af = af +} + +func (rs *RealServerSpec) SetProto(proto uint16) { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(proto)) + rs.proto = binary.BigEndian.Uint16(buf.Bytes()) +} + +func (rs *RealServerSpec) SetPort(port uint16) { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(port)) + rs.port = binary.BigEndian.Uint16(buf.Bytes()) +} + +func (rs *RealServerSpec) SetWeight(weight uint32) { + rs.weight = weight +} + +func (rs *RealServerSpec) GetWeight() uint32 { + return rs.weight +} + +func (rs *RealServerSpec) SetAddr(addr string) { + if strings.Contains(addr, ":") { + rs.af = unix.AF_INET6 + copy(rs.addr[:], net.ParseIP(addr)) + } else { + rs.af = unix.AF_INET + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(rs.addr[:], buf.Bytes()[12:]) + } +} + +func (rs *RealServerSpec) SetFlags(flags uint16) { + rs.flags = flags +} + +func (rs *RealServerSpec) setConnFlags(connFlags uint16) { + rs.connFlags = connFlags +} + +func (rs *RealServerSpec) SetFwdMode(fwdmode DpvsFwdMode) { + rs.setConnFlags(uint16(fwdmode) & DPVS_CONN_F_FWD_MASK) + rs.fwdmode = fwdmode +} + +func (rs *RealServerSpec) SetMaxConn(conns uint32) { + rs.maxConn = conns +} + +func (rs *RealServerSpec) SetMinConn(conns uint32) { + rs.minConn = conns +} + +func (rs *RealServerSpec) SetPresistConns(conns uint32) { + rs.presistConns = conns +} + +func (rs *RealServerSpec) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*rs)) +} + +func (rs *RealServerSpec) Copy(src *RealServerSpec) bool { + if src == nil { + return false + } + + copy(rs.addr[:], src.addr[:]) + + rs.af = src.af + rs.proto = src.proto + rs.port = src.port + rs.weight = src.weight + rs.flags = src.flags + rs.connFlags = src.connFlags + rs.fwdmode = src.fwdmode + rs.maxConn = src.maxConn + rs.minConn = src.minConn + rs.actConns = src.actConns + rs.inActConns = src.inActConns + rs.presistConns = src.presistConns + + return rs.stats.Copy(&src.stats) +} + +func (rs *RealServerSpec) Dump(buf []byte) bool { + if len(buf) != int(rs.Sizeof()) { + return false + } + + var tmp *RealServerSpec = *(**RealServerSpec)(unsafe.Pointer(&buf)) + + return rs.Copy(tmp) +} + +func (rs *RealServerSpec) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, rs) + return buf.Bytes() +} + +func (rs *RealServerSpec) write(conn *pool.Conn) error { + buf := rs.Package() + _, err := conn.WriteN(buf, int(rs.Sizeof())) + if err != nil { + // return errors.New("real server desc write failure(", written, "/", len(buf), ")") + return err + } + return nil +} + +func (rs *RealServerSpec) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*RealServerSpec, error) { + res := len % rs.Sizeof() + cnt := len / rs.Sizeof() + if res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to RealServerSpec") + } + + rss := make([]*RealServerSpec, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(rs.Sizeof())) + if err != nil { + continue + } + + rss[i] = NewRealServerSpec() + rss[i].Dump(buf) + spec := *rss[i] + logger.Info("get real server success", "spec", spec) + } + + return rss, nil +} + +func (rs *RealServerSpec) GetAddr() string { + if rs.af == unix.AF_INET { + addr := net.IPv4(rs.addr[0], rs.addr[1], rs.addr[2], rs.addr[3]) + return addr.String() + } + return "" +} + +func (rs *RealServerSpec) GetPort() uint16 { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(rs.port)) + return binary.BigEndian.Uint16(buf.Bytes()) +} + +func (rs *RealServerSpec) GetConnFlags() uint16 { + return rs.connFlags +} + +func (rs *RealServerSpec) GetOverloaded() bool { + return rs.flags&DPVS_DEST_F_OVERLOAD != 0 +} + +func (rs *RealServerSpec) SetOverloaded(overloaded *bool) { + if overloaded == nil { + return + } + if *overloaded { + rs.flags |= DPVS_DEST_F_OVERLOAD + } else { + rs.flags &= ^uint16(DPVS_DEST_F_OVERLOAD) + } +} + +func (rs *RealServerSpec) GetInhibited() bool { + return rs.flags&DPVS_DEST_F_INHIBITED != 0 +} + +func (rs *RealServerSpec) SetInhibited(inhibited *bool) { + if inhibited == nil { + return + } + if *inhibited { + rs.flags |= DPVS_DEST_F_INHIBITED + } else { + rs.flags &= ^uint16(DPVS_DEST_F_INHIBITED) + } +} + +func (rs *RealServerSpec) GetFwdModeString() string { + return rs.fwdmode.String() +} + +func (rs *RealServerSpec) ID() string { + return fmt.Sprintf("%s:%d", rs.GetAddr(), rs.port) +} + +func (rs *RealServerSpec) Format(kind string) string { + /* + -> RIP:RPORT\t\t\tFNAT\tWeight\tActive\tInactive + */ + return fmt.Sprintf(" -> %s:%d\t\t\t%s\t%d\t%d\t%d", rs.GetAddr(), rs.GetPort(), rs.GetFwdModeString(), rs.weight, rs.actConns, rs.inActConns) +} + +type RealServerFront struct { + af uint32 + proto uint16 + port uint16 + fwmark uint32 + addr [0x10]byte + numDests uint32 + match dpvsMatch + cid uint32 + index uint32 +} + +func NewRealServerFront() *RealServerFront { + return &RealServerFront{} +} + +func (rs *RealServerFront) SetNumDests(n uint32) { + rs.numDests = n +} + +func (rs *RealServerFront) ID() string { + proto := "tcp" + if rs.proto == unix.IPPROTO_UDP { + proto = "udp" + } + return fmt.Sprintf("%s-%d-%s", rs.GetAddr(), rs.GetPort(), proto) +} + +func (rs *RealServerFront) GetAddr() string { + var addr net.IP + + if rs.af == unix.AF_INET { + addr = net.IPv4(rs.addr[0], rs.addr[1], rs.addr[2], rs.addr[3]) + return addr.String() + } + + addr = net.IP{rs.addr[0x0], rs.addr[0x1], rs.addr[0x2], rs.addr[0x3], + rs.addr[0x4], rs.addr[0x5], rs.addr[0x6], rs.addr[0x7], + rs.addr[0x8], rs.addr[0x9], rs.addr[0xa], rs.addr[0xb], + rs.addr[0xc], rs.addr[0xd], rs.addr[0xe], rs.addr[0xf], + } + return addr.String() +} + +func (rs *RealServerFront) GetAf() uint32 { + return rs.af +} + +func (rs *RealServerFront) GetPort() uint16 { + return rs.port +} + +func (rs *RealServerFront) GetProto() uint16 { + return rs.proto +} + +func (rs *RealServerFront) Dump(buf []byte) bool { + if len(buf) != int(rs.Sizeof()) { + return false + } + + var tmp *RealServerFront = *(**RealServerFront)(unsafe.Pointer(&buf)) + + return rs.Copy(tmp) +} + +func (rs *RealServerFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, rs) + return buf.Bytes() +} + +func (rs *RealServerFront) write(conn *pool.Conn) error { + buf := rs.Package() + _, err := conn.WriteN(buf, int(rs.Sizeof())) + if err != nil { + return err + } + return nil +} + +func (rs *RealServerFront) read(conn *pool.Conn, logger hclog.Logger) error { + conn.SetReadBuffer(int(rs.Sizeof())) + buf, err := conn.ReadN(int(rs.Sizeof())) + if err != nil { + return err + } + + if !rs.Dump(buf) { + return errors.New("Dump RealServerFront failed") + } + + return nil +} + +func (rs *RealServerFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*rs)) +} + +func (o *RealServerFront) ParseVipPortProto(vipport string) error { + vip := strings.Split(vipport, "-")[0] + port := strings.Split(vipport, "-")[1] + proto := strings.Split(vipport, "-")[2] + + switch strings.ToLower(proto) { + case "tcp": + o.proto = unix.IPPROTO_TCP + case "udp": + o.proto = unix.IPPROTO_UDP + default: + } + + value, err := strconv.Atoi(port) + if err != nil { + return err + } + + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(value)) + + o.port = binary.BigEndian.Uint16(buf.Bytes()) + if strings.Contains(vipport, ":") { + o.af = unix.AF_INET6 + copy(o.addr[:], net.ParseIP(vip)) + } else { + o.af = unix.AF_INET + + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(vip)) + copy(o.addr[:], buf.Bytes()[12:]) + } + + return nil +} + +func (rs *RealServerFront) Copy(src *RealServerFront) bool { + if src == nil { + return false + } + + copy(rs.addr[:], src.addr[:]) + + rs.af = src.af + rs.proto = src.proto + rs.port = src.port + rs.fwmark = src.fwmark + rs.numDests = src.numDests + rs.cid = src.cid + + return rs.match.Copy(&src.match) +} + +/***************** +******************/ + +func (front *RealServerFront) Get(cp *pool.ConnPool, parentLogger hclog.Logger) ([]*RealServerSpec, error) { + logger := hclog.Default().Named(front.ID()) + if parentLogger != nil { + logger = parentLogger.Named(front.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_GET_DESTS, SOCKOPT_GET, front.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_DESTs write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := front.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_DESTs write body failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_DESTs Read sockmsg failed", "Error", err.Error()) + return nil, err + } + + if err := front.read(conn, logger); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_GET_DESTs read table header failed", "Error", err.Error()) + return nil, err + } + + rs := NewRealServerSpec() + + return rs.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +// put +func (front *RealServerFront) Edit(existOnly bool, rss []*RealServerSpec, cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(front.ID()) + if parentLogger != nil { + logger = parentLogger.Named(front.ID()) + } + + if len(rss) == 0 { + return EDPVS_OK + } + + sEdit := "DPVSAGENT_VS_EDIT_DESTS" + var EDIT uint32 = DPVSAGENT_VS_EDIT_DESTS + + if !existOnly { + EDIT = DPVSAGENT_VS_ADD_DESTS + sEdit = "DPVSAGENT_VS_ADD_DESTS" + } + + front.numDests = uint32(len(rss)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, EDIT, SOCKOPT_SET, front.Sizeof()+rss[0].Sizeof()*uint64(len(rss))) + + if err := msg.Write(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write proto header failed Error=%s", sEdit, err.Error())) + return EDPVS_IO + } + + if err := front.write(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write rss table header failed Error=%s", sEdit, err.Error())) + return EDPVS_IO + } + + for _, rs := range rss { + if err := rs.write(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Write rs %v header failed Error=%s", sEdit, *rs, err.Error())) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + + if err := reply.Read(conn); err != nil { + logger.Error(fmt.Sprintf("Sockopt %s Read sockmsg failed Error=%s", sEdit, err.Error())) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + logger.Info(fmt.Sprintf("%s %v Done result=%s", sEdit, rss, errCode.String())) + return errCode +} + +func (front *RealServerFront) add(rss []*RealServerSpec, cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + if len(rss) == 0 { + return EDPVS_OK + } + + front.numDests = uint32(len(rss)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_ADD_DESTS, SOCKOPT_SET, front.Sizeof()+rss[0].Sizeof()*uint64(len(rss))) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_DESTs write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := front.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_DESTs write rss table header failed", "Error", err.Error()) + return EDPVS_IO + } + + for _, rs := range rss { + if err := rs.write(conn); err != nil { + // backend error + logger.Error("Sockopt DPVSAGENT_VS_ADD_DESTs write spec rs failed", "Error", err.Error()) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_ADD_DESTs Read sockmsg failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVSAGENT_VS_ADD_DESTs Done", "result", result) + return errCode +} + +func (front *RealServerFront) Del(rss []*RealServerSpec, cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + if len(rss) == 0 { + logger.Info("No Real server need delete, return immediately") + return EDPVS_OK + } + + front.numDests = uint32(len(rss)) + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_VS_DEL_DESTS, SOCKOPT_SET, front.Sizeof()+rss[0].Sizeof()*uint64(len(rss))) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_DESTs write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := front.write(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_DESTs write rss table header failed", "Error", err.Error()) + return EDPVS_IO + } + + for _, rs := range rss { + if err := rs.write(conn); err != nil { + // backend error + logger.Error("Sockopt DPVSAGENT_VS_DEL_DESTs write spec rs failed", "Error", err.Error()) + return EDPVS_IO + } + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_VS_DEL_DESTs Read sockmsg failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVSAGENT_VS_ADD_DESTs Done", "result", result) + return errCode +} + +// post +func (front *RealServerFront) Update(rss []*RealServerSpec, cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(front.ID()) + if parentLogger != nil { + logger = parentLogger.Named(front.ID()) + } + + if len(rss) == 0 { + logger.Warn("Remove all RS ! ! !") + } + + running, err := front.Get(cp, logger) + if err != nil { + logger.Error("Get realserver failed", "Error", err.Error()) + return EDPVS_IO + } + + reserved := make(map[string]*RealServerSpec) + for _, rs := range rss { + reserved[rs.ID()] = rs + } + + unreserved := make([]*RealServerSpec, 0) + for _, expire := range running { + if _, ok := reserved[expire.ID()]; !ok { + unreserved = append(unreserved, expire) + } + } + logger.Info("reserved", reserved, "unreserved", unreserved) + + status := front.add(rss, cp, logger) + if status != EDPVS_OK { + return status + } + + errCode := front.Del(unreserved, cp, logger) + result := errCode.String() + logger.Info("Set", "rss", rss, "Done", "result", result) + return errCode +} diff --git a/tools/dpvs-agent/pkg/ipc/types/route.go b/tools/dpvs-agent/pkg/ipc/types/route.go new file mode 100644 index 000000000..e428ff621 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/route.go @@ -0,0 +1,470 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type RouteAddr struct { + addr [0x10]byte + plen uint32 // prefix len +} + +func (o *RouteAddr) Copy(src *RouteAddr) bool { + o.plen = src.plen + copy(o.addr[:], src.addr[:]) + return true +} + +type RouteDetail struct { + af uint32 + mtu uint32 + flags uint32 + metric uint32 + dst RouteAddr + src RouteAddr + gateway RouteAddr + prefSrc RouteAddr + ifName [0x10]byte +} + +func NewRouteDetail() *RouteDetail { + return &RouteDetail{} +} + +func (o *RouteDetail) GetIfName() string { + return TrimRightZeros(string(o.ifName[:])) +} + +func (o *RouteDetail) GetSrc() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.src.addr[0], o.src.addr[1], o.src.addr[2], o.src.addr[3]) + return addr.String() + } + + addr = net.IP{o.src.addr[0x0], o.src.addr[0x1], o.src.addr[0x2], o.src.addr[0x3], + o.src.addr[0x4], o.src.addr[0x5], o.src.addr[0x6], o.src.addr[0x7], + o.src.addr[0x8], o.src.addr[0x9], o.src.addr[0xa], o.src.addr[0xb], + o.src.addr[0xc], o.src.addr[0xd], o.src.addr[0xe], o.src.addr[0xf], + } + return addr.String() +} + +func (o *RouteDetail) GetDst() string { + var addr net.IP + + if o.af == unix.AF_INET { + addr = net.IPv4(o.dst.addr[0], o.dst.addr[1], o.dst.addr[2], o.dst.addr[3]) + return addr.String() + } + + addr = net.IP{o.dst.addr[0x0], o.dst.addr[0x1], o.dst.addr[0x2], o.dst.addr[0x3], + o.dst.addr[0x4], o.dst.addr[0x5], o.dst.addr[0x6], o.dst.addr[0x7], + o.dst.addr[0x8], o.dst.addr[0x9], o.dst.addr[0xa], o.dst.addr[0xb], + o.dst.addr[0xc], o.dst.addr[0xd], o.dst.addr[0xe], o.dst.addr[0xf], + } + return addr.String() +} + +func (o *RouteDetail) Copy(src *RouteDetail) bool { + o.af = src.af + o.mtu = src.mtu + o.flags = src.flags + o.metric = src.metric + o.dst.Copy(&src.dst) + o.src.Copy(&src.src) + o.gateway.Copy(&src.gateway) + o.prefSrc.Copy(&src.prefSrc) + copy(o.ifName[:], src.ifName[:]) + return true +} + +func (o *RouteDetail) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *RouteDetail) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *RouteDetail = *(**RouteDetail)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *RouteDetail) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *RouteDetail) SetAf(af uint32) { + o.af = af +} + +func (o *RouteDetail) SetMtu(mtu uint32) { + o.mtu = mtu +} + +func (o *RouteDetail) SetFlags(flags uint32) { + // FIXME o.flags ^= o.flags first ??? + o.flags |= flags +} + +func (o *RouteDetail) SetMetric(metric uint32) { + o.metric = metric +} + +func (o *RouteDetail) SetScope(scope string) { + switch strings.ToLower(scope) { + case "host": + o.SetFlags(RTF_LOCALIN) + case "kni_host": + o.SetFlags(RTF_KNI) + default: + /*case "global":*/ + /*case "link":*/ + o.SetFlags(RTF_FORWARD) + } +} + +func (o *RouteDetail) SetDst(dst string) { + addr := dst + plen := "32" + if strings.Index(dst, "/") != -1 { + addr = dst[:strings.Index(dst, "/")] + plen = dst[strings.Index(dst, "/")+1:] + } + + if strings.Contains(addr, ":") { + o.SetAf(unix.AF_INET6) + copy(o.dst.addr[:], net.ParseIP(addr)) + } else { + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(o.dst.addr[:], buf.Bytes()[12:]) + } + + mask, err := strconv.Atoi(plen) + if err != nil { + o.dst.plen = 32 + } + o.dst.plen = uint32(mask) +} + +func (o *RouteDetail) SetSrc(src string) bool { + if len(src) == 0 { + return false + } + + if strings.Contains(src, ":") { + o.SetAf(unix.AF_INET6) + copy(o.src.addr[:], net.ParseIP(src)) + } else { + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(src)) + copy(o.src.addr[:], buf.Bytes()[12:]) + } + + return true +} + +func (o *RouteDetail) SetGateway(gw string) bool { + if len(gw) == 0 { + return false + } + + if strings.Contains(gw, ":") { + o.SetAf(unix.AF_INET6) + copy(o.gateway.addr[:], net.ParseIP(gw)) + } else { + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(gw)) + copy(o.gateway.addr[:], buf.Bytes()[12:]) + } + return true +} + +func (o *RouteDetail) SetPrefSrc(pref string) { + if len(pref) == 0 { + return + } + + if strings.Contains(pref, ":") { + o.SetAf(unix.AF_INET6) + copy(o.prefSrc.addr[:], net.ParseIP(pref)) + } else { + o.SetAf(unix.AF_INET) + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(pref)) + copy(o.prefSrc.addr[:], buf.Bytes()[12:]) + } +} + +func (o *RouteDetail) SetDevice(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *RouteDetail) Read(conn *pool.Conn, len uint64) ([]*RouteDetail, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to RouteDetail") + } + + details := make([]*RouteDetail, cnt) + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + details[i] = NewRouteDetail() + details[i].Dump(buf) + } + + return details, nil +} + +func (o *RouteDetail) Write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type RouteFront struct { + count uint32 +} + +func NewRouteFront() *RouteFront { + return &RouteFront{} +} + +func (o *RouteFront) Copy(src *RouteFront) bool { + o.count = src.count + return true +} + +func (o *RouteFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *RouteFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *RouteFront = *(**RouteFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *RouteFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *RouteFront) SetCount(c uint32) { + o.count = c +} + +func (o *RouteFront) GetCount() uint32 { + return o.count +} + +func (o *RouteFront) Read(conn *pool.Conn, len uint64) ([]*RouteFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to RouteFront") + } + + fronts := make([]*RouteFront, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i] = NewRouteFront() + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *RouteFront) Write(conn *pool.Conn) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +/**************** +****************/ +func (o *RouteDetail) Get(cp *pool.ConnPool, parentLogger hclog.Logger) ([]*RouteDetail, error) { + traceName := o.GetIfName() + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + var GET uint32 + GET = DPVSAGENT_ROUTE_GET + if o.af == unix.AF_INET6 { + GET = DPVSAGENT_ROUTE6_GET + } + + msg := NewSockMsg(SOCKOPT_VERSION, GET, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt ", GET, "Write proto header failed", "Error", err.Error()) + return nil, err + } + + if err := o.Write(conn); err != nil { + logger.Error("Sockopt ", GET, "Write proto body failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt ", GET, "Read proto header failed", "Error", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + result := reply.GetErrStr() + logger.Error("Sockopt ", GET, " failed", "result", result) + err := fmt.Errorf("Sockopt %s reply ErrorCode: %s", GET, result) + return nil, err + } + + front := NewRouteFront() + _, err = front.Read(conn, front.Sizeof()) + if err != nil { + logger.Error("Sockopt ", GET, "read list header failed", "Error", err.Error()) + return nil, err + } + + return o.Read(conn, uint64(reply.GetLen())-front.Sizeof()) +} + +func (o *RouteDetail) Add(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + traceName := fmt.Sprintf("add %s via %s dev %s", o.GetSrc(), o.GetDst(), o.GetIfName()) + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var ADD uint32 + ADD = DPVSAGENT_ROUTE_ADD + if o.af == unix.AF_INET6 { + ADD = DPVSAGENT_ROUTE6_ADD + } + + msg := NewSockMsg(SOCKOPT_VERSION, ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt ", ADD, "Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + err = o.Write(conn) + if err != nil { + logger.Error("Sockopt ", ADD, "Write proto body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt ", ADD, "reply failed", "Error", err.Error()) + return EDPVS_IO + } + + return reply.GetErrCode() +} + +func (o *RouteDetail) Del(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + traceName := fmt.Sprintf("del %s via %s dev %s", o.GetSrc(), o.GetDst(), o.GetIfName()) + logger := hclog.Default().Named(traceName) + if parentLogger != nil { + logger = parentLogger.Named(traceName) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + var DEL uint32 + DEL = DPVSAGENT_ROUTE_DEL + if o.af == unix.AF_INET6 { + DEL = DPVSAGENT_ROUTE6_DEL + } + + msg := NewSockMsg(SOCKOPT_VERSION, DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt ", DEL, "Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = o.Write(conn) + if err != nil { + logger.Error("Sockopt ", DEL, "Write proto body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt ", DEL, "reply failed", "Error", err.Error()) + return EDPVS_IO + } + + return reply.GetErrCode() +} diff --git a/tools/dpvs-agent/pkg/ipc/types/sockmsg.go b/tools/dpvs-agent/pkg/ipc/types/sockmsg.go new file mode 100644 index 000000000..3db2543e5 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/sockmsg.go @@ -0,0 +1,132 @@ +package types + +import ( + "bytes" + "encoding/binary" + "errors" + "unsafe" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type SockMsg struct { + version uint32 + id uint32 + sockopt SockoptType + nop uint32 + len uint64 +} + +type ReplySockMsg struct { + version uint32 + id uint32 + sockopt SockoptType + errCode DpvsErrType + errStr [0x40]byte + len uint32 + nop uint32 +} + +func NewSockMsg(version, id uint32, sockopt SockoptType, len uint64) *SockMsg { + return &SockMsg{version: version, id: id, sockopt: sockopt, len: len} +} + +func (msg *SockMsg) GetLen() uint64 { + return msg.len +} + +func NewReplySockMsg() *ReplySockMsg { + return &ReplySockMsg{} +} + +func (msg *ReplySockMsg) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*msg)) +} + +func (msg *ReplySockMsg) Dump(buf []byte) bool { + if len(buf) != int(msg.Sizeof()) { + return false + } + + var tmp *ReplySockMsg = *(**ReplySockMsg)(unsafe.Pointer(&buf)) + msg.version = tmp.version + msg.id = tmp.id + msg.sockopt = tmp.sockopt + msg.errCode = tmp.errCode + msg.len = tmp.len + copy(msg.errStr[:], tmp.errStr[:]) + msg.ZeroPadding() + + return true +} + +func (msg *ReplySockMsg) SetVersion(version uint32) { + msg.version = version +} + +func (msg *ReplySockMsg) SetID(id uint32) { + msg.id = id +} + +func (msg *ReplySockMsg) SetSockopt(opt SockoptType) { + msg.sockopt = opt +} + +func (msg *ReplySockMsg) SetErrCode(code DpvsErrType) { + msg.errCode = code +} + +func (msg *ReplySockMsg) SetErrStr(err []byte) { + copy(msg.errStr[:], err) +} + +func (msg *ReplySockMsg) SetLen(len uint32) { + msg.len = len +} + +func (msg *ReplySockMsg) ZeroPadding() { + msg.nop = 0 +} + +func (msg *ReplySockMsg) GetErrCode() DpvsErrType { + return msg.errCode +} + +func (msg *ReplySockMsg) GetErrStr() string { + return TrimRightZeros(string(msg.errStr[:])) +} + +func (msg *ReplySockMsg) GetLen() uint32 { + return msg.len +} + +func (msg *SockMsg) Package() []byte { + hdr := new(bytes.Buffer) + binary.Write(hdr, binary.LittleEndian, msg) + return hdr.Bytes() +} + +func (msg *SockMsg) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*msg)) +} + +func (msg *SockMsg) Write(conn *pool.Conn) error { + buf := msg.Package() + _, err := conn.WriteN(buf, len(buf)) + if err != nil { + return err + } + return nil +} + +func (msg *ReplySockMsg) Read(conn *pool.Conn) error { + buf, err := conn.ReadN(int(msg.Sizeof())) + if err != nil { + return err + } + + if !msg.Dump(buf) { + return errors.New("dump reply msg failed") + } + return nil +} diff --git a/tools/dpvs-agent/pkg/ipc/types/utility.go b/tools/dpvs-agent/pkg/ipc/types/utility.go new file mode 100644 index 000000000..d887d9a19 --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/utility.go @@ -0,0 +1,11 @@ +package types + +import "strings" + +func TrimRightZeros(s string) string { + idx := strings.IndexByte(s, 0) + if idx >= 0 { + return s[:idx] + } + return s +} diff --git a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go new file mode 100644 index 000000000..bb7cc409d --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go @@ -0,0 +1,693 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "net" + "strconv" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/models" + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type VirtualServerFront struct { + cid uint8 + index uint8 + count uint16 + padding uint32 +} + +func NewVirtualServerFront() *VirtualServerFront { + return &VirtualServerFront{} +} + +func (o *VirtualServerFront) Copy(src *VirtualServerFront) bool { + if src == nil { + return false + } + + o.cid = src.cid + o.index = src.index + o.count = src.count + + return true +} + +func (o *VirtualServerFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *VirtualServerFront = *(**VirtualServerFront)(unsafe.Pointer(&buf)) + return o.Copy(tmp) +} + +func (o *VirtualServerFront) SetCid(cid uint8) { + o.cid = cid +} + +func (o *VirtualServerFront) SetIndex(index uint8) { + o.index = index +} + +func (o *VirtualServerFront) SetCount(count uint16) { + o.count = count +} + +func (o *VirtualServerFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *VirtualServerFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *VirtualServerFront) read(conn *pool.Conn, logger hclog.Logger) error { + conn.SetReadBuffer(int(o.Sizeof())) + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + return err + } + + if !o.Dump(buf) { + return errors.New("dump reply virtual server front failed") + } + logger.Info("Get Virtual Server Count success", "count", o.count) + + return nil +} +func (o *VirtualServerFront) Write(conn *pool.Conn) error { + buf := o.Package() + + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + + return nil +} + +type dpvsDestCheck struct { + types uint8 + padding [7]byte +} + +type VirtualServerSpec struct { + af uint32 + proto uint16 + port uint16 + fwmark uint32 + flags uint32 + timeout uint32 + connTimeout uint32 + netmask uint32 + bps uint32 + limitProportion uint32 + addr [0x10]byte + schedName [0x10]byte + match dpvsMatch + numDests uint32 + numLaddrs uint32 + cid uint64 + stats dpvsStats + hc dpvsDestCheck +} + +func NewVirtualServerSpec() *VirtualServerSpec { + return &VirtualServerSpec{} +} + +func (vs *VirtualServerSpec) Convert2NewRsFront() *RealServerFront { + front := NewRealServerFront() + + front.af = vs.af + front.port = vs.port + front.proto = vs.proto + front.fwmark = vs.fwmark + front.numDests = vs.numDests + front.cid = uint32(vs.cid) + + front.match.Copy(&vs.match) + copy(front.addr[:], vs.addr[:]) + + return front +} + +func (vs *VirtualServerSpec) Copy(src *VirtualServerSpec) bool { + if src == nil { + return false + } + + vs.af = src.af + vs.proto = src.proto + vs.port = src.port + vs.fwmark = src.fwmark + vs.flags = src.flags + vs.timeout = src.timeout + vs.connTimeout = src.connTimeout + vs.netmask = src.netmask + vs.bps = src.bps + vs.limitProportion = src.limitProportion + vs.numDests = src.numDests + vs.numLaddrs = src.numLaddrs + vs.cid = src.cid + vs.hc = src.hc + + copy(vs.addr[:], src.addr[:]) + copy(vs.schedName[:], src.schedName[:]) + + if !vs.match.Copy(&src.match) { + return false + } + if !vs.stats.Copy(&src.stats) { + return false + } + return true +} + +func (vs *VirtualServerSpec) ID() string { + proto := "tcp" + if vs.proto == unix.IPPROTO_UDP { + proto = "udp" + } + return fmt.Sprintf("%s-%d-%s", vs.GetAddr(), vs.GetPort(), proto) +} + +func (vs *VirtualServerSpec) Format(kind string) string { + /* + TCP VIP:PORT sched + -> RIP:RPORT Fnat weight actConn inActConn + -> RIP:RPORT Fnat weight actConn inActConn + ... + */ + + var vipport string + vip := vs.GetAddr() + if vip == "" { + return "" + } + port := vs.GetPort() + + vipport = fmt.Sprintf("%s:%d", vip, port) + if vs.proto == unix.IPPROTO_TCP { + vsHeader := fmt.Sprintf("TCP %s %s\r\n", vipport, string(vs.schedName[:])) + return vsHeader + } + + return "" +} + +func (vs *VirtualServerSpec) Dump(buf []byte) bool { + if len(buf) != int(vs.Sizeof()) { + return false + } + + var tmp *VirtualServerSpec = *(**VirtualServerSpec)(unsafe.Pointer(&buf)) + + return vs.Copy(tmp) +} + +func (vs *VirtualServerSpec) SetAf(af uint32) { + vs.af = af +} +func (vs *VirtualServerSpec) GetAf() uint32 { + return vs.af +} + +func (vs *VirtualServerSpec) SetProto(proto uint16) { + vs.proto = proto +} + +func (vs *VirtualServerSpec) SetPort(port uint16) { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(port)) + vs.port = binary.BigEndian.Uint16(buf.Bytes()) +} + +func (vs *VirtualServerSpec) GetPort() uint16 { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(vs.port)) + return binary.BigEndian.Uint16(buf.Bytes()) +} + +func (vs *VirtualServerSpec) GetProto() uint16 { + return vs.proto +} + +func (vs *VirtualServerSpec) SetFwmark(fwmark uint32) { + vs.fwmark = fwmark +} +func (vs *VirtualServerSpec) GetFwmark() uint32 { + return vs.fwmark +} + +func (vs *VirtualServerSpec) SetFlagsSyncProxy() { + vs.setFlags(DPVS_CONN_F_SYNPROXY) +} + +func (vs *VirtualServerSpec) SetFlagsExpireQuiescent() { + vs.setFlags(DPVS_CONN_F_EXPIRE_QUIESCENT) +} + +func (vs *VirtualServerSpec) SetFlagsPersistent() { + vs.setFlags(DPVS_SVC_F_PERSISTENT) +} + +func (vs *VirtualServerSpec) SetFlagsHashSrcIP() { + vs.flags &= (uint32)(^DPVS_SVC_F_QID_HASH) + vs.flags &= (uint32)(^DPVS_SVC_F_SIP_HASH) + + vs.setFlags(DPVS_SVC_F_SIP_HASH) +} + +func (vs *VirtualServerSpec) SetFlagsHashQuicID() { + vs.flags &= (uint32)(^DPVS_SVC_F_QID_HASH) + vs.flags &= (uint32)(^DPVS_SVC_F_SIP_HASH) + + vs.setFlags(DPVS_SVC_F_QID_HASH) +} + +func (vs *VirtualServerSpec) setFlags(flags uint32) { + vs.flags |= flags +} + +func (vs *VirtualServerSpec) GetFlags() uint32 { + return vs.flags +} + +func (vs *VirtualServerSpec) SetTimeout(t uint32) { + vs.timeout = t +} +func (vs *VirtualServerSpec) GetTimeout() uint32 { + return vs.timeout +} + +func (vs *VirtualServerSpec) SetConnTimeout(ct uint32) { + vs.connTimeout = ct +} + +func (vs *VirtualServerSpec) GetConnTimeout() uint32 { + return vs.connTimeout +} + +func (vs *VirtualServerSpec) SetNetMask(mask uint32) { + vs.netmask = mask +} + +func (vs *VirtualServerSpec) GetNetMask() uint32 { + return vs.netmask +} + +func (vs *VirtualServerSpec) SetBps(bps uint32) { + vs.bps = bps +} + +func (vs *VirtualServerSpec) GetBps() uint32 { + return vs.bps +} + +func (vs *VirtualServerSpec) SetLimitProportion(limit uint32) { + vs.limitProportion = limit +} + +func (vs *VirtualServerSpec) GetLimitProportion() uint32 { + return vs.limitProportion +} + +func (vs *VirtualServerSpec) SetNumDests(num uint32) { + vs.numDests = num +} + +func (vs *VirtualServerSpec) GetNumDests() uint32 { + return vs.numDests +} + +func (vs *VirtualServerSpec) SetNumLaddrs(num uint32) { + vs.numLaddrs = num +} + +func (vs *VirtualServerSpec) SetCid(cid uint64) { + vs.cid = cid +} + +func (vs *VirtualServerSpec) setNetmask(mask uint32) { + vs.netmask = mask +} + +func (vs *VirtualServerSpec) SetAddr(addr string) { + if strings.Contains(addr, ":") { + copy(vs.addr[:], net.ParseIP(addr)) + vs.af = unix.AF_INET6 + vs.setNetmask(128) + return + } + + vs.af = unix.AF_INET + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) + copy(vs.addr[:], buf.Bytes()[12:]) + vs.setNetmask(0xFFFFFFFF) +} + +func (vs *VirtualServerSpec) GetAddr() string { + var addr net.IP + + if vs.af == unix.AF_INET { + addr = net.IPv4(vs.addr[0], vs.addr[1], vs.addr[2], vs.addr[3]) + return addr.String() + } + + addr = net.IP{vs.addr[0x0], vs.addr[0x1], vs.addr[0x2], vs.addr[0x3], + vs.addr[0x4], vs.addr[0x5], vs.addr[0x6], vs.addr[0x7], + vs.addr[0x8], vs.addr[0x9], vs.addr[0xa], vs.addr[0xb], + vs.addr[0xc], vs.addr[0xd], vs.addr[0xe], vs.addr[0xf], + } + return addr.String() +} + +func (vs *VirtualServerSpec) GetSchedName() string { + return TrimRightZeros(string(vs.schedName[:])) +} + +func (vs *VirtualServerSpec) GetDestCheck() []models.DestCheckSpec { + var res []models.DestCheckSpec + if vs.hc.types&DPVS_DEST_HC_PASSIVE != 0 { + res = append(res, models.DestCheckSpecPassive) + } + if vs.hc.types&DPVS_DEST_HC_TCP != 0 { + res = append(res, models.DestCheckSpecTCP) + } + if vs.hc.types&DPVS_DEST_HC_UDP != 0 { + res = append(res, models.DestCheckSpecUDP) + } + if vs.hc.types&DPVS_DEST_HC_PING != 0 { + res = append(res, models.DestCheckSpecPing) + } + return res +} + +func (vs *VirtualServerSpec) SetSchedName(name string) { + sched := strings.ToLower(name) + + switch strings.ToLower(name) { + case "rr": + case "wlc": + case "conhash": + case "fo": + case "mh": + default: + sched = "wrr" + } + copy(vs.schedName[:], []byte(sched)) +} + +func (vs *VirtualServerSpec) SetMatch(m *dpvsMatch) { + vs.match.Copy(m) +} + +func (vs *VirtualServerSpec) SetStats(s *dpvsStats) { + vs.stats.Copy(s) +} + +func (vs *VirtualServerSpec) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*vs)) +} + +func (vs *VirtualServerSpec) ParseVipPortProto(vipport string) error { + items := strings.Split(vipport, "-") + if len(items) != 3 { + return errors.New("invalid vip-port-proto string") + } + + proto := items[2] + + switch strings.ToLower(proto) { + case "udp": + vs.proto = unix.IPPROTO_UDP + case "tcp": + fallthrough + default: + vs.proto = unix.IPPROTO_TCP + } + + // port := items[1] + port, err := strconv.Atoi(items[1]) + if err != nil { + return err + } + vs.SetPort(uint16(port)) + + vip := items[0] + if net.ParseIP(vip) == nil { + return errors.New(fmt.Sprintf("invalid ip addr: %s\n", vip)) + } + vs.SetAddr(vip) + + return nil +} + +func (vs *VirtualServerSpec) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*VirtualServerSpec, error) { + res := len % vs.Sizeof() + cnt := len / vs.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + err := errors.New("the buffer may not convert to VirtualServerSpec") + logger.Error("Read failed", "Error", err.Error()) + return nil, err + } + + vss := make([]*VirtualServerSpec, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(vs.Sizeof())) + if err != nil { + logger.Error("Read VirtualServerSpec() failed", "Error", err.Error()) + return nil, err + } + + vss[i] = NewVirtualServerSpec() + if !vss[i].Dump(buf) { + logger.Error("Dump byte as VirtualServerSpec failed") + return nil, errors.New("dump reply virtual server failed") + } + spec := *vss[i] + logger.Info("get virtual server success", "spec", spec) + } + + return vss, nil +} + +func (vs *VirtualServerSpec) Write(conn *pool.Conn) error { + buf := vs.Package() + + _, err := conn.WriteN(buf, int(vs.Sizeof())) + if err != nil { + return err + } + + return nil +} + +func (vs *VirtualServerSpec) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, vs) + return buf.Bytes() +} + +/***************** +******************/ + +func (front *VirtualServerFront) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*VirtualServerSpec, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVSAGENT_SO_GET_SERVICES, SOCKOPT_GET, front.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_SO_GET_SERVICEs Write proto header failed", "Error", err.Error()) + return nil, err + } + + err = front.Write(conn) + if err != nil { + logger.Error("Sockopt DPVSAGENT_SO_GET_SERVICEs Write proto bodyfailed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVSAGENT_SO_GET_SERVICEs Read proto header failed", "Error", err.Error()) + return nil, err + } + + if err := front.read(conn, logger); err != nil { + logger.Error("Sockopt DPVSAGENT_SO_GET_SERVICEs Read vss table header failed", "Error", err.Error()) + return nil, err + } + + vs := NewVirtualServerSpec() + return vs.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +func (vs *VirtualServerSpec) Get(cp *pool.ConnPool, parentLogger hclog.Logger) ([]*VirtualServerSpec, error) { + logger := hclog.Default().Named(vs.ID()) + if parentLogger != nil { + logger = parentLogger.Named(vs.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + msg := NewSockMsg(SOCKOPT_VERSION, DPVS_SO_GET_SERVICE, SOCKOPT_GET, vs.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_GET_SERVICE Write proto header failed", "Error", err.Error()) + return nil, err + } + + err = vs.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_GET_SERVICE Write proto body failed", "Error", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVS_SO_GET_SERVICE Read failed", "Error", err.Error()) + return nil, err + } + + return vs.read(conn, uint64(reply.GetLen()), logger) +} + +func (vs *VirtualServerSpec) Update(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(vs.ID()) + if parentLogger != nil { + logger = parentLogger.Named(vs.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVS_SO_SET_EDIT, SOCKOPT_SET, vs.Sizeof()) + + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_EDIT Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = vs.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_EDIT Write proto body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_EDIT Read failed", "Error", err.Error()) + return EDPVS_IO + } + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("DPVS_SO_SET_EDIT Done", "result", result) + return errCode +} + +func (vs *VirtualServerSpec) Add(cp *pool.ConnPool, parentLogger hclog.Logger) DpvsErrType { + logger := hclog.Default().Named(vs.ID()) + if parentLogger != nil { + logger = parentLogger.Named(vs.ID()) + } + + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVS_SO_SET_ADD, SOCKOPT_SET, vs.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_ADD Write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + err = vs.Write(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_ADD Write proto body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt DPVS_SO_SET_ADD Read failed", "Error", err.Error()) + return EDPVS_IO + } + errCode := reply.GetErrCode() + result := errCode.String() + + logger.Info("DPVS_SO_SET_ADD Done", "result", result) + return errCode +} + +func (vs *VirtualServerSpec) Del(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, DPVS_SO_SET_DEL, SOCKOPT_SET, vs.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt DPVS_SO_SET_DEL write proto header failed", "Error", err.Error()) + return EDPVS_IO + } + + if err := vs.Write(conn); err != nil { + logger.Error("Sockopt DPVS_SO_SET_DEL Write body failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt DPVS_SO_SET_DEL Read reply failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + + logger.Info("DPVS_SO_SET_DEL Done", "result", result) + return errCode +} diff --git a/tools/dpvs-agent/pkg/ipc/types/vlan.go b/tools/dpvs-agent/pkg/ipc/types/vlan.go new file mode 100644 index 000000000..ece83c0ef --- /dev/null +++ b/tools/dpvs-agent/pkg/ipc/types/vlan.go @@ -0,0 +1,312 @@ +package types + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "strings" + "unsafe" + + "github.com/hashicorp/go-hclog" + "golang.org/x/sys/unix" + + "github.com/dpvs-agent/pkg/ipc/pool" +) + +type VlanFront struct { + count uint32 +} + +func NewVlanFront() *VlanFront { + return &VlanFront{} +} + +func (o *VlanFront) GetCount() uint32 { + return o.count +} + +func (o *VlanFront) SetCount(c uint32) { + o.count = c +} + +func (o *VlanFront) Copy(src *VlanFront) bool { + o.count = src.count + return true +} + +func (o *VlanFront) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *VlanFront) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *VlanFront = *(**VlanFront)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *VlanFront) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *VlanFront) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*VlanFront, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to VlanFront") + } + + fronts := make([]*VlanFront, cnt) + + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + fronts[i] = NewVlanFront() + fronts[i].Dump(buf) + } + + return fronts, nil +} + +func (o *VlanFront) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +type VlanDevice struct { + realDev [0x10]byte + ifName [0x10]byte + proto uint16 + id uint16 +} + +func NewVlanDevice() *VlanDevice { + return &VlanDevice{proto: unix.ETH_P_8021Q} +} + +func (o *VlanDevice) Copy(src *VlanDevice) bool { + copy(o.realDev[:], src.realDev[:]) + copy(o.ifName[:], src.ifName[:]) + o.proto = src.proto + o.id = src.id + return true +} + +func (o *VlanDevice) Sizeof() uint64 { + return uint64(unsafe.Sizeof(*o)) +} + +func (o *VlanDevice) Dump(buf []byte) bool { + if len(buf) != int(o.Sizeof()) { + return false + } + + var tmp *VlanDevice = *(**VlanDevice)(unsafe.Pointer(&buf)) + + return o.Copy(tmp) +} + +func (o *VlanDevice) Package() []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, o) + return buf.Bytes() +} + +func (o *VlanDevice) SetRealDev(name string) { + copy(o.realDev[:], name[:]) +} + +func (o *VlanDevice) SetId(id uint16) { + o.id = id +} + +func (o *VlanDevice) SetIfName(name string) { + copy(o.ifName[:], name[:]) +} + +func (o *VlanDevice) SetProto(proto string) { + p := strings.ToLower(proto) + switch p { + case "vlan": + fallthrough + case "802.1q": + o.proto = unix.ETH_P_8021Q + case "qinq": + fallthrough + case "802.1ad": + o.proto = unix.ETH_P_8021AD + default: + } +} + +func (o *VlanDevice) ValidProto(proto string) bool { + // p := strings.ToLower(proto) + switch strings.ToLower(proto) { + case "vlan": + return true + case "802.1q": + return true + case "qinq": + return true + case "802.1ad": + return true + default: + return false + } + return false +} + +func (o *VlanDevice) read(conn *pool.Conn, len uint64, logger hclog.Logger) ([]*VlanDevice, error) { + res := len % o.Sizeof() + cnt := len / o.Sizeof() + if cnt <= 0 || res != 0 { + conn.Release(int(len)) + return nil, errors.New("Wrong buffer size to read, may not convert to VlanDevice") + } + + devices := make([]*VlanDevice, cnt) + for i := 0; i < int(cnt); i++ { + buf, err := conn.ReadN(int(o.Sizeof())) + if err != nil { + continue + } + devices[i] = NewVlanDevice() + devices[i].Dump(buf) + } + + return devices, nil +} + +func (o *VlanDevice) write(conn *pool.Conn, logger hclog.Logger) error { + buf := o.Package() + _, err := conn.WriteN(buf, int(o.Sizeof())) + if err != nil { + return err + } + return nil +} + +/**************** +****************/ +func (o *VlanDevice) Get(cp *pool.ConnPool, logger hclog.Logger) ([]*VlanDevice, error) { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return nil, err + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, SOCKOPT_GET_VLAN_SHOW, SOCKOPT_GET, o.Sizeof()) + if err := msg.Write(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_VLAN_SHOW Write proto header Error:", err.Error()) + return nil, err + } + + if err := o.write(conn, logger); err != nil { + logger.Error("Sockopt SOCKOPT_GET_VLAN_SHOW write specific vlan Error:", err.Error()) + return nil, err + } + + reply := NewReplySockMsg() + if err := reply.Read(conn); err != nil { + logger.Error("Sockopt SOCKOPT_GET_VLAN_SHOW reply msg Read failed:", err.Error()) + return nil, err + } + + if reply.GetErrCode() != EDPVS_OK { + err = fmt.Errorf("Sockopt SOCKOPT_GET_VLAN_SHOW reply ErrorCode: %s", reply.GetErrStr()) + logger.Error(err.Error()) + return nil, err + } + + front := VlanFront{} + _, err = front.read(conn, front.Sizeof(), logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_GET_VLAN_SHOW read table header failed:", err.Error()) + return nil, err + } + + return o.read(conn, uint64(reply.GetLen())-front.Sizeof(), logger) +} + +func (o *VlanDevice) Add(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed", "Error", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, SOCKOPT_SET_VLAN_ADD, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_ADD Write proto header Error failed", "Error", err.Error()) + return EDPVS_IO + } + + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_ADD write specific vlan Error failed", "Error", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_ADD reply msg Read failed", "Error", err.Error()) + return EDPVS_IO + } + + errCode := reply.GetErrCode() + result := errCode.String() + logger.Info("Sockopt SOCKOPT_SET_VLAN_ADD Done", "result", result) + return errCode +} + +func (o *VlanDevice) Del(cp *pool.ConnPool, logger hclog.Logger) DpvsErrType { + ctx := context.Background() + conn, err := cp.Get(ctx) + if err != nil { + logger.Error("Get conn from pool failed:", err.Error()) + return EDPVS_IO + } + defer cp.Remove(ctx, conn, nil) + + msg := NewSockMsg(SOCKOPT_VERSION, SOCKOPT_SET_VLAN_DEL, SOCKOPT_SET, o.Sizeof()) + err = msg.Write(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_DEL Write proto header Error:", err.Error()) + return EDPVS_IO + } + + err = o.write(conn, logger) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_DEL write specific vlan Error:", err.Error()) + return EDPVS_IO + } + + reply := NewReplySockMsg() + err = reply.Read(conn) + if err != nil { + logger.Error("Sockopt SOCKOPT_SET_VLAN_DEL reply msg Read failed:", err.Error()) + return EDPVS_IO + } + + return reply.GetErrCode() +} diff --git a/tools/dpvs-agent/restapi/configure_dpvs_agent.go b/tools/dpvs-agent/restapi/configure_dpvs_agent.go new file mode 100644 index 000000000..f37abf18a --- /dev/null +++ b/tools/dpvs-agent/restapi/configure_dpvs_agent.go @@ -0,0 +1,172 @@ +// This file is safe to edit. Once it exists it will not be overwritten + +package restapi + +import ( + "crypto/tls" + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + + "github.com/dpvs-agent/restapi/operations" + "github.com/dpvs-agent/restapi/operations/device" + "github.com/dpvs-agent/restapi/operations/virtualserver" +) + +//go:generate swagger generate server --target ../../dpvs-agent --name DpvsAgent --spec ../dpvs-agent-api.yaml --principal interface{} + +func configureFlags(api *operations.DpvsAgentAPI) { + // api.CommandLineOptionsGroups = []swag.CommandLineOptionsGroup{ ... } +} + +func configureAPI(api *operations.DpvsAgentAPI) http.Handler { + // configure the api here + api.ServeError = errors.ServeError + + // Set your custom logger if needed. Default one is log.Printf + // Expected interface func(string, ...interface{}) + // + // Example: + // api.Logger = log.Printf + + api.UseSwaggerUI() + // To continue using redoc as your UI, uncomment the following line + // api.UseRedoc() + + api.JSONConsumer = runtime.JSONConsumer() + + api.JSONProducer = runtime.JSONProducer() + + if api.DeviceDeleteDeviceNameAddrHandler == nil { + api.DeviceDeleteDeviceNameAddrHandler = device.DeleteDeviceNameAddrHandlerFunc(func(params device.DeleteDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameAddr has not yet been implemented") + }) + } + if api.DeviceDeleteDeviceNameRouteHandler == nil { + api.DeviceDeleteDeviceNameRouteHandler = device.DeleteDeviceNameRouteHandlerFunc(func(params device.DeleteDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameRoute has not yet been implemented") + }) + } + if api.DeviceDeleteDeviceNameVlanHandler == nil { + api.DeviceDeleteDeviceNameVlanHandler = device.DeleteDeviceNameVlanHandlerFunc(func(params device.DeleteDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameVlan has not yet been implemented") + }) + } + if api.VirtualserverDeleteVsVipPortHandler == nil { + api.VirtualserverDeleteVsVipPortHandler = virtualserver.DeleteVsVipPortHandlerFunc(func(params virtualserver.DeleteVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPort has not yet been implemented") + }) + } + if api.VirtualserverDeleteVsVipPortLaddrHandler == nil { + api.VirtualserverDeleteVsVipPortLaddrHandler = virtualserver.DeleteVsVipPortLaddrHandlerFunc(func(params virtualserver.DeleteVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortLaddr has not yet been implemented") + }) + } + if api.VirtualserverDeleteVsVipPortRsHandler == nil { + api.VirtualserverDeleteVsVipPortRsHandler = virtualserver.DeleteVsVipPortRsHandlerFunc(func(params virtualserver.DeleteVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortRs has not yet been implemented") + }) + } + if api.DeviceGetDeviceHandler == nil { + api.DeviceGetDeviceHandler = device.GetDeviceHandlerFunc(func(params device.GetDeviceParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDevice has not yet been implemented") + }) + } + if api.DeviceGetDeviceNameAddrHandler == nil { + api.DeviceGetDeviceNameAddrHandler = device.GetDeviceNameAddrHandlerFunc(func(params device.GetDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameAddr has not yet been implemented") + }) + } + if api.DeviceGetDeviceNameRouteHandler == nil { + api.DeviceGetDeviceNameRouteHandler = device.GetDeviceNameRouteHandlerFunc(func(params device.GetDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameRoute has not yet been implemented") + }) + } + if api.DeviceGetDeviceNameVlanHandler == nil { + api.DeviceGetDeviceNameVlanHandler = device.GetDeviceNameVlanHandlerFunc(func(params device.GetDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameVlan has not yet been implemented") + }) + } + if api.VirtualserverGetVsHandler == nil { + api.VirtualserverGetVsHandler = virtualserver.GetVsHandlerFunc(func(params virtualserver.GetVsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVs has not yet been implemented") + }) + } + if api.VirtualserverGetVsVipPortHandler == nil { + api.VirtualserverGetVsVipPortHandler = virtualserver.GetVsVipPortHandlerFunc(func(params virtualserver.GetVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPort has not yet been implemented") + }) + } + if api.VirtualserverGetVsVipPortLaddrHandler == nil { + api.VirtualserverGetVsVipPortLaddrHandler = virtualserver.GetVsVipPortLaddrHandlerFunc(func(params virtualserver.GetVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortLaddr has not yet been implemented") + }) + } + if api.VirtualserverGetVsVipPortRsHandler == nil { + api.VirtualserverGetVsVipPortRsHandler = virtualserver.GetVsVipPortRsHandlerFunc(func(params virtualserver.GetVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortRs has not yet been implemented") + }) + } + if api.DevicePutDeviceNameAddrHandler == nil { + api.DevicePutDeviceNameAddrHandler = device.PutDeviceNameAddrHandlerFunc(func(params device.PutDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameAddr has not yet been implemented") + }) + } + if api.DevicePutDeviceNameRouteHandler == nil { + api.DevicePutDeviceNameRouteHandler = device.PutDeviceNameRouteHandlerFunc(func(params device.PutDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameRoute has not yet been implemented") + }) + } + if api.DevicePutDeviceNameVlanHandler == nil { + api.DevicePutDeviceNameVlanHandler = device.PutDeviceNameVlanHandlerFunc(func(params device.PutDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameVlan has not yet been implemented") + }) + } + if api.VirtualserverPutVsVipPortHandler == nil { + api.VirtualserverPutVsVipPortHandler = virtualserver.PutVsVipPortHandlerFunc(func(params virtualserver.PutVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPort has not yet been implemented") + }) + } + if api.VirtualserverPutVsVipPortLaddrHandler == nil { + api.VirtualserverPutVsVipPortLaddrHandler = virtualserver.PutVsVipPortLaddrHandlerFunc(func(params virtualserver.PutVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortLaddr has not yet been implemented") + }) + } + if api.VirtualserverPutVsVipPortRsHandler == nil { + api.VirtualserverPutVsVipPortRsHandler = virtualserver.PutVsVipPortRsHandlerFunc(func(params virtualserver.PutVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortRs has not yet been implemented") + }) + } + + api.PreServerShutdown = func() {} + + api.ServerShutdown = func() {} + + return setupGlobalMiddleware(api.Serve(setupMiddlewares)) +} + +// The TLS configuration before HTTPS server starts. +func configureTLS(tlsConfig *tls.Config) { + // Make all necessary changes to the TLS configuration here. +} + +// As soon as server is initialized but not run yet, this function will be called. +// If you need to modify a config, store server instance to stop it individually later, this is the place. +// This function can be called multiple times, depending on the number of serving schemes. +// scheme value will be set accordingly: "http", "https" or "unix". +func configureServer(s *http.Server, scheme, addr string) { +} + +// The middleware configuration is for the handler executors. These do not apply to the swagger.json document. +// The middleware executes after routing but before authentication, binding and validation. +func setupMiddlewares(handler http.Handler) http.Handler { + return handler +} + +// The middleware configuration happens before anything, this middleware also applies to serving the swagger.json document. +// So this is a good place to plug in a panic handling middleware, logging and metrics. +func setupGlobalMiddleware(handler http.Handler) http.Handler { + return handler +} diff --git a/tools/dpvs-agent/restapi/doc.go b/tools/dpvs-agent/restapi/doc.go new file mode 100644 index 000000000..d70edbc94 --- /dev/null +++ b/tools/dpvs-agent/restapi/doc.go @@ -0,0 +1,19 @@ +// Code generated by go-swagger; DO NOT EDIT. + +// Package restapi dpvs agent +// +// dpvs agent api +// Schemes: +// http +// Host: petstore.swagger.io +// BasePath: /v2 +// Version: 1.0.0 +// +// Consumes: +// - application/json +// +// Produces: +// - application/json +// +// swagger:meta +package restapi diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go new file mode 100644 index 000000000..488b7f0fe --- /dev/null +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -0,0 +1,4449 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package restapi + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "encoding/json" +) + +var ( + // SwaggerJSON embedded version of the swagger document used at generation time + SwaggerJSON json.RawMessage + // FlatSwaggerJSON embedded flattened version of the swagger document used at generation time + FlatSwaggerJSON json.RawMessage +) + +func init() { + SwaggerJSON = json.RawMessage([]byte(`{ + "schemes": [ + "http" + ], + "swagger": "2.0", + "info": { + "description": "dpvs agent api", + "title": "dpvs agent", + "version": "1.0.0" + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "paths": { + "/device": { + "get": { + "tags": [ + "device" + ], + "summary": "display all net device list", + "parameters": [ + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/addr": { + "get": { + "tags": [ + "device" + ], + "summary": "display special net device ip addr", + "parameters": [ + { + "$ref": "#/parameters/stats" + }, + { + "$ref": "#/parameters/verbose" + }, + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device ip addr", + "parameters": [ + { + "$ref": "#/parameters/sapool" + }, + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/device-addr" + } + ], + "responses": { + "200": { + "description": "Update exist ip addr Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Add new ip addr Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device ip addr", + "parameters": [ + { + "$ref": "#/parameters/sapool" + }, + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/device-addr" + } + ], + "responses": { + "200": { + "description": "delete ip addr from device Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/netlink": { + "get": { + "tags": [ + "device" + ], + "summary": "ip link show dev ${name}", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "ip link set ${name} up", + "parameters": [ + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "ip link set ${name} down", + "parameters": [ + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/netlink/addr": { + "get": { + "tags": [ + "device" + ], + "summary": "display special linux net device addr detail", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "set ip cird to linux net device", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/device-addr" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete ip cird fron linux net device", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/device-addr" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/nic": { + "get": { + "tags": [ + "device" + ], + "summary": "dpip link show ${nic-name} -s -v", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/verbose" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/NicDeviceSpecList" + } + }, + "500": { + "description": "Failure", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "dpip link set ${nic-name} [forward2kni,link,promisc,tc-ingress,tc-egress] [on/up,off/down]", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/forward2kni" + }, + { + "$ref": "#/parameters/link" + }, + { + "$ref": "#/parameters/promisc" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failure", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/route": { + "get": { + "tags": [ + "device" + ], + "summary": "display special net device route", + "parameters": [ + { + "$ref": "#/parameters/stats" + }, + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device route", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/route-config" + } + ], + "responses": { + "200": { + "description": "Update exist route Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Add new route Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device route", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/route-config" + } + ], + "responses": { + "200": { + "description": "delete route Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/vlan": { + "get": { + "tags": [ + "device" + ], + "summary": "display all net device list", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device ", + "parameters": [ + { + "$ref": "#/parameters/device-name" + }, + { + "$ref": "#/parameters/vlan-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device", + "parameters": [ + { + "$ref": "#/parameters/device-name" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/vs": { + "get": { + "tags": [ + "virtualserver" + ], + "summary": "display all vip:port:proto and rsip:port list", + "parameters": [ + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/VirtualServerList" + } + } + } + } + }, + "/vs/{VipPort}": { + "get": { + "tags": [ + "virtualserver" + ], + "summary": "get a specific virtual server", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/VirtualServerList" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "create or update virtual server", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/vs-config" + } + ], + "responses": { + "200": { + "description": "Updated", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/allow": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of ip from white list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update a fully white ip list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of ip form white list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/deny": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of ip from black list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update a fully black ip list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of ip form black list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/acl-config" + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/laddr": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/LocalAddressExpandList" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/laddr-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/laddr-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/rs": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/stats" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of real server to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/rss-config" + }, + { + "$ref": "#/parameters/healthcheck" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update fully real server list to vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/rss-config" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of real server from vip:port:proto", + "parameters": [ + { + "$ref": "#/parameters/service-id" + }, + { + "$ref": "#/parameters/rss-config" + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + } + }, + "definitions": { + "AclAddrList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/CertAuthSpec" + } + } + } + }, + "AddrRange": { + "type": "object", + "properties": { + "End": { + "type": "string" + }, + "Start": { + "type": "string" + } + } + }, + "CertAuthSpec": { + "properties": { + "addr": { + "type": "string" + } + } + }, + "DestCheckSpec": { + "type": "string", + "enum": [ + "passive", + "tcp", + "udp", + "ping" + ] + }, + "Error": { + "type": "string" + }, + "InetAddrSpec": { + "properties": { + "addr": { + "type": "string" + }, + "broadcast": { + "type": "string" + }, + "scope": { + "type": "string" + } + } + }, + "LocalAddressExpandList": { + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/LocalAddressSpecExpand" + } + } + } + }, + "LocalAddressSpecExpand": { + "type": "object", + "properties": { + "addr": { + "type": "string" + }, + "af": { + "type": "integer", + "format": "uint32" + }, + "conns": { + "type": "integer", + "format": "uint32" + }, + "device": { + "type": "string" + }, + "portConflict": { + "type": "integer", + "format": "uint64" + } + } + }, + "LocalAddressSpecTiny": { + "properties": { + "addr": { + "type": "string" + }, + "device": { + "type": "string" + } + } + }, + "LocalAddressTinyList": { + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + } + } + }, + "MatchSpec": { + "type": "object", + "properties": { + "Dest": { + "$ref": "#/definitions/AddrRange" + }, + "InIfName": { + "type": "string" + }, + "OutIfName": { + "type": "string" + }, + "Src": { + "$ref": "#/definitions/AddrRange" + } + } + }, + "NicDeviceDetail": { + "type": "object", + "properties": { + "Flags": { + "type": "integer", + "format": "uint16" + }, + "ID": { + "type": "integer", + "format": "uint16" + }, + "MTU": { + "type": "integer", + "format": "uint16" + }, + "addr": { + "type": "string" + }, + "autoneg": { + "type": "string", + "enum": [ + "fixed-nego", + "auto-nego" + ] + }, + "duplex": { + "type": "string", + "enum": [ + "half-duplex", + "full-duplex" + ] + }, + "nRxQ": { + "type": "integer", + "format": "uint8" + }, + "nTxQ": { + "type": "integer", + "format": "uint8" + }, + "name": { + "type": "string" + }, + "socketID": { + "type": "integer", + "format": "uint8" + }, + "speed": { + "type": "integer", + "format": "uint32" + }, + "status": { + "type": "string", + "enum": [ + "UP", + "DOWN" + ] + } + } + }, + "NicDeviceQueueData": { + "type": "integer", + "format": "uint64" + }, + "NicDeviceSpec": { + "type": "object", + "properties": { + "detail": { + "$ref": "#/definitions/NicDeviceDetail" + }, + "stats": { + "$ref": "#/definitions/NicDeviceStats" + } + } + }, + "NicDeviceSpecList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceSpec" + } + } + } + }, + "NicDeviceStats": { + "type": "object", + "properties": { + "bufAvail": { + "type": "integer", + "format": "uint32" + }, + "bufInuse": { + "type": "integer", + "format": "uint32" + }, + "errorBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "id": { + "type": "integer", + "format": "uint16" + }, + "inBytes": { + "type": "integer", + "format": "uint64" + }, + "inBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "inErrors": { + "type": "integer", + "format": "uint64" + }, + "inMissed": { + "type": "integer", + "format": "uint64" + }, + "inPkts": { + "type": "integer", + "format": "uint64" + }, + "inPktsQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "outBytes": { + "type": "integer", + "format": "uint64" + }, + "outBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "outErrors": { + "type": "integer", + "format": "uint64" + }, + "outPkts": { + "type": "integer", + "format": "uint64" + }, + "outPktsQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "rxNoMbuf": { + "type": "integer", + "format": "uint64" + } + } + }, + "RealServerExpandList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/RealServerSpecExpand" + } + } + } + }, + "RealServerSpecExpand": { + "type": "object", + "properties": { + "Spec": { + "$ref": "#/definitions/RealServerSpecTiny" + }, + "Stats": { + "$ref": "#/definitions/ServerStats" + } + } + }, + "RealServerSpecTiny": { + "type": "object", + "properties": { + "inhibited": { + "type": "boolean", + "default": false + }, + "ip": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": [ + "FNAT", + "SNAT", + "DR", + "TUNNEL", + "NAT" + ] + }, + "overloaded": { + "type": "boolean", + "default": false + }, + "port": { + "type": "integer", + "format": "uint16", + "x-omitempty": false + }, + "weight": { + "type": "integer", + "format": "uint16", + "x-omitempty": false + } + } + }, + "RealServerTinyList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/RealServerSpecTiny" + } + } + } + }, + "RouteSpec": { + "properties": { + "device": { + "type": "string" + }, + "dst": { + "type": "string" + }, + "gateway": { + "type": "string" + }, + "metric": { + "type": "integer", + "format": "uint32" + }, + "mtu": { + "type": "integer", + "format": "uint32" + }, + "prefixSrc": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "src": { + "type": "string" + } + } + }, + "ServerStats": { + "type": "object", + "properties": { + "Conns": { + "type": "integer", + "format": "uint64" + }, + "Cps": { + "type": "integer", + "format": "uint32" + }, + "InBps": { + "type": "integer", + "format": "uint32" + }, + "InBytes": { + "type": "integer", + "format": "uint64" + }, + "InPkts": { + "type": "integer", + "format": "uint64" + }, + "InPps": { + "type": "integer", + "format": "uint32" + }, + "OutBps": { + "type": "integer", + "format": "uint32" + }, + "OutBytes": { + "type": "integer", + "format": "uint64" + }, + "OutPkts": { + "type": "integer", + "format": "uint64" + }, + "OutPps": { + "type": "integer", + "format": "uint32" + } + } + }, + "Status": { + "description": "Status of an individual component", + "type": "object", + "properties": { + "msg": { + "description": "Human readable status/error/warning message", + "type": "string" + }, + "state": { + "description": "State the component is in", + "type": "string", + "enum": [ + "Ok", + "Warning", + "Failure", + "Disabled" + ] + } + } + }, + "VirtualServerList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/VirtualServerSpecExpand" + } + } + } + }, + "VirtualServerSpecExpand": { + "type": "object", + "properties": { + "Addr": { + "type": "string" + }, + "Af": { + "type": "integer", + "format": "uint32" + }, + "Bps": { + "type": "integer", + "format": "uint32" + }, + "ConnTimeout": { + "type": "integer", + "format": "uint32" + }, + "DestCheck": { + "type": "array", + "items": { + "$ref": "#/definitions/DestCheckSpec" + } + }, + "ExpireQuiescent": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "Flags": { + "type": "string" + }, + "Fwmark": { + "type": "integer", + "format": "uint32" + }, + "LimitProportion": { + "type": "integer", + "format": "uint32" + }, + "Match": { + "$ref": "#/definitions/MatchSpec" + }, + "Netmask": { + "type": "integer", + "format": "uint32" + }, + "Port": { + "type": "integer", + "format": "uint16" + }, + "Proto": { + "type": "integer", + "format": "uint16" + }, + "RSs": { + "$ref": "#/definitions/RealServerExpandList" + }, + "SchedName": { + "type": "string", + "enum": [ + "rr", + "wrr", + "wlc", + "connhash" + ] + }, + "Stats": { + "$ref": "#/definitions/ServerStats" + }, + "SyncProxy": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "Timeout": { + "type": "integer", + "format": "uint32" + } + } + }, + "VirtualServerSpecTiny": { + "type": "object", + "properties": { + "Bps": { + "type": "integer", + "format": "uint32" + }, + "ConnTimeout": { + "type": "integer", + "format": "uint32" + }, + "ExpireQuiescent": { + "type": "boolean", + "default": false + }, + "Fwmark": { + "type": "integer", + "format": "uint32" + }, + "LimitProportion": { + "type": "integer", + "format": "uint32" + }, + "Match": { + "$ref": "#/definitions/MatchSpec" + }, + "SchedName": { + "type": "string", + "enum": [ + "rr", + "wrr", + "wlc", + "connhash" + ] + }, + "SyncProxy": { + "type": "boolean", + "default": false + }, + "Timeout": { + "type": "integer", + "format": "uint32" + } + } + }, + "VlanSpec": { + "properties": { + "device": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + }, + "parameters": { + "acl-config": { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + }, + "device-addr": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + }, + "device-name": { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + "forward2kni": { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "forward2Kni", + "in": "query" + }, + "healthcheck": { + "type": "boolean", + "default": false, + "name": "healthcheck", + "in": "query" + }, + "laddr-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + }, + "link": { + "enum": [ + "unset", + "up", + "down" + ], + "type": "string", + "default": "unset", + "name": "link", + "in": "query" + }, + "promisc": { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "promisc", + "in": "query" + }, + "realserver-id": { + "type": "string", + "name": "RipPort", + "in": "path", + "required": true + }, + "route-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RouteSpec" + } + }, + "rs-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerSpecTiny" + } + }, + "rss-config": { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + }, + "sapool": { + "type": "boolean", + "default": false, + "name": "sapool", + "in": "query" + }, + "service-id": { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + "stats": { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + }, + "verbose": { + "type": "boolean", + "default": false, + "name": "verbose", + "in": "query" + }, + "vlan-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VlanSpec" + } + }, + "vs-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VirtualServerSpecTiny" + } + } + }, + "tags": [ + { + "description": "virtualserver", + "name": "virtualserver" + }, + { + "description": "route", + "name": "route" + }, + { + "description": "laddr", + "name": "laddr" + }, + { + "description": "tunnel", + "name": "tunnel" + }, + { + "description": "inet addr", + "name": "inetaddr" + }, + { + "description": "white list", + "name": "white_list" + }, + { + "description": "black list", + "name": "black_list" + }, + { + "description": "arp", + "name": "arp" + } + ] +}`)) + FlatSwaggerJSON = json.RawMessage([]byte(`{ + "schemes": [ + "http" + ], + "swagger": "2.0", + "info": { + "description": "dpvs agent api", + "title": "dpvs agent", + "version": "1.0.0" + }, + "host": "petstore.swagger.io", + "basePath": "/v2", + "paths": { + "/device": { + "get": { + "tags": [ + "device" + ], + "summary": "display all net device list", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/addr": { + "get": { + "tags": [ + "device" + ], + "summary": "display special net device ip addr", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + }, + { + "type": "boolean", + "default": false, + "name": "verbose", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device ip addr", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "sapool", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + } + ], + "responses": { + "200": { + "description": "Update exist ip addr Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Add new ip addr Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device ip addr", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "sapool", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + } + ], + "responses": { + "200": { + "description": "delete ip addr from device Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/netlink": { + "get": { + "tags": [ + "device" + ], + "summary": "ip link show dev ${name}", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "ip link set ${name} up", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "ip link set ${name} down", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/netlink/addr": { + "get": { + "tags": [ + "device" + ], + "summary": "display special linux net device addr detail", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "set ip cird to linux net device", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete ip cird fron linux net device", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/nic": { + "get": { + "tags": [ + "device" + ], + "summary": "dpip link show ${nic-name} -s -v", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "verbose", + "in": "query" + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/NicDeviceSpecList" + } + }, + "500": { + "description": "Failure", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "dpip link set ${nic-name} [forward2kni,link,promisc,tc-ingress,tc-egress] [on/up,off/down]", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "forward2Kni", + "in": "query" + }, + { + "enum": [ + "unset", + "up", + "down" + ], + "type": "string", + "default": "unset", + "name": "link", + "in": "query" + }, + { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "promisc", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failure", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/route": { + "get": { + "tags": [ + "device" + ], + "summary": "display special net device route", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + }, + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device route", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RouteSpec" + } + } + ], + "responses": { + "200": { + "description": "Update exist route Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Add new route Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device route", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RouteSpec" + } + } + ], + "responses": { + "200": { + "description": "delete route Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/device/{name}/vlan": { + "get": { + "tags": [ + "device" + ], + "summary": "display all net device list", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "device" + ], + "summary": "add/update special net device ", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VlanSpec" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + }, + "delete": { + "tags": [ + "device" + ], + "summary": "delete special net device", + "parameters": [ + { + "type": "string", + "name": "name", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Failed", + "schema": { + "type": "string" + } + } + } + } + }, + "/vs": { + "get": { + "tags": [ + "virtualserver" + ], + "summary": "display all vip:port:proto and rsip:port list", + "parameters": [ + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/VirtualServerList" + } + } + } + } + }, + "/vs/{VipPort}": { + "get": { + "tags": [ + "virtualserver" + ], + "summary": "get a specific virtual server", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/VirtualServerList" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "create or update virtual server", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VirtualServerSpecTiny" + } + } + ], + "responses": { + "200": { + "description": "Updated", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/allow": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of ip from white list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update a fully white ip list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of ip form white list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/deny": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of ip from black list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update a fully black ip list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of ip form black list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/laddr": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "$ref": "#/definitions/LocalAddressExpandList" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Error while creating virtual server", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + }, + "/vs/{VipPort}/rs": { + "get": { + "tags": [ + "virtualserver" + ], + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + } + } + }, + "put": { + "tags": [ + "virtualserver" + ], + "summary": "Add a set of real server to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + }, + { + "type": "boolean", + "default": false, + "name": "healthcheck", + "in": "query" + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "post": { + "tags": [ + "virtualserver" + ], + "summary": "Update fully real server list to vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + } + ], + "responses": { + "200": { + "description": "Success", + "schema": { + "type": "string" + } + }, + "201": { + "description": "Created", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + }, + "delete": { + "tags": [ + "virtualserver" + ], + "summary": "Delete a set of real server from vip:port:proto", + "parameters": [ + { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + } + ], + "responses": { + "200": { + "description": "Success" + }, + "404": { + "description": "Service not found", + "schema": { + "type": "string" + } + }, + "460": { + "description": "Invalid frontend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidFrontend" + }, + "461": { + "description": "Invalid backend in service configuration", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "InvalidBackend" + }, + "500": { + "description": "Service deletion failed", + "schema": { + "$ref": "#/definitions/Error" + }, + "x-go-name": "Failure" + } + } + } + } + }, + "definitions": { + "AclAddrList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/CertAuthSpec" + } + } + } + }, + "AddrRange": { + "type": "object", + "properties": { + "End": { + "type": "string" + }, + "Start": { + "type": "string" + } + } + }, + "CertAuthSpec": { + "properties": { + "addr": { + "type": "string" + } + } + }, + "DestCheckSpec": { + "type": "string", + "enum": [ + "passive", + "tcp", + "udp", + "ping" + ] + }, + "Error": { + "type": "string" + }, + "InetAddrSpec": { + "properties": { + "addr": { + "type": "string" + }, + "broadcast": { + "type": "string" + }, + "scope": { + "type": "string" + } + } + }, + "LocalAddressExpandList": { + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/LocalAddressSpecExpand" + } + } + } + }, + "LocalAddressSpecExpand": { + "type": "object", + "properties": { + "addr": { + "type": "string" + }, + "af": { + "type": "integer", + "format": "uint32" + }, + "conns": { + "type": "integer", + "format": "uint32" + }, + "device": { + "type": "string" + }, + "portConflict": { + "type": "integer", + "format": "uint64" + } + } + }, + "LocalAddressSpecTiny": { + "properties": { + "addr": { + "type": "string" + }, + "device": { + "type": "string" + } + } + }, + "LocalAddressTinyList": { + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + } + } + }, + "MatchSpec": { + "type": "object", + "properties": { + "Dest": { + "$ref": "#/definitions/AddrRange" + }, + "InIfName": { + "type": "string" + }, + "OutIfName": { + "type": "string" + }, + "Src": { + "$ref": "#/definitions/AddrRange" + } + } + }, + "NicDeviceDetail": { + "type": "object", + "properties": { + "Flags": { + "type": "integer", + "format": "uint16" + }, + "ID": { + "type": "integer", + "format": "uint16" + }, + "MTU": { + "type": "integer", + "format": "uint16" + }, + "addr": { + "type": "string" + }, + "autoneg": { + "type": "string", + "enum": [ + "fixed-nego", + "auto-nego" + ] + }, + "duplex": { + "type": "string", + "enum": [ + "half-duplex", + "full-duplex" + ] + }, + "nRxQ": { + "type": "integer", + "format": "uint8" + }, + "nTxQ": { + "type": "integer", + "format": "uint8" + }, + "name": { + "type": "string" + }, + "socketID": { + "type": "integer", + "format": "uint8" + }, + "speed": { + "type": "integer", + "format": "uint32" + }, + "status": { + "type": "string", + "enum": [ + "UP", + "DOWN" + ] + } + } + }, + "NicDeviceQueueData": { + "type": "integer", + "format": "uint64" + }, + "NicDeviceSpec": { + "type": "object", + "properties": { + "detail": { + "$ref": "#/definitions/NicDeviceDetail" + }, + "stats": { + "$ref": "#/definitions/NicDeviceStats" + } + } + }, + "NicDeviceSpecList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceSpec" + } + } + } + }, + "NicDeviceStats": { + "type": "object", + "properties": { + "bufAvail": { + "type": "integer", + "format": "uint32" + }, + "bufInuse": { + "type": "integer", + "format": "uint32" + }, + "errorBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "id": { + "type": "integer", + "format": "uint16" + }, + "inBytes": { + "type": "integer", + "format": "uint64" + }, + "inBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "inErrors": { + "type": "integer", + "format": "uint64" + }, + "inMissed": { + "type": "integer", + "format": "uint64" + }, + "inPkts": { + "type": "integer", + "format": "uint64" + }, + "inPktsQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "outBytes": { + "type": "integer", + "format": "uint64" + }, + "outBytesQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "outErrors": { + "type": "integer", + "format": "uint64" + }, + "outPkts": { + "type": "integer", + "format": "uint64" + }, + "outPktsQ": { + "type": "array", + "items": { + "$ref": "#/definitions/NicDeviceQueueData" + } + }, + "rxNoMbuf": { + "type": "integer", + "format": "uint64" + } + } + }, + "RealServerExpandList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/RealServerSpecExpand" + } + } + } + }, + "RealServerSpecExpand": { + "type": "object", + "properties": { + "Spec": { + "$ref": "#/definitions/RealServerSpecTiny" + }, + "Stats": { + "$ref": "#/definitions/ServerStats" + } + } + }, + "RealServerSpecTiny": { + "type": "object", + "properties": { + "inhibited": { + "type": "boolean", + "default": false + }, + "ip": { + "type": "string" + }, + "mode": { + "type": "string", + "enum": [ + "FNAT", + "SNAT", + "DR", + "TUNNEL", + "NAT" + ] + }, + "overloaded": { + "type": "boolean", + "default": false + }, + "port": { + "type": "integer", + "format": "uint16", + "x-omitempty": false + }, + "weight": { + "type": "integer", + "format": "uint16", + "x-omitempty": false + } + } + }, + "RealServerTinyList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/RealServerSpecTiny" + } + } + } + }, + "RouteSpec": { + "properties": { + "device": { + "type": "string" + }, + "dst": { + "type": "string" + }, + "gateway": { + "type": "string" + }, + "metric": { + "type": "integer", + "format": "uint32" + }, + "mtu": { + "type": "integer", + "format": "uint32" + }, + "prefixSrc": { + "type": "string" + }, + "scope": { + "type": "string" + }, + "src": { + "type": "string" + } + } + }, + "ServerStats": { + "type": "object", + "properties": { + "Conns": { + "type": "integer", + "format": "uint64" + }, + "Cps": { + "type": "integer", + "format": "uint32" + }, + "InBps": { + "type": "integer", + "format": "uint32" + }, + "InBytes": { + "type": "integer", + "format": "uint64" + }, + "InPkts": { + "type": "integer", + "format": "uint64" + }, + "InPps": { + "type": "integer", + "format": "uint32" + }, + "OutBps": { + "type": "integer", + "format": "uint32" + }, + "OutBytes": { + "type": "integer", + "format": "uint64" + }, + "OutPkts": { + "type": "integer", + "format": "uint64" + }, + "OutPps": { + "type": "integer", + "format": "uint32" + } + } + }, + "Status": { + "description": "Status of an individual component", + "type": "object", + "properties": { + "msg": { + "description": "Human readable status/error/warning message", + "type": "string" + }, + "state": { + "description": "State the component is in", + "type": "string", + "enum": [ + "Ok", + "Warning", + "Failure", + "Disabled" + ] + } + } + }, + "VirtualServerList": { + "type": "object", + "properties": { + "Items": { + "type": "array", + "items": { + "$ref": "#/definitions/VirtualServerSpecExpand" + } + } + } + }, + "VirtualServerSpecExpand": { + "type": "object", + "properties": { + "Addr": { + "type": "string" + }, + "Af": { + "type": "integer", + "format": "uint32" + }, + "Bps": { + "type": "integer", + "format": "uint32" + }, + "ConnTimeout": { + "type": "integer", + "format": "uint32" + }, + "DestCheck": { + "type": "array", + "items": { + "$ref": "#/definitions/DestCheckSpec" + } + }, + "ExpireQuiescent": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "Flags": { + "type": "string" + }, + "Fwmark": { + "type": "integer", + "format": "uint32" + }, + "LimitProportion": { + "type": "integer", + "format": "uint32" + }, + "Match": { + "$ref": "#/definitions/MatchSpec" + }, + "Netmask": { + "type": "integer", + "format": "uint32" + }, + "Port": { + "type": "integer", + "format": "uint16" + }, + "Proto": { + "type": "integer", + "format": "uint16" + }, + "RSs": { + "$ref": "#/definitions/RealServerExpandList" + }, + "SchedName": { + "type": "string", + "enum": [ + "rr", + "wrr", + "wlc", + "connhash" + ] + }, + "Stats": { + "$ref": "#/definitions/ServerStats" + }, + "SyncProxy": { + "type": "string", + "enum": [ + "true", + "false" + ] + }, + "Timeout": { + "type": "integer", + "format": "uint32" + } + } + }, + "VirtualServerSpecTiny": { + "type": "object", + "properties": { + "Bps": { + "type": "integer", + "format": "uint32" + }, + "ConnTimeout": { + "type": "integer", + "format": "uint32" + }, + "ExpireQuiescent": { + "type": "boolean", + "default": false + }, + "Fwmark": { + "type": "integer", + "format": "uint32" + }, + "LimitProportion": { + "type": "integer", + "format": "uint32" + }, + "Match": { + "$ref": "#/definitions/MatchSpec" + }, + "SchedName": { + "type": "string", + "enum": [ + "rr", + "wrr", + "wlc", + "connhash" + ] + }, + "SyncProxy": { + "type": "boolean", + "default": false + }, + "Timeout": { + "type": "integer", + "format": "uint32" + } + } + }, + "VlanSpec": { + "properties": { + "device": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + } + } + }, + "parameters": { + "acl-config": { + "name": "acl", + "in": "body", + "schema": { + "$ref": "#/definitions/AclAddrList" + } + }, + "device-addr": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/InetAddrSpec" + } + }, + "device-name": { + "type": "string", + "name": "name", + "in": "path", + "required": true + }, + "forward2kni": { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "forward2Kni", + "in": "query" + }, + "healthcheck": { + "type": "boolean", + "default": false, + "name": "healthcheck", + "in": "query" + }, + "laddr-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/LocalAddressSpecTiny" + } + }, + "link": { + "enum": [ + "unset", + "up", + "down" + ], + "type": "string", + "default": "unset", + "name": "link", + "in": "query" + }, + "promisc": { + "enum": [ + "unset", + "on", + "off" + ], + "type": "string", + "default": "unset", + "name": "promisc", + "in": "query" + }, + "realserver-id": { + "type": "string", + "name": "RipPort", + "in": "path", + "required": true + }, + "route-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RouteSpec" + } + }, + "rs-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerSpecTiny" + } + }, + "rss-config": { + "name": "rss", + "in": "body", + "schema": { + "$ref": "#/definitions/RealServerTinyList" + } + }, + "sapool": { + "type": "boolean", + "default": false, + "name": "sapool", + "in": "query" + }, + "service-id": { + "type": "string", + "name": "VipPort", + "in": "path", + "required": true + }, + "stats": { + "type": "boolean", + "default": false, + "name": "stats", + "in": "query" + }, + "verbose": { + "type": "boolean", + "default": false, + "name": "verbose", + "in": "query" + }, + "vlan-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VlanSpec" + } + }, + "vs-config": { + "name": "spec", + "in": "body", + "schema": { + "$ref": "#/definitions/VirtualServerSpecTiny" + } + } + }, + "tags": [ + { + "description": "virtualserver", + "name": "virtualserver" + }, + { + "description": "route", + "name": "route" + }, + { + "description": "laddr", + "name": "laddr" + }, + { + "description": "tunnel", + "name": "tunnel" + }, + { + "description": "inet addr", + "name": "inetaddr" + }, + { + "description": "white list", + "name": "white_list" + }, + { + "description": "black list", + "name": "black_list" + }, + { + "description": "arp", + "name": "arp" + } + ] +}`)) +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr.go new file mode 100644 index 000000000..ecb1bab59 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameAddrHandlerFunc turns a function with the right signature into a delete device name addr handler +type DeleteDeviceNameAddrHandlerFunc func(DeleteDeviceNameAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameAddrHandlerFunc) Handle(params DeleteDeviceNameAddrParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameAddrHandler interface for that can handle valid delete device name addr params +type DeleteDeviceNameAddrHandler interface { + Handle(DeleteDeviceNameAddrParams) middleware.Responder +} + +// NewDeleteDeviceNameAddr creates a new http.Handler for the delete device name addr operation +func NewDeleteDeviceNameAddr(ctx *middleware.Context, handler DeleteDeviceNameAddrHandler) *DeleteDeviceNameAddr { + return &DeleteDeviceNameAddr{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameAddr swagger:route DELETE /device/{name}/addr device deleteDeviceNameAddr + +delete special net device ip addr +*/ +type DeleteDeviceNameAddr struct { + Context *middleware.Context + Handler DeleteDeviceNameAddrHandler +} + +func (o *DeleteDeviceNameAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_parameters.go new file mode 100644 index 000000000..c4134b592 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_parameters.go @@ -0,0 +1,145 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteDeviceNameAddrParams creates a new DeleteDeviceNameAddrParams object +// with the default values initialized. +func NewDeleteDeviceNameAddrParams() DeleteDeviceNameAddrParams { + + var ( + // initialize parameters with default values + + sapoolDefault = bool(false) + ) + + return DeleteDeviceNameAddrParams{ + Sapool: &sapoolDefault, + } +} + +// DeleteDeviceNameAddrParams contains all the bound params for the delete device name addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameAddr +type DeleteDeviceNameAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Sapool *bool + /* + In: body + */ + Spec *models.InetAddrSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameAddrParams() beforehand. +func (o *DeleteDeviceNameAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qSapool, qhkSapool, _ := qs.GetOK("sapool") + if err := o.bindSapool(qSapool, qhkSapool, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.InetAddrSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindSapool binds and validates parameter Sapool from query. +func (o *DeleteDeviceNameAddrParams) bindSapool(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewDeleteDeviceNameAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("sapool", "query", "bool", raw) + } + o.Sapool = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_responses.go new file mode 100644 index 000000000..82afd7bb0 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameAddrOKCode is the HTTP code returned for type DeleteDeviceNameAddrOK +const DeleteDeviceNameAddrOKCode int = 200 + +/* +DeleteDeviceNameAddrOK delete ip addr from device Success + +swagger:response deleteDeviceNameAddrOK +*/ +type DeleteDeviceNameAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameAddrOK creates DeleteDeviceNameAddrOK with default headers values +func NewDeleteDeviceNameAddrOK() *DeleteDeviceNameAddrOK { + + return &DeleteDeviceNameAddrOK{} +} + +// WithPayload adds the payload to the delete device name addr o k response +func (o *DeleteDeviceNameAddrOK) WithPayload(payload string) *DeleteDeviceNameAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name addr o k response +func (o *DeleteDeviceNameAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameAddrInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameAddrInternalServerError +const DeleteDeviceNameAddrInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameAddrInternalServerError Failed + +swagger:response deleteDeviceNameAddrInternalServerError +*/ +type DeleteDeviceNameAddrInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameAddrInternalServerError creates DeleteDeviceNameAddrInternalServerError with default headers values +func NewDeleteDeviceNameAddrInternalServerError() *DeleteDeviceNameAddrInternalServerError { + + return &DeleteDeviceNameAddrInternalServerError{} +} + +// WithPayload adds the payload to the delete device name addr internal server error response +func (o *DeleteDeviceNameAddrInternalServerError) WithPayload(payload string) *DeleteDeviceNameAddrInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name addr internal server error response +func (o *DeleteDeviceNameAddrInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameAddrInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_urlbuilder.go new file mode 100644 index 000000000..e58276264 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_addr_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// DeleteDeviceNameAddrURL generates an URL for the delete device name addr operation +type DeleteDeviceNameAddrURL struct { + Name string + + Sapool *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameAddrURL) WithBasePath(bp string) *DeleteDeviceNameAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var sapoolQ string + if o.Sapool != nil { + sapoolQ = swag.FormatBool(*o.Sapool) + } + if sapoolQ != "" { + qs.Set("sapool", sapoolQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink.go new file mode 100644 index 000000000..5429f3a10 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameNetlinkHandlerFunc turns a function with the right signature into a delete device name netlink handler +type DeleteDeviceNameNetlinkHandlerFunc func(DeleteDeviceNameNetlinkParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameNetlinkHandlerFunc) Handle(params DeleteDeviceNameNetlinkParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameNetlinkHandler interface for that can handle valid delete device name netlink params +type DeleteDeviceNameNetlinkHandler interface { + Handle(DeleteDeviceNameNetlinkParams) middleware.Responder +} + +// NewDeleteDeviceNameNetlink creates a new http.Handler for the delete device name netlink operation +func NewDeleteDeviceNameNetlink(ctx *middleware.Context, handler DeleteDeviceNameNetlinkHandler) *DeleteDeviceNameNetlink { + return &DeleteDeviceNameNetlink{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameNetlink swagger:route DELETE /device/{name}/netlink device deleteDeviceNameNetlink + +ip link set ${name} down +*/ +type DeleteDeviceNameNetlink struct { + Context *middleware.Context + Handler DeleteDeviceNameNetlinkHandler +} + +func (o *DeleteDeviceNameNetlink) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameNetlinkParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go new file mode 100644 index 000000000..63cb56c24 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameNetlinkAddrHandlerFunc turns a function with the right signature into a delete device name netlink addr handler +type DeleteDeviceNameNetlinkAddrHandlerFunc func(DeleteDeviceNameNetlinkAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameNetlinkAddrHandlerFunc) Handle(params DeleteDeviceNameNetlinkAddrParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameNetlinkAddrHandler interface for that can handle valid delete device name netlink addr params +type DeleteDeviceNameNetlinkAddrHandler interface { + Handle(DeleteDeviceNameNetlinkAddrParams) middleware.Responder +} + +// NewDeleteDeviceNameNetlinkAddr creates a new http.Handler for the delete device name netlink addr operation +func NewDeleteDeviceNameNetlinkAddr(ctx *middleware.Context, handler DeleteDeviceNameNetlinkAddrHandler) *DeleteDeviceNameNetlinkAddr { + return &DeleteDeviceNameNetlinkAddr{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameNetlinkAddr swagger:route DELETE /device/{name}/netlink/addr device deleteDeviceNameNetlinkAddr + +delete ip cird fron linux net device +*/ +type DeleteDeviceNameNetlinkAddr struct { + Context *middleware.Context + Handler DeleteDeviceNameNetlinkAddrHandler +} + +func (o *DeleteDeviceNameNetlinkAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameNetlinkAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_parameters.go new file mode 100644 index 000000000..9727f0252 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteDeviceNameNetlinkAddrParams creates a new DeleteDeviceNameNetlinkAddrParams object +// +// There are no default values defined in the spec. +func NewDeleteDeviceNameNetlinkAddrParams() DeleteDeviceNameNetlinkAddrParams { + + return DeleteDeviceNameNetlinkAddrParams{} +} + +// DeleteDeviceNameNetlinkAddrParams contains all the bound params for the delete device name netlink addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameNetlinkAddr +type DeleteDeviceNameNetlinkAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.InetAddrSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameNetlinkAddrParams() beforehand. +func (o *DeleteDeviceNameNetlinkAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.InetAddrSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameNetlinkAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_responses.go new file mode 100644 index 000000000..25d71dc7d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameNetlinkAddrOKCode is the HTTP code returned for type DeleteDeviceNameNetlinkAddrOK +const DeleteDeviceNameNetlinkAddrOKCode int = 200 + +/* +DeleteDeviceNameNetlinkAddrOK Success + +swagger:response deleteDeviceNameNetlinkAddrOK +*/ +type DeleteDeviceNameNetlinkAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameNetlinkAddrOK creates DeleteDeviceNameNetlinkAddrOK with default headers values +func NewDeleteDeviceNameNetlinkAddrOK() *DeleteDeviceNameNetlinkAddrOK { + + return &DeleteDeviceNameNetlinkAddrOK{} +} + +// WithPayload adds the payload to the delete device name netlink addr o k response +func (o *DeleteDeviceNameNetlinkAddrOK) WithPayload(payload string) *DeleteDeviceNameNetlinkAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name netlink addr o k response +func (o *DeleteDeviceNameNetlinkAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameNetlinkAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameNetlinkAddrInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameNetlinkAddrInternalServerError +const DeleteDeviceNameNetlinkAddrInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameNetlinkAddrInternalServerError Not Found + +swagger:response deleteDeviceNameNetlinkAddrInternalServerError +*/ +type DeleteDeviceNameNetlinkAddrInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameNetlinkAddrInternalServerError creates DeleteDeviceNameNetlinkAddrInternalServerError with default headers values +func NewDeleteDeviceNameNetlinkAddrInternalServerError() *DeleteDeviceNameNetlinkAddrInternalServerError { + + return &DeleteDeviceNameNetlinkAddrInternalServerError{} +} + +// WithPayload adds the payload to the delete device name netlink addr internal server error response +func (o *DeleteDeviceNameNetlinkAddrInternalServerError) WithPayload(payload string) *DeleteDeviceNameNetlinkAddrInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name netlink addr internal server error response +func (o *DeleteDeviceNameNetlinkAddrInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameNetlinkAddrInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_urlbuilder.go new file mode 100644 index 000000000..581dbc5f3 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteDeviceNameNetlinkAddrURL generates an URL for the delete device name netlink addr operation +type DeleteDeviceNameNetlinkAddrURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameNetlinkAddrURL) WithBasePath(bp string) *DeleteDeviceNameNetlinkAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameNetlinkAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameNetlinkAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameNetlinkAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameNetlinkAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameNetlinkAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameNetlinkAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameNetlinkAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameNetlinkAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameNetlinkAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_parameters.go new file mode 100644 index 000000000..8dd329583 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewDeleteDeviceNameNetlinkParams creates a new DeleteDeviceNameNetlinkParams object +// +// There are no default values defined in the spec. +func NewDeleteDeviceNameNetlinkParams() DeleteDeviceNameNetlinkParams { + + return DeleteDeviceNameNetlinkParams{} +} + +// DeleteDeviceNameNetlinkParams contains all the bound params for the delete device name netlink operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameNetlink +type DeleteDeviceNameNetlinkParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameNetlinkParams() beforehand. +func (o *DeleteDeviceNameNetlinkParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameNetlinkParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_responses.go new file mode 100644 index 000000000..fd82c62e1 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameNetlinkOKCode is the HTTP code returned for type DeleteDeviceNameNetlinkOK +const DeleteDeviceNameNetlinkOKCode int = 200 + +/* +DeleteDeviceNameNetlinkOK Success + +swagger:response deleteDeviceNameNetlinkOK +*/ +type DeleteDeviceNameNetlinkOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameNetlinkOK creates DeleteDeviceNameNetlinkOK with default headers values +func NewDeleteDeviceNameNetlinkOK() *DeleteDeviceNameNetlinkOK { + + return &DeleteDeviceNameNetlinkOK{} +} + +// WithPayload adds the payload to the delete device name netlink o k response +func (o *DeleteDeviceNameNetlinkOK) WithPayload(payload string) *DeleteDeviceNameNetlinkOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name netlink o k response +func (o *DeleteDeviceNameNetlinkOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameNetlinkOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameNetlinkInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameNetlinkInternalServerError +const DeleteDeviceNameNetlinkInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameNetlinkInternalServerError Not Found + +swagger:response deleteDeviceNameNetlinkInternalServerError +*/ +type DeleteDeviceNameNetlinkInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameNetlinkInternalServerError creates DeleteDeviceNameNetlinkInternalServerError with default headers values +func NewDeleteDeviceNameNetlinkInternalServerError() *DeleteDeviceNameNetlinkInternalServerError { + + return &DeleteDeviceNameNetlinkInternalServerError{} +} + +// WithPayload adds the payload to the delete device name netlink internal server error response +func (o *DeleteDeviceNameNetlinkInternalServerError) WithPayload(payload string) *DeleteDeviceNameNetlinkInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name netlink internal server error response +func (o *DeleteDeviceNameNetlinkInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameNetlinkInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_urlbuilder.go new file mode 100644 index 000000000..460186582 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteDeviceNameNetlinkURL generates an URL for the delete device name netlink operation +type DeleteDeviceNameNetlinkURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameNetlinkURL) WithBasePath(bp string) *DeleteDeviceNameNetlinkURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameNetlinkURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameNetlinkURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameNetlinkURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameNetlinkURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameNetlinkURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameNetlinkURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameNetlinkURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameNetlinkURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameNetlinkURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_route.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route.go new file mode 100644 index 000000000..8cce8d372 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameRouteHandlerFunc turns a function with the right signature into a delete device name route handler +type DeleteDeviceNameRouteHandlerFunc func(DeleteDeviceNameRouteParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameRouteHandlerFunc) Handle(params DeleteDeviceNameRouteParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameRouteHandler interface for that can handle valid delete device name route params +type DeleteDeviceNameRouteHandler interface { + Handle(DeleteDeviceNameRouteParams) middleware.Responder +} + +// NewDeleteDeviceNameRoute creates a new http.Handler for the delete device name route operation +func NewDeleteDeviceNameRoute(ctx *middleware.Context, handler DeleteDeviceNameRouteHandler) *DeleteDeviceNameRoute { + return &DeleteDeviceNameRoute{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameRoute swagger:route DELETE /device/{name}/route device deleteDeviceNameRoute + +delete special net device route +*/ +type DeleteDeviceNameRoute struct { + Context *middleware.Context + Handler DeleteDeviceNameRouteHandler +} + +func (o *DeleteDeviceNameRoute) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameRouteParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_parameters.go new file mode 100644 index 000000000..47b47fba7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteDeviceNameRouteParams creates a new DeleteDeviceNameRouteParams object +// +// There are no default values defined in the spec. +func NewDeleteDeviceNameRouteParams() DeleteDeviceNameRouteParams { + + return DeleteDeviceNameRouteParams{} +} + +// DeleteDeviceNameRouteParams contains all the bound params for the delete device name route operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameRoute +type DeleteDeviceNameRouteParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.RouteSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameRouteParams() beforehand. +func (o *DeleteDeviceNameRouteParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RouteSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameRouteParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_responses.go new file mode 100644 index 000000000..c9146f0fe --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameRouteOKCode is the HTTP code returned for type DeleteDeviceNameRouteOK +const DeleteDeviceNameRouteOKCode int = 200 + +/* +DeleteDeviceNameRouteOK delete route Success + +swagger:response deleteDeviceNameRouteOK +*/ +type DeleteDeviceNameRouteOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameRouteOK creates DeleteDeviceNameRouteOK with default headers values +func NewDeleteDeviceNameRouteOK() *DeleteDeviceNameRouteOK { + + return &DeleteDeviceNameRouteOK{} +} + +// WithPayload adds the payload to the delete device name route o k response +func (o *DeleteDeviceNameRouteOK) WithPayload(payload string) *DeleteDeviceNameRouteOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name route o k response +func (o *DeleteDeviceNameRouteOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameRouteOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameRouteInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameRouteInternalServerError +const DeleteDeviceNameRouteInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameRouteInternalServerError Failed + +swagger:response deleteDeviceNameRouteInternalServerError +*/ +type DeleteDeviceNameRouteInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameRouteInternalServerError creates DeleteDeviceNameRouteInternalServerError with default headers values +func NewDeleteDeviceNameRouteInternalServerError() *DeleteDeviceNameRouteInternalServerError { + + return &DeleteDeviceNameRouteInternalServerError{} +} + +// WithPayload adds the payload to the delete device name route internal server error response +func (o *DeleteDeviceNameRouteInternalServerError) WithPayload(payload string) *DeleteDeviceNameRouteInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name route internal server error response +func (o *DeleteDeviceNameRouteInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameRouteInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_urlbuilder.go new file mode 100644 index 000000000..8be3d0374 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_route_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteDeviceNameRouteURL generates an URL for the delete device name route operation +type DeleteDeviceNameRouteURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameRouteURL) WithBasePath(bp string) *DeleteDeviceNameRouteURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameRouteURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameRouteURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/route" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameRouteURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameRouteURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameRouteURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameRouteURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameRouteURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameRouteURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameRouteURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan.go new file mode 100644 index 000000000..88d8a8feb --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteDeviceNameVlanHandlerFunc turns a function with the right signature into a delete device name vlan handler +type DeleteDeviceNameVlanHandlerFunc func(DeleteDeviceNameVlanParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteDeviceNameVlanHandlerFunc) Handle(params DeleteDeviceNameVlanParams) middleware.Responder { + return fn(params) +} + +// DeleteDeviceNameVlanHandler interface for that can handle valid delete device name vlan params +type DeleteDeviceNameVlanHandler interface { + Handle(DeleteDeviceNameVlanParams) middleware.Responder +} + +// NewDeleteDeviceNameVlan creates a new http.Handler for the delete device name vlan operation +func NewDeleteDeviceNameVlan(ctx *middleware.Context, handler DeleteDeviceNameVlanHandler) *DeleteDeviceNameVlan { + return &DeleteDeviceNameVlan{Context: ctx, Handler: handler} +} + +/* + DeleteDeviceNameVlan swagger:route DELETE /device/{name}/vlan device deleteDeviceNameVlan + +delete special net device +*/ +type DeleteDeviceNameVlan struct { + Context *middleware.Context + Handler DeleteDeviceNameVlanHandler +} + +func (o *DeleteDeviceNameVlan) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteDeviceNameVlanParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_parameters.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_parameters.go new file mode 100644 index 000000000..ab157fa5a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewDeleteDeviceNameVlanParams creates a new DeleteDeviceNameVlanParams object +// +// There are no default values defined in the spec. +func NewDeleteDeviceNameVlanParams() DeleteDeviceNameVlanParams { + + return DeleteDeviceNameVlanParams{} +} + +// DeleteDeviceNameVlanParams contains all the bound params for the delete device name vlan operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteDeviceNameVlan +type DeleteDeviceNameVlanParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteDeviceNameVlanParams() beforehand. +func (o *DeleteDeviceNameVlanParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *DeleteDeviceNameVlanParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_responses.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_responses.go new file mode 100644 index 000000000..f6a934a11 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// DeleteDeviceNameVlanOKCode is the HTTP code returned for type DeleteDeviceNameVlanOK +const DeleteDeviceNameVlanOKCode int = 200 + +/* +DeleteDeviceNameVlanOK Success + +swagger:response deleteDeviceNameVlanOK +*/ +type DeleteDeviceNameVlanOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameVlanOK creates DeleteDeviceNameVlanOK with default headers values +func NewDeleteDeviceNameVlanOK() *DeleteDeviceNameVlanOK { + + return &DeleteDeviceNameVlanOK{} +} + +// WithPayload adds the payload to the delete device name vlan o k response +func (o *DeleteDeviceNameVlanOK) WithPayload(payload string) *DeleteDeviceNameVlanOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name vlan o k response +func (o *DeleteDeviceNameVlanOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameVlanOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteDeviceNameVlanInternalServerErrorCode is the HTTP code returned for type DeleteDeviceNameVlanInternalServerError +const DeleteDeviceNameVlanInternalServerErrorCode int = 500 + +/* +DeleteDeviceNameVlanInternalServerError Failed + +swagger:response deleteDeviceNameVlanInternalServerError +*/ +type DeleteDeviceNameVlanInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteDeviceNameVlanInternalServerError creates DeleteDeviceNameVlanInternalServerError with default headers values +func NewDeleteDeviceNameVlanInternalServerError() *DeleteDeviceNameVlanInternalServerError { + + return &DeleteDeviceNameVlanInternalServerError{} +} + +// WithPayload adds the payload to the delete device name vlan internal server error response +func (o *DeleteDeviceNameVlanInternalServerError) WithPayload(payload string) *DeleteDeviceNameVlanInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete device name vlan internal server error response +func (o *DeleteDeviceNameVlanInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteDeviceNameVlanInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_urlbuilder.go new file mode 100644 index 000000000..e0e5ef6cf --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_vlan_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteDeviceNameVlanURL generates an URL for the delete device name vlan operation +type DeleteDeviceNameVlanURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameVlanURL) WithBasePath(bp string) *DeleteDeviceNameVlanURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteDeviceNameVlanURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteDeviceNameVlanURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/vlan" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on DeleteDeviceNameVlanURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteDeviceNameVlanURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteDeviceNameVlanURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteDeviceNameVlanURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteDeviceNameVlanURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteDeviceNameVlanURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteDeviceNameVlanURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device.go b/tools/dpvs-agent/restapi/operations/device/get_device.go new file mode 100644 index 000000000..f9f968395 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceHandlerFunc turns a function with the right signature into a get device handler +type GetDeviceHandlerFunc func(GetDeviceParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceHandlerFunc) Handle(params GetDeviceParams) middleware.Responder { + return fn(params) +} + +// GetDeviceHandler interface for that can handle valid get device params +type GetDeviceHandler interface { + Handle(GetDeviceParams) middleware.Responder +} + +// NewGetDevice creates a new http.Handler for the get device operation +func NewGetDevice(ctx *middleware.Context, handler GetDeviceHandler) *GetDevice { + return &GetDevice{Context: ctx, Handler: handler} +} + +/* + GetDevice swagger:route GET /device device getDevice + +display all net device list +*/ +type GetDevice struct { + Context *middleware.Context + Handler GetDeviceHandler +} + +func (o *GetDevice) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_addr.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr.go new file mode 100644 index 000000000..0c159713c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameAddrHandlerFunc turns a function with the right signature into a get device name addr handler +type GetDeviceNameAddrHandlerFunc func(GetDeviceNameAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameAddrHandlerFunc) Handle(params GetDeviceNameAddrParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameAddrHandler interface for that can handle valid get device name addr params +type GetDeviceNameAddrHandler interface { + Handle(GetDeviceNameAddrParams) middleware.Responder +} + +// NewGetDeviceNameAddr creates a new http.Handler for the get device name addr operation +func NewGetDeviceNameAddr(ctx *middleware.Context, handler GetDeviceNameAddrHandler) *GetDeviceNameAddr { + return &GetDeviceNameAddr{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameAddr swagger:route GET /device/{name}/addr device getDeviceNameAddr + +display special net device ip addr +*/ +type GetDeviceNameAddr struct { + Context *middleware.Context + Handler GetDeviceNameAddrHandler +} + +func (o *GetDeviceNameAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_parameters.go new file mode 100644 index 000000000..cc1620fa7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_parameters.go @@ -0,0 +1,153 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameAddrParams creates a new GetDeviceNameAddrParams object +// with the default values initialized. +func NewGetDeviceNameAddrParams() GetDeviceNameAddrParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + verboseDefault = bool(false) + ) + + return GetDeviceNameAddrParams{ + Stats: &statsDefault, + + Verbose: &verboseDefault, + } +} + +// GetDeviceNameAddrParams contains all the bound params for the get device name addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameAddr +type GetDeviceNameAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool + /* + In: query + Default: false + */ + Verbose *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameAddrParams() beforehand. +func (o *GetDeviceNameAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + + qVerbose, qhkVerbose, _ := qs.GetOK("verbose") + if err := o.bindVerbose(qVerbose, qhkVerbose, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameAddrParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} + +// bindVerbose binds and validates parameter Verbose from query. +func (o *GetDeviceNameAddrParams) bindVerbose(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("verbose", "query", "bool", raw) + } + o.Verbose = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_responses.go new file mode 100644 index 000000000..e2ff4ac14 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameAddrOKCode is the HTTP code returned for type GetDeviceNameAddrOK +const GetDeviceNameAddrOKCode int = 200 + +/* +GetDeviceNameAddrOK Success + +swagger:response getDeviceNameAddrOK +*/ +type GetDeviceNameAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameAddrOK creates GetDeviceNameAddrOK with default headers values +func NewGetDeviceNameAddrOK() *GetDeviceNameAddrOK { + + return &GetDeviceNameAddrOK{} +} + +// WithPayload adds the payload to the get device name addr o k response +func (o *GetDeviceNameAddrOK) WithPayload(payload string) *GetDeviceNameAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name addr o k response +func (o *GetDeviceNameAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameAddrNotFoundCode is the HTTP code returned for type GetDeviceNameAddrNotFound +const GetDeviceNameAddrNotFoundCode int = 404 + +/* +GetDeviceNameAddrNotFound Not Found + +swagger:response getDeviceNameAddrNotFound +*/ +type GetDeviceNameAddrNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameAddrNotFound creates GetDeviceNameAddrNotFound with default headers values +func NewGetDeviceNameAddrNotFound() *GetDeviceNameAddrNotFound { + + return &GetDeviceNameAddrNotFound{} +} + +// WithPayload adds the payload to the get device name addr not found response +func (o *GetDeviceNameAddrNotFound) WithPayload(payload string) *GetDeviceNameAddrNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name addr not found response +func (o *GetDeviceNameAddrNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameAddrNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_urlbuilder.go new file mode 100644 index 000000000..a4c2cd9db --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_addr_urlbuilder.go @@ -0,0 +1,124 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameAddrURL generates an URL for the get device name addr operation +type GetDeviceNameAddrURL struct { + Name string + + Stats *bool + Verbose *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameAddrURL) WithBasePath(bp string) *GetDeviceNameAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + var verboseQ string + if o.Verbose != nil { + verboseQ = swag.FormatBool(*o.Verbose) + } + if verboseQ != "" { + qs.Set("verbose", verboseQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink.go new file mode 100644 index 000000000..04f4f4ce7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameNetlinkHandlerFunc turns a function with the right signature into a get device name netlink handler +type GetDeviceNameNetlinkHandlerFunc func(GetDeviceNameNetlinkParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameNetlinkHandlerFunc) Handle(params GetDeviceNameNetlinkParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameNetlinkHandler interface for that can handle valid get device name netlink params +type GetDeviceNameNetlinkHandler interface { + Handle(GetDeviceNameNetlinkParams) middleware.Responder +} + +// NewGetDeviceNameNetlink creates a new http.Handler for the get device name netlink operation +func NewGetDeviceNameNetlink(ctx *middleware.Context, handler GetDeviceNameNetlinkHandler) *GetDeviceNameNetlink { + return &GetDeviceNameNetlink{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameNetlink swagger:route GET /device/{name}/netlink device getDeviceNameNetlink + +ip link show dev ${name} +*/ +type GetDeviceNameNetlink struct { + Context *middleware.Context + Handler GetDeviceNameNetlinkHandler +} + +func (o *GetDeviceNameNetlink) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameNetlinkParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go new file mode 100644 index 000000000..d9670c047 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameNetlinkAddrHandlerFunc turns a function with the right signature into a get device name netlink addr handler +type GetDeviceNameNetlinkAddrHandlerFunc func(GetDeviceNameNetlinkAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameNetlinkAddrHandlerFunc) Handle(params GetDeviceNameNetlinkAddrParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameNetlinkAddrHandler interface for that can handle valid get device name netlink addr params +type GetDeviceNameNetlinkAddrHandler interface { + Handle(GetDeviceNameNetlinkAddrParams) middleware.Responder +} + +// NewGetDeviceNameNetlinkAddr creates a new http.Handler for the get device name netlink addr operation +func NewGetDeviceNameNetlinkAddr(ctx *middleware.Context, handler GetDeviceNameNetlinkAddrHandler) *GetDeviceNameNetlinkAddr { + return &GetDeviceNameNetlinkAddr{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameNetlinkAddr swagger:route GET /device/{name}/netlink/addr device getDeviceNameNetlinkAddr + +display special linux net device addr detail +*/ +type GetDeviceNameNetlinkAddr struct { + Context *middleware.Context + Handler GetDeviceNameNetlinkAddrHandler +} + +func (o *GetDeviceNameNetlinkAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameNetlinkAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_parameters.go new file mode 100644 index 000000000..ff3ffbf49 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameNetlinkAddrParams creates a new GetDeviceNameNetlinkAddrParams object +// with the default values initialized. +func NewGetDeviceNameNetlinkAddrParams() GetDeviceNameNetlinkAddrParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceNameNetlinkAddrParams{ + Stats: &statsDefault, + } +} + +// GetDeviceNameNetlinkAddrParams contains all the bound params for the get device name netlink addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameNetlinkAddr +type GetDeviceNameNetlinkAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameNetlinkAddrParams() beforehand. +func (o *GetDeviceNameNetlinkAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameNetlinkAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameNetlinkAddrParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameNetlinkAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_responses.go new file mode 100644 index 000000000..ee54be55b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameNetlinkAddrOKCode is the HTTP code returned for type GetDeviceNameNetlinkAddrOK +const GetDeviceNameNetlinkAddrOKCode int = 200 + +/* +GetDeviceNameNetlinkAddrOK Success + +swagger:response getDeviceNameNetlinkAddrOK +*/ +type GetDeviceNameNetlinkAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNetlinkAddrOK creates GetDeviceNameNetlinkAddrOK with default headers values +func NewGetDeviceNameNetlinkAddrOK() *GetDeviceNameNetlinkAddrOK { + + return &GetDeviceNameNetlinkAddrOK{} +} + +// WithPayload adds the payload to the get device name netlink addr o k response +func (o *GetDeviceNameNetlinkAddrOK) WithPayload(payload string) *GetDeviceNameNetlinkAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name netlink addr o k response +func (o *GetDeviceNameNetlinkAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNetlinkAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameNetlinkAddrNotFoundCode is the HTTP code returned for type GetDeviceNameNetlinkAddrNotFound +const GetDeviceNameNetlinkAddrNotFoundCode int = 404 + +/* +GetDeviceNameNetlinkAddrNotFound Not Found + +swagger:response getDeviceNameNetlinkAddrNotFound +*/ +type GetDeviceNameNetlinkAddrNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNetlinkAddrNotFound creates GetDeviceNameNetlinkAddrNotFound with default headers values +func NewGetDeviceNameNetlinkAddrNotFound() *GetDeviceNameNetlinkAddrNotFound { + + return &GetDeviceNameNetlinkAddrNotFound{} +} + +// WithPayload adds the payload to the get device name netlink addr not found response +func (o *GetDeviceNameNetlinkAddrNotFound) WithPayload(payload string) *GetDeviceNameNetlinkAddrNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name netlink addr not found response +func (o *GetDeviceNameNetlinkAddrNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNetlinkAddrNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_urlbuilder.go new file mode 100644 index 000000000..463da03fe --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameNetlinkAddrURL generates an URL for the get device name netlink addr operation +type GetDeviceNameNetlinkAddrURL struct { + Name string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNetlinkAddrURL) WithBasePath(bp string) *GetDeviceNameNetlinkAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNetlinkAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameNetlinkAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameNetlinkAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameNetlinkAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameNetlinkAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameNetlinkAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameNetlinkAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameNetlinkAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameNetlinkAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_parameters.go new file mode 100644 index 000000000..99f198265 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameNetlinkParams creates a new GetDeviceNameNetlinkParams object +// with the default values initialized. +func NewGetDeviceNameNetlinkParams() GetDeviceNameNetlinkParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceNameNetlinkParams{ + Stats: &statsDefault, + } +} + +// GetDeviceNameNetlinkParams contains all the bound params for the get device name netlink operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameNetlink +type GetDeviceNameNetlinkParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameNetlinkParams() beforehand. +func (o *GetDeviceNameNetlinkParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameNetlinkParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameNetlinkParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameNetlinkParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_responses.go new file mode 100644 index 000000000..865e01439 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameNetlinkOKCode is the HTTP code returned for type GetDeviceNameNetlinkOK +const GetDeviceNameNetlinkOKCode int = 200 + +/* +GetDeviceNameNetlinkOK Success + +swagger:response getDeviceNameNetlinkOK +*/ +type GetDeviceNameNetlinkOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNetlinkOK creates GetDeviceNameNetlinkOK with default headers values +func NewGetDeviceNameNetlinkOK() *GetDeviceNameNetlinkOK { + + return &GetDeviceNameNetlinkOK{} +} + +// WithPayload adds the payload to the get device name netlink o k response +func (o *GetDeviceNameNetlinkOK) WithPayload(payload string) *GetDeviceNameNetlinkOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name netlink o k response +func (o *GetDeviceNameNetlinkOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNetlinkOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameNetlinkNotFoundCode is the HTTP code returned for type GetDeviceNameNetlinkNotFound +const GetDeviceNameNetlinkNotFoundCode int = 404 + +/* +GetDeviceNameNetlinkNotFound Not Found + +swagger:response getDeviceNameNetlinkNotFound +*/ +type GetDeviceNameNetlinkNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNetlinkNotFound creates GetDeviceNameNetlinkNotFound with default headers values +func NewGetDeviceNameNetlinkNotFound() *GetDeviceNameNetlinkNotFound { + + return &GetDeviceNameNetlinkNotFound{} +} + +// WithPayload adds the payload to the get device name netlink not found response +func (o *GetDeviceNameNetlinkNotFound) WithPayload(payload string) *GetDeviceNameNetlinkNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name netlink not found response +func (o *GetDeviceNameNetlinkNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNetlinkNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_urlbuilder.go new file mode 100644 index 000000000..2f9847cdc --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameNetlinkURL generates an URL for the get device name netlink operation +type GetDeviceNameNetlinkURL struct { + Name string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNetlinkURL) WithBasePath(bp string) *GetDeviceNameNetlinkURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNetlinkURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameNetlinkURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameNetlinkURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameNetlinkURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameNetlinkURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameNetlinkURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameNetlinkURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameNetlinkURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameNetlinkURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_nic.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic.go new file mode 100644 index 000000000..1f58cbd38 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameNicHandlerFunc turns a function with the right signature into a get device name nic handler +type GetDeviceNameNicHandlerFunc func(GetDeviceNameNicParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameNicHandlerFunc) Handle(params GetDeviceNameNicParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameNicHandler interface for that can handle valid get device name nic params +type GetDeviceNameNicHandler interface { + Handle(GetDeviceNameNicParams) middleware.Responder +} + +// NewGetDeviceNameNic creates a new http.Handler for the get device name nic operation +func NewGetDeviceNameNic(ctx *middleware.Context, handler GetDeviceNameNicHandler) *GetDeviceNameNic { + return &GetDeviceNameNic{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameNic swagger:route GET /device/{name}/nic device getDeviceNameNic + +dpip link show ${nic-name} -s -v +*/ +type GetDeviceNameNic struct { + Context *middleware.Context + Handler GetDeviceNameNicHandler +} + +func (o *GetDeviceNameNic) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameNicParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_parameters.go new file mode 100644 index 000000000..d09091d52 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_parameters.go @@ -0,0 +1,153 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameNicParams creates a new GetDeviceNameNicParams object +// with the default values initialized. +func NewGetDeviceNameNicParams() GetDeviceNameNicParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + verboseDefault = bool(false) + ) + + return GetDeviceNameNicParams{ + Stats: &statsDefault, + + Verbose: &verboseDefault, + } +} + +// GetDeviceNameNicParams contains all the bound params for the get device name nic operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameNic +type GetDeviceNameNicParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool + /* + In: query + Default: false + */ + Verbose *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameNicParams() beforehand. +func (o *GetDeviceNameNicParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + + qVerbose, qhkVerbose, _ := qs.GetOK("verbose") + if err := o.bindVerbose(qVerbose, qhkVerbose, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameNicParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameNicParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameNicParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} + +// bindVerbose binds and validates parameter Verbose from query. +func (o *GetDeviceNameNicParams) bindVerbose(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameNicParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("verbose", "query", "bool", raw) + } + o.Verbose = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_responses.go new file mode 100644 index 000000000..b55984b92 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_responses.go @@ -0,0 +1,102 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// GetDeviceNameNicOKCode is the HTTP code returned for type GetDeviceNameNicOK +const GetDeviceNameNicOKCode int = 200 + +/* +GetDeviceNameNicOK Success + +swagger:response getDeviceNameNicOK +*/ +type GetDeviceNameNicOK struct { + + /* + In: Body + */ + Payload *models.NicDeviceSpecList `json:"body,omitempty"` +} + +// NewGetDeviceNameNicOK creates GetDeviceNameNicOK with default headers values +func NewGetDeviceNameNicOK() *GetDeviceNameNicOK { + + return &GetDeviceNameNicOK{} +} + +// WithPayload adds the payload to the get device name nic o k response +func (o *GetDeviceNameNicOK) WithPayload(payload *models.NicDeviceSpecList) *GetDeviceNameNicOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name nic o k response +func (o *GetDeviceNameNicOK) SetPayload(payload *models.NicDeviceSpecList) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNicOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetDeviceNameNicInternalServerErrorCode is the HTTP code returned for type GetDeviceNameNicInternalServerError +const GetDeviceNameNicInternalServerErrorCode int = 500 + +/* +GetDeviceNameNicInternalServerError Failure + +swagger:response getDeviceNameNicInternalServerError +*/ +type GetDeviceNameNicInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameNicInternalServerError creates GetDeviceNameNicInternalServerError with default headers values +func NewGetDeviceNameNicInternalServerError() *GetDeviceNameNicInternalServerError { + + return &GetDeviceNameNicInternalServerError{} +} + +// WithPayload adds the payload to the get device name nic internal server error response +func (o *GetDeviceNameNicInternalServerError) WithPayload(payload string) *GetDeviceNameNicInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name nic internal server error response +func (o *GetDeviceNameNicInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameNicInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_urlbuilder.go new file mode 100644 index 000000000..9d1b99104 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_nic_urlbuilder.go @@ -0,0 +1,124 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameNicURL generates an URL for the get device name nic operation +type GetDeviceNameNicURL struct { + Name string + + Stats *bool + Verbose *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNicURL) WithBasePath(bp string) *GetDeviceNameNicURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameNicURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameNicURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/nic" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameNicURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + var verboseQ string + if o.Verbose != nil { + verboseQ = swag.FormatBool(*o.Verbose) + } + if verboseQ != "" { + qs.Set("verbose", verboseQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameNicURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameNicURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameNicURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameNicURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameNicURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameNicURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_route.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_route.go new file mode 100644 index 000000000..fe7625fc1 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_route.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameRouteHandlerFunc turns a function with the right signature into a get device name route handler +type GetDeviceNameRouteHandlerFunc func(GetDeviceNameRouteParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameRouteHandlerFunc) Handle(params GetDeviceNameRouteParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameRouteHandler interface for that can handle valid get device name route params +type GetDeviceNameRouteHandler interface { + Handle(GetDeviceNameRouteParams) middleware.Responder +} + +// NewGetDeviceNameRoute creates a new http.Handler for the get device name route operation +func NewGetDeviceNameRoute(ctx *middleware.Context, handler GetDeviceNameRouteHandler) *GetDeviceNameRoute { + return &GetDeviceNameRoute{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameRoute swagger:route GET /device/{name}/route device getDeviceNameRoute + +display special net device route +*/ +type GetDeviceNameRoute struct { + Context *middleware.Context + Handler GetDeviceNameRouteHandler +} + +func (o *GetDeviceNameRoute) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameRouteParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_route_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_parameters.go new file mode 100644 index 000000000..00ab725c6 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameRouteParams creates a new GetDeviceNameRouteParams object +// with the default values initialized. +func NewGetDeviceNameRouteParams() GetDeviceNameRouteParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceNameRouteParams{ + Stats: &statsDefault, + } +} + +// GetDeviceNameRouteParams contains all the bound params for the get device name route operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameRoute +type GetDeviceNameRouteParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameRouteParams() beforehand. +func (o *GetDeviceNameRouteParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameRouteParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameRouteParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameRouteParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_route_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_responses.go new file mode 100644 index 000000000..d66415808 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameRouteOKCode is the HTTP code returned for type GetDeviceNameRouteOK +const GetDeviceNameRouteOKCode int = 200 + +/* +GetDeviceNameRouteOK Success + +swagger:response getDeviceNameRouteOK +*/ +type GetDeviceNameRouteOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameRouteOK creates GetDeviceNameRouteOK with default headers values +func NewGetDeviceNameRouteOK() *GetDeviceNameRouteOK { + + return &GetDeviceNameRouteOK{} +} + +// WithPayload adds the payload to the get device name route o k response +func (o *GetDeviceNameRouteOK) WithPayload(payload string) *GetDeviceNameRouteOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name route o k response +func (o *GetDeviceNameRouteOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameRouteOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameRouteNotFoundCode is the HTTP code returned for type GetDeviceNameRouteNotFound +const GetDeviceNameRouteNotFoundCode int = 404 + +/* +GetDeviceNameRouteNotFound Not Found + +swagger:response getDeviceNameRouteNotFound +*/ +type GetDeviceNameRouteNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameRouteNotFound creates GetDeviceNameRouteNotFound with default headers values +func NewGetDeviceNameRouteNotFound() *GetDeviceNameRouteNotFound { + + return &GetDeviceNameRouteNotFound{} +} + +// WithPayload adds the payload to the get device name route not found response +func (o *GetDeviceNameRouteNotFound) WithPayload(payload string) *GetDeviceNameRouteNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name route not found response +func (o *GetDeviceNameRouteNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameRouteNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_route_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_urlbuilder.go new file mode 100644 index 000000000..167d1f25a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_route_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameRouteURL generates an URL for the get device name route operation +type GetDeviceNameRouteURL struct { + Name string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameRouteURL) WithBasePath(bp string) *GetDeviceNameRouteURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameRouteURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameRouteURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/route" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameRouteURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameRouteURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameRouteURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameRouteURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameRouteURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameRouteURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameRouteURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan.go new file mode 100644 index 000000000..78539a3f5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetDeviceNameVlanHandlerFunc turns a function with the right signature into a get device name vlan handler +type GetDeviceNameVlanHandlerFunc func(GetDeviceNameVlanParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetDeviceNameVlanHandlerFunc) Handle(params GetDeviceNameVlanParams) middleware.Responder { + return fn(params) +} + +// GetDeviceNameVlanHandler interface for that can handle valid get device name vlan params +type GetDeviceNameVlanHandler interface { + Handle(GetDeviceNameVlanParams) middleware.Responder +} + +// NewGetDeviceNameVlan creates a new http.Handler for the get device name vlan operation +func NewGetDeviceNameVlan(ctx *middleware.Context, handler GetDeviceNameVlanHandler) *GetDeviceNameVlan { + return &GetDeviceNameVlan{Context: ctx, Handler: handler} +} + +/* + GetDeviceNameVlan swagger:route GET /device/{name}/vlan device getDeviceNameVlan + +display all net device list +*/ +type GetDeviceNameVlan struct { + Context *middleware.Context + Handler GetDeviceNameVlanHandler +} + +func (o *GetDeviceNameVlan) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetDeviceNameVlanParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_parameters.go new file mode 100644 index 000000000..1188161c8 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceNameVlanParams creates a new GetDeviceNameVlanParams object +// with the default values initialized. +func NewGetDeviceNameVlanParams() GetDeviceNameVlanParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceNameVlanParams{ + Stats: &statsDefault, + } +} + +// GetDeviceNameVlanParams contains all the bound params for the get device name vlan operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDeviceNameVlan +type GetDeviceNameVlanParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceNameVlanParams() beforehand. +func (o *GetDeviceNameVlanParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *GetDeviceNameVlanParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceNameVlanParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceNameVlanParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_responses.go new file mode 100644 index 000000000..d3bf35e47 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceNameVlanOKCode is the HTTP code returned for type GetDeviceNameVlanOK +const GetDeviceNameVlanOKCode int = 200 + +/* +GetDeviceNameVlanOK Success + +swagger:response getDeviceNameVlanOK +*/ +type GetDeviceNameVlanOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameVlanOK creates GetDeviceNameVlanOK with default headers values +func NewGetDeviceNameVlanOK() *GetDeviceNameVlanOK { + + return &GetDeviceNameVlanOK{} +} + +// WithPayload adds the payload to the get device name vlan o k response +func (o *GetDeviceNameVlanOK) WithPayload(payload string) *GetDeviceNameVlanOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name vlan o k response +func (o *GetDeviceNameVlanOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameVlanOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetDeviceNameVlanNotFoundCode is the HTTP code returned for type GetDeviceNameVlanNotFound +const GetDeviceNameVlanNotFoundCode int = 404 + +/* +GetDeviceNameVlanNotFound Not Found + +swagger:response getDeviceNameVlanNotFound +*/ +type GetDeviceNameVlanNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceNameVlanNotFound creates GetDeviceNameVlanNotFound with default headers values +func NewGetDeviceNameVlanNotFound() *GetDeviceNameVlanNotFound { + + return &GetDeviceNameVlanNotFound{} +} + +// WithPayload adds the payload to the get device name vlan not found response +func (o *GetDeviceNameVlanNotFound) WithPayload(payload string) *GetDeviceNameVlanNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device name vlan not found response +func (o *GetDeviceNameVlanNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceNameVlanNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_urlbuilder.go new file mode 100644 index 000000000..7044acbc9 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_vlan_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetDeviceNameVlanURL generates an URL for the get device name vlan operation +type GetDeviceNameVlanURL struct { + Name string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameVlanURL) WithBasePath(bp string) *GetDeviceNameVlanURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceNameVlanURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceNameVlanURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/vlan" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on GetDeviceNameVlanURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceNameVlanURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceNameVlanURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceNameVlanURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceNameVlanURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceNameVlanURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceNameVlanURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_parameters.go b/tools/dpvs-agent/restapi/operations/device/get_device_parameters.go new file mode 100644 index 000000000..59c367e91 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_parameters.go @@ -0,0 +1,92 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetDeviceParams creates a new GetDeviceParams object +// with the default values initialized. +func NewGetDeviceParams() GetDeviceParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetDeviceParams{ + Stats: &statsDefault, + } +} + +// GetDeviceParams contains all the bound params for the get device operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetDevice +type GetDeviceParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetDeviceParams() beforehand. +func (o *GetDeviceParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetDeviceParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetDeviceParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_responses.go b/tools/dpvs-agent/restapi/operations/device/get_device_responses.go new file mode 100644 index 000000000..c9b51cc5e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_responses.go @@ -0,0 +1,55 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetDeviceOKCode is the HTTP code returned for type GetDeviceOK +const GetDeviceOKCode int = 200 + +/* +GetDeviceOK Success + +swagger:response getDeviceOK +*/ +type GetDeviceOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetDeviceOK creates GetDeviceOK with default headers values +func NewGetDeviceOK() *GetDeviceOK { + + return &GetDeviceOK{} +} + +// WithPayload adds the payload to the get device o k response +func (o *GetDeviceOK) WithPayload(payload string) *GetDeviceOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get device o k response +func (o *GetDeviceOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetDeviceOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/get_device_urlbuilder.go new file mode 100644 index 000000000..87d5f1eab --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/get_device_urlbuilder.go @@ -0,0 +1,105 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + + "github.com/go-openapi/swag" +) + +// GetDeviceURL generates an URL for the get device operation +type GetDeviceURL struct { + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceURL) WithBasePath(bp string) *GetDeviceURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetDeviceURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetDeviceURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetDeviceURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetDeviceURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetDeviceURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetDeviceURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetDeviceURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetDeviceURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_addr.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr.go new file mode 100644 index 000000000..2d46e6c55 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameAddrHandlerFunc turns a function with the right signature into a put device name addr handler +type PutDeviceNameAddrHandlerFunc func(PutDeviceNameAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameAddrHandlerFunc) Handle(params PutDeviceNameAddrParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameAddrHandler interface for that can handle valid put device name addr params +type PutDeviceNameAddrHandler interface { + Handle(PutDeviceNameAddrParams) middleware.Responder +} + +// NewPutDeviceNameAddr creates a new http.Handler for the put device name addr operation +func NewPutDeviceNameAddr(ctx *middleware.Context, handler PutDeviceNameAddrHandler) *PutDeviceNameAddr { + return &PutDeviceNameAddr{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameAddr swagger:route PUT /device/{name}/addr device putDeviceNameAddr + +add/update special net device ip addr +*/ +type PutDeviceNameAddr struct { + Context *middleware.Context + Handler PutDeviceNameAddrHandler +} + +func (o *PutDeviceNameAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_parameters.go new file mode 100644 index 000000000..07bc411bb --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_parameters.go @@ -0,0 +1,145 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutDeviceNameAddrParams creates a new PutDeviceNameAddrParams object +// with the default values initialized. +func NewPutDeviceNameAddrParams() PutDeviceNameAddrParams { + + var ( + // initialize parameters with default values + + sapoolDefault = bool(false) + ) + + return PutDeviceNameAddrParams{ + Sapool: &sapoolDefault, + } +} + +// PutDeviceNameAddrParams contains all the bound params for the put device name addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameAddr +type PutDeviceNameAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: false + */ + Sapool *bool + /* + In: body + */ + Spec *models.InetAddrSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameAddrParams() beforehand. +func (o *PutDeviceNameAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qSapool, qhkSapool, _ := qs.GetOK("sapool") + if err := o.bindSapool(qSapool, qhkSapool, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.InetAddrSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindSapool binds and validates parameter Sapool from query. +func (o *PutDeviceNameAddrParams) bindSapool(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutDeviceNameAddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("sapool", "query", "bool", raw) + } + o.Sapool = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_responses.go new file mode 100644 index 000000000..417f1d91d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_responses.go @@ -0,0 +1,141 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameAddrOKCode is the HTTP code returned for type PutDeviceNameAddrOK +const PutDeviceNameAddrOKCode int = 200 + +/* +PutDeviceNameAddrOK Update exist ip addr Success + +swagger:response putDeviceNameAddrOK +*/ +type PutDeviceNameAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameAddrOK creates PutDeviceNameAddrOK with default headers values +func NewPutDeviceNameAddrOK() *PutDeviceNameAddrOK { + + return &PutDeviceNameAddrOK{} +} + +// WithPayload adds the payload to the put device name addr o k response +func (o *PutDeviceNameAddrOK) WithPayload(payload string) *PutDeviceNameAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name addr o k response +func (o *PutDeviceNameAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameAddrCreatedCode is the HTTP code returned for type PutDeviceNameAddrCreated +const PutDeviceNameAddrCreatedCode int = 201 + +/* +PutDeviceNameAddrCreated Add new ip addr Success + +swagger:response putDeviceNameAddrCreated +*/ +type PutDeviceNameAddrCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameAddrCreated creates PutDeviceNameAddrCreated with default headers values +func NewPutDeviceNameAddrCreated() *PutDeviceNameAddrCreated { + + return &PutDeviceNameAddrCreated{} +} + +// WithPayload adds the payload to the put device name addr created response +func (o *PutDeviceNameAddrCreated) WithPayload(payload string) *PutDeviceNameAddrCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name addr created response +func (o *PutDeviceNameAddrCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameAddrCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameAddrInternalServerErrorCode is the HTTP code returned for type PutDeviceNameAddrInternalServerError +const PutDeviceNameAddrInternalServerErrorCode int = 500 + +/* +PutDeviceNameAddrInternalServerError Failed + +swagger:response putDeviceNameAddrInternalServerError +*/ +type PutDeviceNameAddrInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameAddrInternalServerError creates PutDeviceNameAddrInternalServerError with default headers values +func NewPutDeviceNameAddrInternalServerError() *PutDeviceNameAddrInternalServerError { + + return &PutDeviceNameAddrInternalServerError{} +} + +// WithPayload adds the payload to the put device name addr internal server error response +func (o *PutDeviceNameAddrInternalServerError) WithPayload(payload string) *PutDeviceNameAddrInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name addr internal server error response +func (o *PutDeviceNameAddrInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameAddrInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_urlbuilder.go new file mode 100644 index 000000000..a136e39c6 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_addr_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// PutDeviceNameAddrURL generates an URL for the put device name addr operation +type PutDeviceNameAddrURL struct { + Name string + + Sapool *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameAddrURL) WithBasePath(bp string) *PutDeviceNameAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var sapoolQ string + if o.Sapool != nil { + sapoolQ = swag.FormatBool(*o.Sapool) + } + if sapoolQ != "" { + qs.Set("sapool", sapoolQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink.go new file mode 100644 index 000000000..41ba0fcd6 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameNetlinkHandlerFunc turns a function with the right signature into a put device name netlink handler +type PutDeviceNameNetlinkHandlerFunc func(PutDeviceNameNetlinkParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameNetlinkHandlerFunc) Handle(params PutDeviceNameNetlinkParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameNetlinkHandler interface for that can handle valid put device name netlink params +type PutDeviceNameNetlinkHandler interface { + Handle(PutDeviceNameNetlinkParams) middleware.Responder +} + +// NewPutDeviceNameNetlink creates a new http.Handler for the put device name netlink operation +func NewPutDeviceNameNetlink(ctx *middleware.Context, handler PutDeviceNameNetlinkHandler) *PutDeviceNameNetlink { + return &PutDeviceNameNetlink{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameNetlink swagger:route PUT /device/{name}/netlink device putDeviceNameNetlink + +ip link set ${name} up +*/ +type PutDeviceNameNetlink struct { + Context *middleware.Context + Handler PutDeviceNameNetlinkHandler +} + +func (o *PutDeviceNameNetlink) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameNetlinkParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go new file mode 100644 index 000000000..b08ea86b7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameNetlinkAddrHandlerFunc turns a function with the right signature into a put device name netlink addr handler +type PutDeviceNameNetlinkAddrHandlerFunc func(PutDeviceNameNetlinkAddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameNetlinkAddrHandlerFunc) Handle(params PutDeviceNameNetlinkAddrParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameNetlinkAddrHandler interface for that can handle valid put device name netlink addr params +type PutDeviceNameNetlinkAddrHandler interface { + Handle(PutDeviceNameNetlinkAddrParams) middleware.Responder +} + +// NewPutDeviceNameNetlinkAddr creates a new http.Handler for the put device name netlink addr operation +func NewPutDeviceNameNetlinkAddr(ctx *middleware.Context, handler PutDeviceNameNetlinkAddrHandler) *PutDeviceNameNetlinkAddr { + return &PutDeviceNameNetlinkAddr{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameNetlinkAddr swagger:route PUT /device/{name}/netlink/addr device putDeviceNameNetlinkAddr + +set ip cird to linux net device +*/ +type PutDeviceNameNetlinkAddr struct { + Context *middleware.Context + Handler PutDeviceNameNetlinkAddrHandler +} + +func (o *PutDeviceNameNetlinkAddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameNetlinkAddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_parameters.go new file mode 100644 index 000000000..7fcd77b11 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutDeviceNameNetlinkAddrParams creates a new PutDeviceNameNetlinkAddrParams object +// +// There are no default values defined in the spec. +func NewPutDeviceNameNetlinkAddrParams() PutDeviceNameNetlinkAddrParams { + + return PutDeviceNameNetlinkAddrParams{} +} + +// PutDeviceNameNetlinkAddrParams contains all the bound params for the put device name netlink addr operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameNetlinkAddr +type PutDeviceNameNetlinkAddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.InetAddrSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameNetlinkAddrParams() beforehand. +func (o *PutDeviceNameNetlinkAddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.InetAddrSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameNetlinkAddrParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_responses.go new file mode 100644 index 000000000..b0287d36b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameNetlinkAddrOKCode is the HTTP code returned for type PutDeviceNameNetlinkAddrOK +const PutDeviceNameNetlinkAddrOKCode int = 200 + +/* +PutDeviceNameNetlinkAddrOK Success + +swagger:response putDeviceNameNetlinkAddrOK +*/ +type PutDeviceNameNetlinkAddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNetlinkAddrOK creates PutDeviceNameNetlinkAddrOK with default headers values +func NewPutDeviceNameNetlinkAddrOK() *PutDeviceNameNetlinkAddrOK { + + return &PutDeviceNameNetlinkAddrOK{} +} + +// WithPayload adds the payload to the put device name netlink addr o k response +func (o *PutDeviceNameNetlinkAddrOK) WithPayload(payload string) *PutDeviceNameNetlinkAddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name netlink addr o k response +func (o *PutDeviceNameNetlinkAddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNetlinkAddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameNetlinkAddrInternalServerErrorCode is the HTTP code returned for type PutDeviceNameNetlinkAddrInternalServerError +const PutDeviceNameNetlinkAddrInternalServerErrorCode int = 500 + +/* +PutDeviceNameNetlinkAddrInternalServerError Not Found + +swagger:response putDeviceNameNetlinkAddrInternalServerError +*/ +type PutDeviceNameNetlinkAddrInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNetlinkAddrInternalServerError creates PutDeviceNameNetlinkAddrInternalServerError with default headers values +func NewPutDeviceNameNetlinkAddrInternalServerError() *PutDeviceNameNetlinkAddrInternalServerError { + + return &PutDeviceNameNetlinkAddrInternalServerError{} +} + +// WithPayload adds the payload to the put device name netlink addr internal server error response +func (o *PutDeviceNameNetlinkAddrInternalServerError) WithPayload(payload string) *PutDeviceNameNetlinkAddrInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name netlink addr internal server error response +func (o *PutDeviceNameNetlinkAddrInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNetlinkAddrInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_urlbuilder.go new file mode 100644 index 000000000..ef47a83b2 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameNetlinkAddrURL generates an URL for the put device name netlink addr operation +type PutDeviceNameNetlinkAddrURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNetlinkAddrURL) WithBasePath(bp string) *PutDeviceNameNetlinkAddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNetlinkAddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameNetlinkAddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink/addr" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameNetlinkAddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameNetlinkAddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameNetlinkAddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameNetlinkAddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameNetlinkAddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameNetlinkAddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameNetlinkAddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_parameters.go new file mode 100644 index 000000000..d8d9e20f1 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewPutDeviceNameNetlinkParams creates a new PutDeviceNameNetlinkParams object +// +// There are no default values defined in the spec. +func NewPutDeviceNameNetlinkParams() PutDeviceNameNetlinkParams { + + return PutDeviceNameNetlinkParams{} +} + +// PutDeviceNameNetlinkParams contains all the bound params for the put device name netlink operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameNetlink +type PutDeviceNameNetlinkParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameNetlinkParams() beforehand. +func (o *PutDeviceNameNetlinkParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameNetlinkParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_responses.go new file mode 100644 index 000000000..ba2a6d07f --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameNetlinkOKCode is the HTTP code returned for type PutDeviceNameNetlinkOK +const PutDeviceNameNetlinkOKCode int = 200 + +/* +PutDeviceNameNetlinkOK Success + +swagger:response putDeviceNameNetlinkOK +*/ +type PutDeviceNameNetlinkOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNetlinkOK creates PutDeviceNameNetlinkOK with default headers values +func NewPutDeviceNameNetlinkOK() *PutDeviceNameNetlinkOK { + + return &PutDeviceNameNetlinkOK{} +} + +// WithPayload adds the payload to the put device name netlink o k response +func (o *PutDeviceNameNetlinkOK) WithPayload(payload string) *PutDeviceNameNetlinkOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name netlink o k response +func (o *PutDeviceNameNetlinkOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNetlinkOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameNetlinkInternalServerErrorCode is the HTTP code returned for type PutDeviceNameNetlinkInternalServerError +const PutDeviceNameNetlinkInternalServerErrorCode int = 500 + +/* +PutDeviceNameNetlinkInternalServerError Not Found + +swagger:response putDeviceNameNetlinkInternalServerError +*/ +type PutDeviceNameNetlinkInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNetlinkInternalServerError creates PutDeviceNameNetlinkInternalServerError with default headers values +func NewPutDeviceNameNetlinkInternalServerError() *PutDeviceNameNetlinkInternalServerError { + + return &PutDeviceNameNetlinkInternalServerError{} +} + +// WithPayload adds the payload to the put device name netlink internal server error response +func (o *PutDeviceNameNetlinkInternalServerError) WithPayload(payload string) *PutDeviceNameNetlinkInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name netlink internal server error response +func (o *PutDeviceNameNetlinkInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNetlinkInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_urlbuilder.go new file mode 100644 index 000000000..1b636026c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameNetlinkURL generates an URL for the put device name netlink operation +type PutDeviceNameNetlinkURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNetlinkURL) WithBasePath(bp string) *PutDeviceNameNetlinkURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNetlinkURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameNetlinkURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/netlink" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameNetlinkURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameNetlinkURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameNetlinkURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameNetlinkURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameNetlinkURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameNetlinkURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameNetlinkURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic.go new file mode 100644 index 000000000..4bf05efd7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameNicHandlerFunc turns a function with the right signature into a put device name nic handler +type PutDeviceNameNicHandlerFunc func(PutDeviceNameNicParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameNicHandlerFunc) Handle(params PutDeviceNameNicParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameNicHandler interface for that can handle valid put device name nic params +type PutDeviceNameNicHandler interface { + Handle(PutDeviceNameNicParams) middleware.Responder +} + +// NewPutDeviceNameNic creates a new http.Handler for the put device name nic operation +func NewPutDeviceNameNic(ctx *middleware.Context, handler PutDeviceNameNicHandler) *PutDeviceNameNic { + return &PutDeviceNameNic{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameNic swagger:route PUT /device/{name}/nic device putDeviceNameNic + +dpip link set ${nic-name} [forward2kni,link,promisc,tc-ingress,tc-egress] [on/up,off/down] +*/ +type PutDeviceNameNic struct { + Context *middleware.Context + Handler PutDeviceNameNicHandler +} + +func (o *PutDeviceNameNic) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameNicParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go new file mode 100644 index 000000000..a8cd915e3 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go @@ -0,0 +1,218 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// NewPutDeviceNameNicParams creates a new PutDeviceNameNicParams object +// with the default values initialized. +func NewPutDeviceNameNicParams() PutDeviceNameNicParams { + + var ( + // initialize parameters with default values + + forward2KniDefault = string("unset") + linkDefault = string("unset") + + promiscDefault = string("unset") + ) + + return PutDeviceNameNicParams{ + Forward2Kni: &forward2KniDefault, + + Link: &linkDefault, + + Promisc: &promiscDefault, + } +} + +// PutDeviceNameNicParams contains all the bound params for the put device name nic operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameNic +type PutDeviceNameNicParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: query + Default: "unset" + */ + Forward2Kni *string + /* + In: query + Default: "unset" + */ + Link *string + /* + Required: true + In: path + */ + Name string + /* + In: query + Default: "unset" + */ + Promisc *string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameNicParams() beforehand. +func (o *PutDeviceNameNicParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + qForward2Kni, qhkForward2Kni, _ := qs.GetOK("forward2Kni") + if err := o.bindForward2Kni(qForward2Kni, qhkForward2Kni, route.Formats); err != nil { + res = append(res, err) + } + + qLink, qhkLink, _ := qs.GetOK("link") + if err := o.bindLink(qLink, qhkLink, route.Formats); err != nil { + res = append(res, err) + } + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + qPromisc, qhkPromisc, _ := qs.GetOK("promisc") + if err := o.bindPromisc(qPromisc, qhkPromisc, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindForward2Kni binds and validates parameter Forward2Kni from query. +func (o *PutDeviceNameNicParams) bindForward2Kni(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutDeviceNameNicParams() + return nil + } + o.Forward2Kni = &raw + + if err := o.validateForward2Kni(formats); err != nil { + return err + } + + return nil +} + +// validateForward2Kni carries on validations for parameter Forward2Kni +func (o *PutDeviceNameNicParams) validateForward2Kni(formats strfmt.Registry) error { + + if err := validate.EnumCase("forward2Kni", "query", *o.Forward2Kni, []interface{}{"unset", "on", "off"}, true); err != nil { + return err + } + + return nil +} + +// bindLink binds and validates parameter Link from query. +func (o *PutDeviceNameNicParams) bindLink(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutDeviceNameNicParams() + return nil + } + o.Link = &raw + + if err := o.validateLink(formats); err != nil { + return err + } + + return nil +} + +// validateLink carries on validations for parameter Link +func (o *PutDeviceNameNicParams) validateLink(formats strfmt.Registry) error { + + if err := validate.EnumCase("link", "query", *o.Link, []interface{}{"unset", "up", "down"}, true); err != nil { + return err + } + + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameNicParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} + +// bindPromisc binds and validates parameter Promisc from query. +func (o *PutDeviceNameNicParams) bindPromisc(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutDeviceNameNicParams() + return nil + } + o.Promisc = &raw + + if err := o.validatePromisc(formats); err != nil { + return err + } + + return nil +} + +// validatePromisc carries on validations for parameter Promisc +func (o *PutDeviceNameNicParams) validatePromisc(formats strfmt.Registry) error { + + if err := validate.EnumCase("promisc", "query", *o.Promisc, []interface{}{"unset", "on", "off"}, true); err != nil { + return err + } + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_responses.go new file mode 100644 index 000000000..2ca881446 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameNicOKCode is the HTTP code returned for type PutDeviceNameNicOK +const PutDeviceNameNicOKCode int = 200 + +/* +PutDeviceNameNicOK Success + +swagger:response putDeviceNameNicOK +*/ +type PutDeviceNameNicOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNicOK creates PutDeviceNameNicOK with default headers values +func NewPutDeviceNameNicOK() *PutDeviceNameNicOK { + + return &PutDeviceNameNicOK{} +} + +// WithPayload adds the payload to the put device name nic o k response +func (o *PutDeviceNameNicOK) WithPayload(payload string) *PutDeviceNameNicOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name nic o k response +func (o *PutDeviceNameNicOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNicOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameNicInternalServerErrorCode is the HTTP code returned for type PutDeviceNameNicInternalServerError +const PutDeviceNameNicInternalServerErrorCode int = 500 + +/* +PutDeviceNameNicInternalServerError Failure + +swagger:response putDeviceNameNicInternalServerError +*/ +type PutDeviceNameNicInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameNicInternalServerError creates PutDeviceNameNicInternalServerError with default headers values +func NewPutDeviceNameNicInternalServerError() *PutDeviceNameNicInternalServerError { + + return &PutDeviceNameNicInternalServerError{} +} + +// WithPayload adds the payload to the put device name nic internal server error response +func (o *PutDeviceNameNicInternalServerError) WithPayload(payload string) *PutDeviceNameNicInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name nic internal server error response +func (o *PutDeviceNameNicInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameNicInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_urlbuilder.go new file mode 100644 index 000000000..865956941 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_urlbuilder.go @@ -0,0 +1,131 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameNicURL generates an URL for the put device name nic operation +type PutDeviceNameNicURL struct { + Name string + + Forward2Kni *string + Link *string + Promisc *string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNicURL) WithBasePath(bp string) *PutDeviceNameNicURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameNicURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameNicURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/nic" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameNicURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var forward2KniQ string + if o.Forward2Kni != nil { + forward2KniQ = *o.Forward2Kni + } + if forward2KniQ != "" { + qs.Set("forward2Kni", forward2KniQ) + } + + var linkQ string + if o.Link != nil { + linkQ = *o.Link + } + if linkQ != "" { + qs.Set("link", linkQ) + } + + var promiscQ string + if o.Promisc != nil { + promiscQ = *o.Promisc + } + if promiscQ != "" { + qs.Set("promisc", promiscQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameNicURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameNicURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameNicURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameNicURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameNicURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameNicURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_route.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_route.go new file mode 100644 index 000000000..e5b7940c5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_route.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameRouteHandlerFunc turns a function with the right signature into a put device name route handler +type PutDeviceNameRouteHandlerFunc func(PutDeviceNameRouteParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameRouteHandlerFunc) Handle(params PutDeviceNameRouteParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameRouteHandler interface for that can handle valid put device name route params +type PutDeviceNameRouteHandler interface { + Handle(PutDeviceNameRouteParams) middleware.Responder +} + +// NewPutDeviceNameRoute creates a new http.Handler for the put device name route operation +func NewPutDeviceNameRoute(ctx *middleware.Context, handler PutDeviceNameRouteHandler) *PutDeviceNameRoute { + return &PutDeviceNameRoute{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameRoute swagger:route PUT /device/{name}/route device putDeviceNameRoute + +add/update special net device route +*/ +type PutDeviceNameRoute struct { + Context *middleware.Context + Handler PutDeviceNameRouteHandler +} + +func (o *PutDeviceNameRoute) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameRouteParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_route_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_parameters.go new file mode 100644 index 000000000..29831e533 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutDeviceNameRouteParams creates a new PutDeviceNameRouteParams object +// +// There are no default values defined in the spec. +func NewPutDeviceNameRouteParams() PutDeviceNameRouteParams { + + return PutDeviceNameRouteParams{} +} + +// PutDeviceNameRouteParams contains all the bound params for the put device name route operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameRoute +type PutDeviceNameRouteParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.RouteSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameRouteParams() beforehand. +func (o *PutDeviceNameRouteParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RouteSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameRouteParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_route_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_responses.go new file mode 100644 index 000000000..87f0b47ed --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_responses.go @@ -0,0 +1,141 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameRouteOKCode is the HTTP code returned for type PutDeviceNameRouteOK +const PutDeviceNameRouteOKCode int = 200 + +/* +PutDeviceNameRouteOK Update exist route Success + +swagger:response putDeviceNameRouteOK +*/ +type PutDeviceNameRouteOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameRouteOK creates PutDeviceNameRouteOK with default headers values +func NewPutDeviceNameRouteOK() *PutDeviceNameRouteOK { + + return &PutDeviceNameRouteOK{} +} + +// WithPayload adds the payload to the put device name route o k response +func (o *PutDeviceNameRouteOK) WithPayload(payload string) *PutDeviceNameRouteOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name route o k response +func (o *PutDeviceNameRouteOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameRouteOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameRouteCreatedCode is the HTTP code returned for type PutDeviceNameRouteCreated +const PutDeviceNameRouteCreatedCode int = 201 + +/* +PutDeviceNameRouteCreated Add new route Success + +swagger:response putDeviceNameRouteCreated +*/ +type PutDeviceNameRouteCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameRouteCreated creates PutDeviceNameRouteCreated with default headers values +func NewPutDeviceNameRouteCreated() *PutDeviceNameRouteCreated { + + return &PutDeviceNameRouteCreated{} +} + +// WithPayload adds the payload to the put device name route created response +func (o *PutDeviceNameRouteCreated) WithPayload(payload string) *PutDeviceNameRouteCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name route created response +func (o *PutDeviceNameRouteCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameRouteCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameRouteInternalServerErrorCode is the HTTP code returned for type PutDeviceNameRouteInternalServerError +const PutDeviceNameRouteInternalServerErrorCode int = 500 + +/* +PutDeviceNameRouteInternalServerError Failed + +swagger:response putDeviceNameRouteInternalServerError +*/ +type PutDeviceNameRouteInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameRouteInternalServerError creates PutDeviceNameRouteInternalServerError with default headers values +func NewPutDeviceNameRouteInternalServerError() *PutDeviceNameRouteInternalServerError { + + return &PutDeviceNameRouteInternalServerError{} +} + +// WithPayload adds the payload to the put device name route internal server error response +func (o *PutDeviceNameRouteInternalServerError) WithPayload(payload string) *PutDeviceNameRouteInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name route internal server error response +func (o *PutDeviceNameRouteInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameRouteInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_route_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_urlbuilder.go new file mode 100644 index 000000000..3776a3036 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_route_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameRouteURL generates an URL for the put device name route operation +type PutDeviceNameRouteURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameRouteURL) WithBasePath(bp string) *PutDeviceNameRouteURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameRouteURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameRouteURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/route" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameRouteURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameRouteURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameRouteURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameRouteURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameRouteURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameRouteURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameRouteURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan.go new file mode 100644 index 000000000..dd519e482 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutDeviceNameVlanHandlerFunc turns a function with the right signature into a put device name vlan handler +type PutDeviceNameVlanHandlerFunc func(PutDeviceNameVlanParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutDeviceNameVlanHandlerFunc) Handle(params PutDeviceNameVlanParams) middleware.Responder { + return fn(params) +} + +// PutDeviceNameVlanHandler interface for that can handle valid put device name vlan params +type PutDeviceNameVlanHandler interface { + Handle(PutDeviceNameVlanParams) middleware.Responder +} + +// NewPutDeviceNameVlan creates a new http.Handler for the put device name vlan operation +func NewPutDeviceNameVlan(ctx *middleware.Context, handler PutDeviceNameVlanHandler) *PutDeviceNameVlan { + return &PutDeviceNameVlan{Context: ctx, Handler: handler} +} + +/* + PutDeviceNameVlan swagger:route PUT /device/{name}/vlan device putDeviceNameVlan + +add/update special net device +*/ +type PutDeviceNameVlan struct { + Context *middleware.Context + Handler PutDeviceNameVlanHandler +} + +func (o *PutDeviceNameVlan) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutDeviceNameVlanParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_parameters.go new file mode 100644 index 000000000..63c5965c5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutDeviceNameVlanParams creates a new PutDeviceNameVlanParams object +// +// There are no default values defined in the spec. +func NewPutDeviceNameVlanParams() PutDeviceNameVlanParams { + + return PutDeviceNameVlanParams{} +} + +// PutDeviceNameVlanParams contains all the bound params for the put device name vlan operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutDeviceNameVlan +type PutDeviceNameVlanParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + Name string + /* + In: body + */ + Spec *models.VlanSpec +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutDeviceNameVlanParams() beforehand. +func (o *PutDeviceNameVlanParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rName, rhkName, _ := route.Params.GetOK("name") + if err := o.bindName(rName, rhkName, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.VlanSpec + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindName binds and validates parameter Name from path. +func (o *PutDeviceNameVlanParams) bindName(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.Name = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_responses.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_responses.go new file mode 100644 index 000000000..241b8ef3d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// PutDeviceNameVlanOKCode is the HTTP code returned for type PutDeviceNameVlanOK +const PutDeviceNameVlanOKCode int = 200 + +/* +PutDeviceNameVlanOK Success + +swagger:response putDeviceNameVlanOK +*/ +type PutDeviceNameVlanOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameVlanOK creates PutDeviceNameVlanOK with default headers values +func NewPutDeviceNameVlanOK() *PutDeviceNameVlanOK { + + return &PutDeviceNameVlanOK{} +} + +// WithPayload adds the payload to the put device name vlan o k response +func (o *PutDeviceNameVlanOK) WithPayload(payload string) *PutDeviceNameVlanOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name vlan o k response +func (o *PutDeviceNameVlanOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameVlanOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutDeviceNameVlanInternalServerErrorCode is the HTTP code returned for type PutDeviceNameVlanInternalServerError +const PutDeviceNameVlanInternalServerErrorCode int = 500 + +/* +PutDeviceNameVlanInternalServerError Failed + +swagger:response putDeviceNameVlanInternalServerError +*/ +type PutDeviceNameVlanInternalServerError struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutDeviceNameVlanInternalServerError creates PutDeviceNameVlanInternalServerError with default headers values +func NewPutDeviceNameVlanInternalServerError() *PutDeviceNameVlanInternalServerError { + + return &PutDeviceNameVlanInternalServerError{} +} + +// WithPayload adds the payload to the put device name vlan internal server error response +func (o *PutDeviceNameVlanInternalServerError) WithPayload(payload string) *PutDeviceNameVlanInternalServerError { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put device name vlan internal server error response +func (o *PutDeviceNameVlanInternalServerError) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutDeviceNameVlanInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_urlbuilder.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_urlbuilder.go new file mode 100644 index 000000000..2892d676c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_vlan_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package device + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutDeviceNameVlanURL generates an URL for the put device name vlan operation +type PutDeviceNameVlanURL struct { + Name string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameVlanURL) WithBasePath(bp string) *PutDeviceNameVlanURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutDeviceNameVlanURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutDeviceNameVlanURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/device/{name}/vlan" + + name := o.Name + if name != "" { + _path = strings.Replace(_path, "{name}", name, -1) + } else { + return nil, errors.New("name is required on PutDeviceNameVlanURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutDeviceNameVlanURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutDeviceNameVlanURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutDeviceNameVlanURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutDeviceNameVlanURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutDeviceNameVlanURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutDeviceNameVlanURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/dpvs_agent_api.go b/tools/dpvs-agent/restapi/operations/dpvs_agent_api.go new file mode 100644 index 000000000..5421e4aa7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/dpvs_agent_api.go @@ -0,0 +1,736 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package operations + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "fmt" + "net/http" + "strings" + + "github.com/go-openapi/errors" + "github.com/go-openapi/loads" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/runtime/security" + "github.com/go-openapi/spec" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + + "github.com/dpvs-agent/restapi/operations/device" + "github.com/dpvs-agent/restapi/operations/virtualserver" +) + +// NewDpvsAgentAPI creates a new DpvsAgent instance +func NewDpvsAgentAPI(spec *loads.Document) *DpvsAgentAPI { + return &DpvsAgentAPI{ + handlers: make(map[string]map[string]http.Handler), + formats: strfmt.Default, + defaultConsumes: "application/json", + defaultProduces: "application/json", + customConsumers: make(map[string]runtime.Consumer), + customProducers: make(map[string]runtime.Producer), + PreServerShutdown: func() {}, + ServerShutdown: func() {}, + spec: spec, + useSwaggerUI: false, + ServeError: errors.ServeError, + BasicAuthenticator: security.BasicAuth, + APIKeyAuthenticator: security.APIKeyAuth, + BearerAuthenticator: security.BearerAuth, + + JSONConsumer: runtime.JSONConsumer(), + + JSONProducer: runtime.JSONProducer(), + + DeviceDeleteDeviceNameAddrHandler: device.DeleteDeviceNameAddrHandlerFunc(func(params device.DeleteDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameAddr has not yet been implemented") + }), + DeviceDeleteDeviceNameNetlinkHandler: device.DeleteDeviceNameNetlinkHandlerFunc(func(params device.DeleteDeviceNameNetlinkParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameNetlink has not yet been implemented") + }), + DeviceDeleteDeviceNameNetlinkAddrHandler: device.DeleteDeviceNameNetlinkAddrHandlerFunc(func(params device.DeleteDeviceNameNetlinkAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameNetlinkAddr has not yet been implemented") + }), + DeviceDeleteDeviceNameRouteHandler: device.DeleteDeviceNameRouteHandlerFunc(func(params device.DeleteDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameRoute has not yet been implemented") + }), + DeviceDeleteDeviceNameVlanHandler: device.DeleteDeviceNameVlanHandlerFunc(func(params device.DeleteDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.DeleteDeviceNameVlan has not yet been implemented") + }), + VirtualserverDeleteVsVipPortHandler: virtualserver.DeleteVsVipPortHandlerFunc(func(params virtualserver.DeleteVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPort has not yet been implemented") + }), + VirtualserverDeleteVsVipPortAllowHandler: virtualserver.DeleteVsVipPortAllowHandlerFunc(func(params virtualserver.DeleteVsVipPortAllowParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortAllow has not yet been implemented") + }), + VirtualserverDeleteVsVipPortDenyHandler: virtualserver.DeleteVsVipPortDenyHandlerFunc(func(params virtualserver.DeleteVsVipPortDenyParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortDeny has not yet been implemented") + }), + VirtualserverDeleteVsVipPortLaddrHandler: virtualserver.DeleteVsVipPortLaddrHandlerFunc(func(params virtualserver.DeleteVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortLaddr has not yet been implemented") + }), + VirtualserverDeleteVsVipPortRsHandler: virtualserver.DeleteVsVipPortRsHandlerFunc(func(params virtualserver.DeleteVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.DeleteVsVipPortRs has not yet been implemented") + }), + DeviceGetDeviceHandler: device.GetDeviceHandlerFunc(func(params device.GetDeviceParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDevice has not yet been implemented") + }), + DeviceGetDeviceNameAddrHandler: device.GetDeviceNameAddrHandlerFunc(func(params device.GetDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameAddr has not yet been implemented") + }), + DeviceGetDeviceNameNetlinkHandler: device.GetDeviceNameNetlinkHandlerFunc(func(params device.GetDeviceNameNetlinkParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameNetlink has not yet been implemented") + }), + DeviceGetDeviceNameNetlinkAddrHandler: device.GetDeviceNameNetlinkAddrHandlerFunc(func(params device.GetDeviceNameNetlinkAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameNetlinkAddr has not yet been implemented") + }), + DeviceGetDeviceNameNicHandler: device.GetDeviceNameNicHandlerFunc(func(params device.GetDeviceNameNicParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameNic has not yet been implemented") + }), + DeviceGetDeviceNameRouteHandler: device.GetDeviceNameRouteHandlerFunc(func(params device.GetDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameRoute has not yet been implemented") + }), + DeviceGetDeviceNameVlanHandler: device.GetDeviceNameVlanHandlerFunc(func(params device.GetDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.GetDeviceNameVlan has not yet been implemented") + }), + VirtualserverGetVsHandler: virtualserver.GetVsHandlerFunc(func(params virtualserver.GetVsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVs has not yet been implemented") + }), + VirtualserverGetVsVipPortHandler: virtualserver.GetVsVipPortHandlerFunc(func(params virtualserver.GetVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPort has not yet been implemented") + }), + VirtualserverGetVsVipPortAllowHandler: virtualserver.GetVsVipPortAllowHandlerFunc(func(params virtualserver.GetVsVipPortAllowParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortAllow has not yet been implemented") + }), + VirtualserverGetVsVipPortDenyHandler: virtualserver.GetVsVipPortDenyHandlerFunc(func(params virtualserver.GetVsVipPortDenyParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortDeny has not yet been implemented") + }), + VirtualserverGetVsVipPortLaddrHandler: virtualserver.GetVsVipPortLaddrHandlerFunc(func(params virtualserver.GetVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortLaddr has not yet been implemented") + }), + VirtualserverGetVsVipPortRsHandler: virtualserver.GetVsVipPortRsHandlerFunc(func(params virtualserver.GetVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.GetVsVipPortRs has not yet been implemented") + }), + VirtualserverPostVsVipPortAllowHandler: virtualserver.PostVsVipPortAllowHandlerFunc(func(params virtualserver.PostVsVipPortAllowParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PostVsVipPortAllow has not yet been implemented") + }), + VirtualserverPostVsVipPortDenyHandler: virtualserver.PostVsVipPortDenyHandlerFunc(func(params virtualserver.PostVsVipPortDenyParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PostVsVipPortDeny has not yet been implemented") + }), + VirtualserverPostVsVipPortRsHandler: virtualserver.PostVsVipPortRsHandlerFunc(func(params virtualserver.PostVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PostVsVipPortRs has not yet been implemented") + }), + DevicePutDeviceNameAddrHandler: device.PutDeviceNameAddrHandlerFunc(func(params device.PutDeviceNameAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameAddr has not yet been implemented") + }), + DevicePutDeviceNameNetlinkHandler: device.PutDeviceNameNetlinkHandlerFunc(func(params device.PutDeviceNameNetlinkParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameNetlink has not yet been implemented") + }), + DevicePutDeviceNameNetlinkAddrHandler: device.PutDeviceNameNetlinkAddrHandlerFunc(func(params device.PutDeviceNameNetlinkAddrParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameNetlinkAddr has not yet been implemented") + }), + DevicePutDeviceNameNicHandler: device.PutDeviceNameNicHandlerFunc(func(params device.PutDeviceNameNicParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameNic has not yet been implemented") + }), + DevicePutDeviceNameRouteHandler: device.PutDeviceNameRouteHandlerFunc(func(params device.PutDeviceNameRouteParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameRoute has not yet been implemented") + }), + DevicePutDeviceNameVlanHandler: device.PutDeviceNameVlanHandlerFunc(func(params device.PutDeviceNameVlanParams) middleware.Responder { + return middleware.NotImplemented("operation device.PutDeviceNameVlan has not yet been implemented") + }), + VirtualserverPutVsVipPortHandler: virtualserver.PutVsVipPortHandlerFunc(func(params virtualserver.PutVsVipPortParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPort has not yet been implemented") + }), + VirtualserverPutVsVipPortAllowHandler: virtualserver.PutVsVipPortAllowHandlerFunc(func(params virtualserver.PutVsVipPortAllowParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortAllow has not yet been implemented") + }), + VirtualserverPutVsVipPortDenyHandler: virtualserver.PutVsVipPortDenyHandlerFunc(func(params virtualserver.PutVsVipPortDenyParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortDeny has not yet been implemented") + }), + VirtualserverPutVsVipPortLaddrHandler: virtualserver.PutVsVipPortLaddrHandlerFunc(func(params virtualserver.PutVsVipPortLaddrParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortLaddr has not yet been implemented") + }), + VirtualserverPutVsVipPortRsHandler: virtualserver.PutVsVipPortRsHandlerFunc(func(params virtualserver.PutVsVipPortRsParams) middleware.Responder { + return middleware.NotImplemented("operation virtualserver.PutVsVipPortRs has not yet been implemented") + }), + } +} + +/*DpvsAgentAPI dpvs agent api */ +type DpvsAgentAPI struct { + spec *loads.Document + context *middleware.Context + handlers map[string]map[string]http.Handler + formats strfmt.Registry + customConsumers map[string]runtime.Consumer + customProducers map[string]runtime.Producer + defaultConsumes string + defaultProduces string + Middleware func(middleware.Builder) http.Handler + useSwaggerUI bool + + // BasicAuthenticator generates a runtime.Authenticator from the supplied basic auth function. + // It has a default implementation in the security package, however you can replace it for your particular usage. + BasicAuthenticator func(security.UserPassAuthentication) runtime.Authenticator + + // APIKeyAuthenticator generates a runtime.Authenticator from the supplied token auth function. + // It has a default implementation in the security package, however you can replace it for your particular usage. + APIKeyAuthenticator func(string, string, security.TokenAuthentication) runtime.Authenticator + + // BearerAuthenticator generates a runtime.Authenticator from the supplied bearer token auth function. + // It has a default implementation in the security package, however you can replace it for your particular usage. + BearerAuthenticator func(string, security.ScopedTokenAuthentication) runtime.Authenticator + + // JSONConsumer registers a consumer for the following mime types: + // - application/json + JSONConsumer runtime.Consumer + + // JSONProducer registers a producer for the following mime types: + // - application/json + JSONProducer runtime.Producer + + // DeviceDeleteDeviceNameAddrHandler sets the operation handler for the delete device name addr operation + DeviceDeleteDeviceNameAddrHandler device.DeleteDeviceNameAddrHandler + // DeviceDeleteDeviceNameNetlinkHandler sets the operation handler for the delete device name netlink operation + DeviceDeleteDeviceNameNetlinkHandler device.DeleteDeviceNameNetlinkHandler + // DeviceDeleteDeviceNameNetlinkAddrHandler sets the operation handler for the delete device name netlink addr operation + DeviceDeleteDeviceNameNetlinkAddrHandler device.DeleteDeviceNameNetlinkAddrHandler + // DeviceDeleteDeviceNameRouteHandler sets the operation handler for the delete device name route operation + DeviceDeleteDeviceNameRouteHandler device.DeleteDeviceNameRouteHandler + // DeviceDeleteDeviceNameVlanHandler sets the operation handler for the delete device name vlan operation + DeviceDeleteDeviceNameVlanHandler device.DeleteDeviceNameVlanHandler + // VirtualserverDeleteVsVipPortHandler sets the operation handler for the delete vs vip port operation + VirtualserverDeleteVsVipPortHandler virtualserver.DeleteVsVipPortHandler + // VirtualserverDeleteVsVipPortAllowHandler sets the operation handler for the delete vs vip port allow operation + VirtualserverDeleteVsVipPortAllowHandler virtualserver.DeleteVsVipPortAllowHandler + // VirtualserverDeleteVsVipPortDenyHandler sets the operation handler for the delete vs vip port deny operation + VirtualserverDeleteVsVipPortDenyHandler virtualserver.DeleteVsVipPortDenyHandler + // VirtualserverDeleteVsVipPortLaddrHandler sets the operation handler for the delete vs vip port laddr operation + VirtualserverDeleteVsVipPortLaddrHandler virtualserver.DeleteVsVipPortLaddrHandler + // VirtualserverDeleteVsVipPortRsHandler sets the operation handler for the delete vs vip port rs operation + VirtualserverDeleteVsVipPortRsHandler virtualserver.DeleteVsVipPortRsHandler + // DeviceGetDeviceHandler sets the operation handler for the get device operation + DeviceGetDeviceHandler device.GetDeviceHandler + // DeviceGetDeviceNameAddrHandler sets the operation handler for the get device name addr operation + DeviceGetDeviceNameAddrHandler device.GetDeviceNameAddrHandler + // DeviceGetDeviceNameNetlinkHandler sets the operation handler for the get device name netlink operation + DeviceGetDeviceNameNetlinkHandler device.GetDeviceNameNetlinkHandler + // DeviceGetDeviceNameNetlinkAddrHandler sets the operation handler for the get device name netlink addr operation + DeviceGetDeviceNameNetlinkAddrHandler device.GetDeviceNameNetlinkAddrHandler + // DeviceGetDeviceNameNicHandler sets the operation handler for the get device name nic operation + DeviceGetDeviceNameNicHandler device.GetDeviceNameNicHandler + // DeviceGetDeviceNameRouteHandler sets the operation handler for the get device name route operation + DeviceGetDeviceNameRouteHandler device.GetDeviceNameRouteHandler + // DeviceGetDeviceNameVlanHandler sets the operation handler for the get device name vlan operation + DeviceGetDeviceNameVlanHandler device.GetDeviceNameVlanHandler + // VirtualserverGetVsHandler sets the operation handler for the get vs operation + VirtualserverGetVsHandler virtualserver.GetVsHandler + // VirtualserverGetVsVipPortHandler sets the operation handler for the get vs vip port operation + VirtualserverGetVsVipPortHandler virtualserver.GetVsVipPortHandler + // VirtualserverGetVsVipPortAllowHandler sets the operation handler for the get vs vip port allow operation + VirtualserverGetVsVipPortAllowHandler virtualserver.GetVsVipPortAllowHandler + // VirtualserverGetVsVipPortDenyHandler sets the operation handler for the get vs vip port deny operation + VirtualserverGetVsVipPortDenyHandler virtualserver.GetVsVipPortDenyHandler + // VirtualserverGetVsVipPortLaddrHandler sets the operation handler for the get vs vip port laddr operation + VirtualserverGetVsVipPortLaddrHandler virtualserver.GetVsVipPortLaddrHandler + // VirtualserverGetVsVipPortRsHandler sets the operation handler for the get vs vip port rs operation + VirtualserverGetVsVipPortRsHandler virtualserver.GetVsVipPortRsHandler + // VirtualserverPostVsVipPortAllowHandler sets the operation handler for the post vs vip port allow operation + VirtualserverPostVsVipPortAllowHandler virtualserver.PostVsVipPortAllowHandler + // VirtualserverPostVsVipPortDenyHandler sets the operation handler for the post vs vip port deny operation + VirtualserverPostVsVipPortDenyHandler virtualserver.PostVsVipPortDenyHandler + // VirtualserverPostVsVipPortRsHandler sets the operation handler for the post vs vip port rs operation + VirtualserverPostVsVipPortRsHandler virtualserver.PostVsVipPortRsHandler + // DevicePutDeviceNameAddrHandler sets the operation handler for the put device name addr operation + DevicePutDeviceNameAddrHandler device.PutDeviceNameAddrHandler + // DevicePutDeviceNameNetlinkHandler sets the operation handler for the put device name netlink operation + DevicePutDeviceNameNetlinkHandler device.PutDeviceNameNetlinkHandler + // DevicePutDeviceNameNetlinkAddrHandler sets the operation handler for the put device name netlink addr operation + DevicePutDeviceNameNetlinkAddrHandler device.PutDeviceNameNetlinkAddrHandler + // DevicePutDeviceNameNicHandler sets the operation handler for the put device name nic operation + DevicePutDeviceNameNicHandler device.PutDeviceNameNicHandler + // DevicePutDeviceNameRouteHandler sets the operation handler for the put device name route operation + DevicePutDeviceNameRouteHandler device.PutDeviceNameRouteHandler + // DevicePutDeviceNameVlanHandler sets the operation handler for the put device name vlan operation + DevicePutDeviceNameVlanHandler device.PutDeviceNameVlanHandler + // VirtualserverPutVsVipPortHandler sets the operation handler for the put vs vip port operation + VirtualserverPutVsVipPortHandler virtualserver.PutVsVipPortHandler + // VirtualserverPutVsVipPortAllowHandler sets the operation handler for the put vs vip port allow operation + VirtualserverPutVsVipPortAllowHandler virtualserver.PutVsVipPortAllowHandler + // VirtualserverPutVsVipPortDenyHandler sets the operation handler for the put vs vip port deny operation + VirtualserverPutVsVipPortDenyHandler virtualserver.PutVsVipPortDenyHandler + // VirtualserverPutVsVipPortLaddrHandler sets the operation handler for the put vs vip port laddr operation + VirtualserverPutVsVipPortLaddrHandler virtualserver.PutVsVipPortLaddrHandler + // VirtualserverPutVsVipPortRsHandler sets the operation handler for the put vs vip port rs operation + VirtualserverPutVsVipPortRsHandler virtualserver.PutVsVipPortRsHandler + + // ServeError is called when an error is received, there is a default handler + // but you can set your own with this + ServeError func(http.ResponseWriter, *http.Request, error) + + // PreServerShutdown is called before the HTTP(S) server is shutdown + // This allows for custom functions to get executed before the HTTP(S) server stops accepting traffic + PreServerShutdown func() + + // ServerShutdown is called when the HTTP(S) server is shut down and done + // handling all active connections and does not accept connections any more + ServerShutdown func() + + // Custom command line argument groups with their descriptions + CommandLineOptionsGroups []swag.CommandLineOptionsGroup + + // User defined logger function. + Logger func(string, ...interface{}) +} + +// UseRedoc for documentation at /docs +func (o *DpvsAgentAPI) UseRedoc() { + o.useSwaggerUI = false +} + +// UseSwaggerUI for documentation at /docs +func (o *DpvsAgentAPI) UseSwaggerUI() { + o.useSwaggerUI = true +} + +// SetDefaultProduces sets the default produces media type +func (o *DpvsAgentAPI) SetDefaultProduces(mediaType string) { + o.defaultProduces = mediaType +} + +// SetDefaultConsumes returns the default consumes media type +func (o *DpvsAgentAPI) SetDefaultConsumes(mediaType string) { + o.defaultConsumes = mediaType +} + +// SetSpec sets a spec that will be served for the clients. +func (o *DpvsAgentAPI) SetSpec(spec *loads.Document) { + o.spec = spec +} + +// DefaultProduces returns the default produces media type +func (o *DpvsAgentAPI) DefaultProduces() string { + return o.defaultProduces +} + +// DefaultConsumes returns the default consumes media type +func (o *DpvsAgentAPI) DefaultConsumes() string { + return o.defaultConsumes +} + +// Formats returns the registered string formats +func (o *DpvsAgentAPI) Formats() strfmt.Registry { + return o.formats +} + +// RegisterFormat registers a custom format validator +func (o *DpvsAgentAPI) RegisterFormat(name string, format strfmt.Format, validator strfmt.Validator) { + o.formats.Add(name, format, validator) +} + +// Validate validates the registrations in the DpvsAgentAPI +func (o *DpvsAgentAPI) Validate() error { + var unregistered []string + + if o.JSONConsumer == nil { + unregistered = append(unregistered, "JSONConsumer") + } + + if o.JSONProducer == nil { + unregistered = append(unregistered, "JSONProducer") + } + + if o.DeviceDeleteDeviceNameAddrHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameAddrHandler") + } + if o.DeviceDeleteDeviceNameNetlinkHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameNetlinkHandler") + } + if o.DeviceDeleteDeviceNameNetlinkAddrHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameNetlinkAddrHandler") + } + if o.DeviceDeleteDeviceNameRouteHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameRouteHandler") + } + if o.DeviceDeleteDeviceNameVlanHandler == nil { + unregistered = append(unregistered, "device.DeleteDeviceNameVlanHandler") + } + if o.VirtualserverDeleteVsVipPortHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortHandler") + } + if o.VirtualserverDeleteVsVipPortAllowHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortAllowHandler") + } + if o.VirtualserverDeleteVsVipPortDenyHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortDenyHandler") + } + if o.VirtualserverDeleteVsVipPortLaddrHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortLaddrHandler") + } + if o.VirtualserverDeleteVsVipPortRsHandler == nil { + unregistered = append(unregistered, "virtualserver.DeleteVsVipPortRsHandler") + } + if o.DeviceGetDeviceHandler == nil { + unregistered = append(unregistered, "device.GetDeviceHandler") + } + if o.DeviceGetDeviceNameAddrHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameAddrHandler") + } + if o.DeviceGetDeviceNameNetlinkHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameNetlinkHandler") + } + if o.DeviceGetDeviceNameNetlinkAddrHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameNetlinkAddrHandler") + } + if o.DeviceGetDeviceNameNicHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameNicHandler") + } + if o.DeviceGetDeviceNameRouteHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameRouteHandler") + } + if o.DeviceGetDeviceNameVlanHandler == nil { + unregistered = append(unregistered, "device.GetDeviceNameVlanHandler") + } + if o.VirtualserverGetVsHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsHandler") + } + if o.VirtualserverGetVsVipPortHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortHandler") + } + if o.VirtualserverGetVsVipPortAllowHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortAllowHandler") + } + if o.VirtualserverGetVsVipPortDenyHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortDenyHandler") + } + if o.VirtualserverGetVsVipPortLaddrHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortLaddrHandler") + } + if o.VirtualserverGetVsVipPortRsHandler == nil { + unregistered = append(unregistered, "virtualserver.GetVsVipPortRsHandler") + } + if o.VirtualserverPostVsVipPortAllowHandler == nil { + unregistered = append(unregistered, "virtualserver.PostVsVipPortAllowHandler") + } + if o.VirtualserverPostVsVipPortDenyHandler == nil { + unregistered = append(unregistered, "virtualserver.PostVsVipPortDenyHandler") + } + if o.VirtualserverPostVsVipPortRsHandler == nil { + unregistered = append(unregistered, "virtualserver.PostVsVipPortRsHandler") + } + if o.DevicePutDeviceNameAddrHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameAddrHandler") + } + if o.DevicePutDeviceNameNetlinkHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameNetlinkHandler") + } + if o.DevicePutDeviceNameNetlinkAddrHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameNetlinkAddrHandler") + } + if o.DevicePutDeviceNameNicHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameNicHandler") + } + if o.DevicePutDeviceNameRouteHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameRouteHandler") + } + if o.DevicePutDeviceNameVlanHandler == nil { + unregistered = append(unregistered, "device.PutDeviceNameVlanHandler") + } + if o.VirtualserverPutVsVipPortHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortHandler") + } + if o.VirtualserverPutVsVipPortAllowHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortAllowHandler") + } + if o.VirtualserverPutVsVipPortDenyHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortDenyHandler") + } + if o.VirtualserverPutVsVipPortLaddrHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortLaddrHandler") + } + if o.VirtualserverPutVsVipPortRsHandler == nil { + unregistered = append(unregistered, "virtualserver.PutVsVipPortRsHandler") + } + + if len(unregistered) > 0 { + return fmt.Errorf("missing registration: %s", strings.Join(unregistered, ", ")) + } + + return nil +} + +// ServeErrorFor gets a error handler for a given operation id +func (o *DpvsAgentAPI) ServeErrorFor(operationID string) func(http.ResponseWriter, *http.Request, error) { + return o.ServeError +} + +// AuthenticatorsFor gets the authenticators for the specified security schemes +func (o *DpvsAgentAPI) AuthenticatorsFor(schemes map[string]spec.SecurityScheme) map[string]runtime.Authenticator { + return nil +} + +// Authorizer returns the registered authorizer +func (o *DpvsAgentAPI) Authorizer() runtime.Authorizer { + return nil +} + +// ConsumersFor gets the consumers for the specified media types. +// MIME type parameters are ignored here. +func (o *DpvsAgentAPI) ConsumersFor(mediaTypes []string) map[string]runtime.Consumer { + result := make(map[string]runtime.Consumer, len(mediaTypes)) + for _, mt := range mediaTypes { + switch mt { + case "application/json": + result["application/json"] = o.JSONConsumer + } + + if c, ok := o.customConsumers[mt]; ok { + result[mt] = c + } + } + return result +} + +// ProducersFor gets the producers for the specified media types. +// MIME type parameters are ignored here. +func (o *DpvsAgentAPI) ProducersFor(mediaTypes []string) map[string]runtime.Producer { + result := make(map[string]runtime.Producer, len(mediaTypes)) + for _, mt := range mediaTypes { + switch mt { + case "application/json": + result["application/json"] = o.JSONProducer + } + + if p, ok := o.customProducers[mt]; ok { + result[mt] = p + } + } + return result +} + +// HandlerFor gets a http.Handler for the provided operation method and path +func (o *DpvsAgentAPI) HandlerFor(method, path string) (http.Handler, bool) { + if o.handlers == nil { + return nil, false + } + um := strings.ToUpper(method) + if _, ok := o.handlers[um]; !ok { + return nil, false + } + if path == "/" { + path = "" + } + h, ok := o.handlers[um][path] + return h, ok +} + +// Context returns the middleware context for the dpvs agent API +func (o *DpvsAgentAPI) Context() *middleware.Context { + if o.context == nil { + o.context = middleware.NewRoutableContext(o.spec, o, nil) + } + + return o.context +} + +func (o *DpvsAgentAPI) initHandlerCache() { + o.Context() // don't care about the result, just that the initialization happened + if o.handlers == nil { + o.handlers = make(map[string]map[string]http.Handler) + } + + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/addr"] = device.NewDeleteDeviceNameAddr(o.context, o.DeviceDeleteDeviceNameAddrHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/netlink"] = device.NewDeleteDeviceNameNetlink(o.context, o.DeviceDeleteDeviceNameNetlinkHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/netlink/addr"] = device.NewDeleteDeviceNameNetlinkAddr(o.context, o.DeviceDeleteDeviceNameNetlinkAddrHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/route"] = device.NewDeleteDeviceNameRoute(o.context, o.DeviceDeleteDeviceNameRouteHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/device/{name}/vlan"] = device.NewDeleteDeviceNameVlan(o.context, o.DeviceDeleteDeviceNameVlanHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}"] = virtualserver.NewDeleteVsVipPort(o.context, o.VirtualserverDeleteVsVipPortHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}/allow"] = virtualserver.NewDeleteVsVipPortAllow(o.context, o.VirtualserverDeleteVsVipPortAllowHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}/deny"] = virtualserver.NewDeleteVsVipPortDeny(o.context, o.VirtualserverDeleteVsVipPortDenyHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}/laddr"] = virtualserver.NewDeleteVsVipPortLaddr(o.context, o.VirtualserverDeleteVsVipPortLaddrHandler) + if o.handlers["DELETE"] == nil { + o.handlers["DELETE"] = make(map[string]http.Handler) + } + o.handlers["DELETE"]["/vs/{VipPort}/rs"] = virtualserver.NewDeleteVsVipPortRs(o.context, o.VirtualserverDeleteVsVipPortRsHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device"] = device.NewGetDevice(o.context, o.DeviceGetDeviceHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/addr"] = device.NewGetDeviceNameAddr(o.context, o.DeviceGetDeviceNameAddrHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/netlink"] = device.NewGetDeviceNameNetlink(o.context, o.DeviceGetDeviceNameNetlinkHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/netlink/addr"] = device.NewGetDeviceNameNetlinkAddr(o.context, o.DeviceGetDeviceNameNetlinkAddrHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/nic"] = device.NewGetDeviceNameNic(o.context, o.DeviceGetDeviceNameNicHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/route"] = device.NewGetDeviceNameRoute(o.context, o.DeviceGetDeviceNameRouteHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/device/{name}/vlan"] = device.NewGetDeviceNameVlan(o.context, o.DeviceGetDeviceNameVlanHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs"] = virtualserver.NewGetVs(o.context, o.VirtualserverGetVsHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}"] = virtualserver.NewGetVsVipPort(o.context, o.VirtualserverGetVsVipPortHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}/allow"] = virtualserver.NewGetVsVipPortAllow(o.context, o.VirtualserverGetVsVipPortAllowHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}/deny"] = virtualserver.NewGetVsVipPortDeny(o.context, o.VirtualserverGetVsVipPortDenyHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}/laddr"] = virtualserver.NewGetVsVipPortLaddr(o.context, o.VirtualserverGetVsVipPortLaddrHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } + o.handlers["GET"]["/vs/{VipPort}/rs"] = virtualserver.NewGetVsVipPortRs(o.context, o.VirtualserverGetVsVipPortRsHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/vs/{VipPort}/allow"] = virtualserver.NewPostVsVipPortAllow(o.context, o.VirtualserverPostVsVipPortAllowHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/vs/{VipPort}/deny"] = virtualserver.NewPostVsVipPortDeny(o.context, o.VirtualserverPostVsVipPortDenyHandler) + if o.handlers["POST"] == nil { + o.handlers["POST"] = make(map[string]http.Handler) + } + o.handlers["POST"]["/vs/{VipPort}/rs"] = virtualserver.NewPostVsVipPortRs(o.context, o.VirtualserverPostVsVipPortRsHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/addr"] = device.NewPutDeviceNameAddr(o.context, o.DevicePutDeviceNameAddrHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/netlink"] = device.NewPutDeviceNameNetlink(o.context, o.DevicePutDeviceNameNetlinkHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/netlink/addr"] = device.NewPutDeviceNameNetlinkAddr(o.context, o.DevicePutDeviceNameNetlinkAddrHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/nic"] = device.NewPutDeviceNameNic(o.context, o.DevicePutDeviceNameNicHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/route"] = device.NewPutDeviceNameRoute(o.context, o.DevicePutDeviceNameRouteHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/device/{name}/vlan"] = device.NewPutDeviceNameVlan(o.context, o.DevicePutDeviceNameVlanHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}"] = virtualserver.NewPutVsVipPort(o.context, o.VirtualserverPutVsVipPortHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}/allow"] = virtualserver.NewPutVsVipPortAllow(o.context, o.VirtualserverPutVsVipPortAllowHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}/deny"] = virtualserver.NewPutVsVipPortDeny(o.context, o.VirtualserverPutVsVipPortDenyHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}/laddr"] = virtualserver.NewPutVsVipPortLaddr(o.context, o.VirtualserverPutVsVipPortLaddrHandler) + if o.handlers["PUT"] == nil { + o.handlers["PUT"] = make(map[string]http.Handler) + } + o.handlers["PUT"]["/vs/{VipPort}/rs"] = virtualserver.NewPutVsVipPortRs(o.context, o.VirtualserverPutVsVipPortRsHandler) +} + +// Serve creates a http handler to serve the API over HTTP +// can be used directly in http.ListenAndServe(":8000", api.Serve(nil)) +func (o *DpvsAgentAPI) Serve(builder middleware.Builder) http.Handler { + o.Init() + + if o.Middleware != nil { + return o.Middleware(builder) + } + if o.useSwaggerUI { + return o.context.APIHandlerSwaggerUI(builder) + } + return o.context.APIHandler(builder) +} + +// Init allows you to just initialize the handler cache, you can then recompose the middleware as you see fit +func (o *DpvsAgentAPI) Init() { + if len(o.handlers) == 0 { + o.initHandlerCache() + } +} + +// RegisterConsumer allows you to add (or override) a consumer for a media type. +func (o *DpvsAgentAPI) RegisterConsumer(mediaType string, consumer runtime.Consumer) { + o.customConsumers[mediaType] = consumer +} + +// RegisterProducer allows you to add (or override) a producer for a media type. +func (o *DpvsAgentAPI) RegisterProducer(mediaType string, producer runtime.Producer) { + o.customProducers[mediaType] = producer +} + +// AddMiddlewareFor adds a http middleware to existing handler +func (o *DpvsAgentAPI) AddMiddlewareFor(method, path string, builder middleware.Builder) { + um := strings.ToUpper(method) + if path == "/" { + path = "" + } + o.Init() + if h, ok := o.handlers[um][path]; ok { + o.handlers[method][path] = builder(h) + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port.go new file mode 100644 index 000000000..14d8bbebd --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortHandlerFunc turns a function with the right signature into a delete vs vip port handler +type DeleteVsVipPortHandlerFunc func(DeleteVsVipPortParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortHandlerFunc) Handle(params DeleteVsVipPortParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortHandler interface for that can handle valid delete vs vip port params +type DeleteVsVipPortHandler interface { + Handle(DeleteVsVipPortParams) middleware.Responder +} + +// NewDeleteVsVipPort creates a new http.Handler for the delete vs vip port operation +func NewDeleteVsVipPort(ctx *middleware.Context, handler DeleteVsVipPortHandler) *DeleteVsVipPort { + return &DeleteVsVipPort{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPort swagger:route DELETE /vs/{VipPort} virtualserver deleteVsVipPort + +Delete a vip:port:proto +*/ +type DeleteVsVipPort struct { + Context *middleware.Context + Handler DeleteVsVipPortHandler +} + +func (o *DeleteVsVipPort) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow.go new file mode 100644 index 000000000..1aee746da --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortAllowHandlerFunc turns a function with the right signature into a delete vs vip port allow handler +type DeleteVsVipPortAllowHandlerFunc func(DeleteVsVipPortAllowParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortAllowHandlerFunc) Handle(params DeleteVsVipPortAllowParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortAllowHandler interface for that can handle valid delete vs vip port allow params +type DeleteVsVipPortAllowHandler interface { + Handle(DeleteVsVipPortAllowParams) middleware.Responder +} + +// NewDeleteVsVipPortAllow creates a new http.Handler for the delete vs vip port allow operation +func NewDeleteVsVipPortAllow(ctx *middleware.Context, handler DeleteVsVipPortAllowHandler) *DeleteVsVipPortAllow { + return &DeleteVsVipPortAllow{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPortAllow swagger:route DELETE /vs/{VipPort}/allow virtualserver deleteVsVipPortAllow + +Delete a set of ip form white list to vip:port:proto +*/ +type DeleteVsVipPortAllow struct { + Context *middleware.Context + Handler DeleteVsVipPortAllowHandler +} + +func (o *DeleteVsVipPortAllow) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortAllowParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_parameters.go new file mode 100644 index 000000000..532017c51 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteVsVipPortAllowParams creates a new DeleteVsVipPortAllowParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortAllowParams() DeleteVsVipPortAllowParams { + + return DeleteVsVipPortAllowParams{} +} + +// DeleteVsVipPortAllowParams contains all the bound params for the delete vs vip port allow operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPortAllow +type DeleteVsVipPortAllowParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortAllowParams() beforehand. +func (o *DeleteVsVipPortAllowParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortAllowParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_responses.go new file mode 100644 index 000000000..03337c63d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_responses.go @@ -0,0 +1,211 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortAllowOKCode is the HTTP code returned for type DeleteVsVipPortAllowOK +const DeleteVsVipPortAllowOKCode int = 200 + +/* +DeleteVsVipPortAllowOK Success + +swagger:response deleteVsVipPortAllowOK +*/ +type DeleteVsVipPortAllowOK struct { +} + +// NewDeleteVsVipPortAllowOK creates DeleteVsVipPortAllowOK with default headers values +func NewDeleteVsVipPortAllowOK() *DeleteVsVipPortAllowOK { + + return &DeleteVsVipPortAllowOK{} +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +// DeleteVsVipPortAllowNotFoundCode is the HTTP code returned for type DeleteVsVipPortAllowNotFound +const DeleteVsVipPortAllowNotFoundCode int = 404 + +/* +DeleteVsVipPortAllowNotFound Service not found + +swagger:response deleteVsVipPortAllowNotFound +*/ +type DeleteVsVipPortAllowNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortAllowNotFound creates DeleteVsVipPortAllowNotFound with default headers values +func NewDeleteVsVipPortAllowNotFound() *DeleteVsVipPortAllowNotFound { + + return &DeleteVsVipPortAllowNotFound{} +} + +// WithPayload adds the payload to the delete vs vip port allow not found response +func (o *DeleteVsVipPortAllowNotFound) WithPayload(payload string) *DeleteVsVipPortAllowNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port allow not found response +func (o *DeleteVsVipPortAllowNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortAllowInvalidFrontendCode is the HTTP code returned for type DeleteVsVipPortAllowInvalidFrontend +const DeleteVsVipPortAllowInvalidFrontendCode int = 460 + +/* +DeleteVsVipPortAllowInvalidFrontend Invalid frontend in service configuration + +swagger:response deleteVsVipPortAllowInvalidFrontend +*/ +type DeleteVsVipPortAllowInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortAllowInvalidFrontend creates DeleteVsVipPortAllowInvalidFrontend with default headers values +func NewDeleteVsVipPortAllowInvalidFrontend() *DeleteVsVipPortAllowInvalidFrontend { + + return &DeleteVsVipPortAllowInvalidFrontend{} +} + +// WithPayload adds the payload to the delete vs vip port allow invalid frontend response +func (o *DeleteVsVipPortAllowInvalidFrontend) WithPayload(payload models.Error) *DeleteVsVipPortAllowInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port allow invalid frontend response +func (o *DeleteVsVipPortAllowInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortAllowInvalidBackendCode is the HTTP code returned for type DeleteVsVipPortAllowInvalidBackend +const DeleteVsVipPortAllowInvalidBackendCode int = 461 + +/* +DeleteVsVipPortAllowInvalidBackend Invalid backend in service configuration + +swagger:response deleteVsVipPortAllowInvalidBackend +*/ +type DeleteVsVipPortAllowInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortAllowInvalidBackend creates DeleteVsVipPortAllowInvalidBackend with default headers values +func NewDeleteVsVipPortAllowInvalidBackend() *DeleteVsVipPortAllowInvalidBackend { + + return &DeleteVsVipPortAllowInvalidBackend{} +} + +// WithPayload adds the payload to the delete vs vip port allow invalid backend response +func (o *DeleteVsVipPortAllowInvalidBackend) WithPayload(payload models.Error) *DeleteVsVipPortAllowInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port allow invalid backend response +func (o *DeleteVsVipPortAllowInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortAllowFailureCode is the HTTP code returned for type DeleteVsVipPortAllowFailure +const DeleteVsVipPortAllowFailureCode int = 500 + +/* +DeleteVsVipPortAllowFailure Service deletion failed + +swagger:response deleteVsVipPortAllowFailure +*/ +type DeleteVsVipPortAllowFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortAllowFailure creates DeleteVsVipPortAllowFailure with default headers values +func NewDeleteVsVipPortAllowFailure() *DeleteVsVipPortAllowFailure { + + return &DeleteVsVipPortAllowFailure{} +} + +// WithPayload adds the payload to the delete vs vip port allow failure response +func (o *DeleteVsVipPortAllowFailure) WithPayload(payload models.Error) *DeleteVsVipPortAllowFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port allow failure response +func (o *DeleteVsVipPortAllowFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortAllowFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_urlbuilder.go new file mode 100644 index 000000000..bb48d3228 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_allow_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortAllowURL generates an URL for the delete vs vip port allow operation +type DeleteVsVipPortAllowURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortAllowURL) WithBasePath(bp string) *DeleteVsVipPortAllowURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortAllowURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortAllowURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/allow" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortAllowURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortAllowURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortAllowURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortAllowURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortAllowURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortAllowURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortAllowURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny.go new file mode 100644 index 000000000..93c81f5b4 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortDenyHandlerFunc turns a function with the right signature into a delete vs vip port deny handler +type DeleteVsVipPortDenyHandlerFunc func(DeleteVsVipPortDenyParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortDenyHandlerFunc) Handle(params DeleteVsVipPortDenyParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortDenyHandler interface for that can handle valid delete vs vip port deny params +type DeleteVsVipPortDenyHandler interface { + Handle(DeleteVsVipPortDenyParams) middleware.Responder +} + +// NewDeleteVsVipPortDeny creates a new http.Handler for the delete vs vip port deny operation +func NewDeleteVsVipPortDeny(ctx *middleware.Context, handler DeleteVsVipPortDenyHandler) *DeleteVsVipPortDeny { + return &DeleteVsVipPortDeny{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPortDeny swagger:route DELETE /vs/{VipPort}/deny virtualserver deleteVsVipPortDeny + +Delete a set of ip form black list to vip:port:proto +*/ +type DeleteVsVipPortDeny struct { + Context *middleware.Context + Handler DeleteVsVipPortDenyHandler +} + +func (o *DeleteVsVipPortDeny) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortDenyParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_parameters.go new file mode 100644 index 000000000..b01bc07e9 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteVsVipPortDenyParams creates a new DeleteVsVipPortDenyParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortDenyParams() DeleteVsVipPortDenyParams { + + return DeleteVsVipPortDenyParams{} +} + +// DeleteVsVipPortDenyParams contains all the bound params for the delete vs vip port deny operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPortDeny +type DeleteVsVipPortDenyParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortDenyParams() beforehand. +func (o *DeleteVsVipPortDenyParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortDenyParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_responses.go new file mode 100644 index 000000000..05c87233f --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_responses.go @@ -0,0 +1,211 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortDenyOKCode is the HTTP code returned for type DeleteVsVipPortDenyOK +const DeleteVsVipPortDenyOKCode int = 200 + +/* +DeleteVsVipPortDenyOK Success + +swagger:response deleteVsVipPortDenyOK +*/ +type DeleteVsVipPortDenyOK struct { +} + +// NewDeleteVsVipPortDenyOK creates DeleteVsVipPortDenyOK with default headers values +func NewDeleteVsVipPortDenyOK() *DeleteVsVipPortDenyOK { + + return &DeleteVsVipPortDenyOK{} +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +// DeleteVsVipPortDenyNotFoundCode is the HTTP code returned for type DeleteVsVipPortDenyNotFound +const DeleteVsVipPortDenyNotFoundCode int = 404 + +/* +DeleteVsVipPortDenyNotFound Service not found + +swagger:response deleteVsVipPortDenyNotFound +*/ +type DeleteVsVipPortDenyNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortDenyNotFound creates DeleteVsVipPortDenyNotFound with default headers values +func NewDeleteVsVipPortDenyNotFound() *DeleteVsVipPortDenyNotFound { + + return &DeleteVsVipPortDenyNotFound{} +} + +// WithPayload adds the payload to the delete vs vip port deny not found response +func (o *DeleteVsVipPortDenyNotFound) WithPayload(payload string) *DeleteVsVipPortDenyNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port deny not found response +func (o *DeleteVsVipPortDenyNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortDenyInvalidFrontendCode is the HTTP code returned for type DeleteVsVipPortDenyInvalidFrontend +const DeleteVsVipPortDenyInvalidFrontendCode int = 460 + +/* +DeleteVsVipPortDenyInvalidFrontend Invalid frontend in service configuration + +swagger:response deleteVsVipPortDenyInvalidFrontend +*/ +type DeleteVsVipPortDenyInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortDenyInvalidFrontend creates DeleteVsVipPortDenyInvalidFrontend with default headers values +func NewDeleteVsVipPortDenyInvalidFrontend() *DeleteVsVipPortDenyInvalidFrontend { + + return &DeleteVsVipPortDenyInvalidFrontend{} +} + +// WithPayload adds the payload to the delete vs vip port deny invalid frontend response +func (o *DeleteVsVipPortDenyInvalidFrontend) WithPayload(payload models.Error) *DeleteVsVipPortDenyInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port deny invalid frontend response +func (o *DeleteVsVipPortDenyInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortDenyInvalidBackendCode is the HTTP code returned for type DeleteVsVipPortDenyInvalidBackend +const DeleteVsVipPortDenyInvalidBackendCode int = 461 + +/* +DeleteVsVipPortDenyInvalidBackend Invalid backend in service configuration + +swagger:response deleteVsVipPortDenyInvalidBackend +*/ +type DeleteVsVipPortDenyInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortDenyInvalidBackend creates DeleteVsVipPortDenyInvalidBackend with default headers values +func NewDeleteVsVipPortDenyInvalidBackend() *DeleteVsVipPortDenyInvalidBackend { + + return &DeleteVsVipPortDenyInvalidBackend{} +} + +// WithPayload adds the payload to the delete vs vip port deny invalid backend response +func (o *DeleteVsVipPortDenyInvalidBackend) WithPayload(payload models.Error) *DeleteVsVipPortDenyInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port deny invalid backend response +func (o *DeleteVsVipPortDenyInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortDenyFailureCode is the HTTP code returned for type DeleteVsVipPortDenyFailure +const DeleteVsVipPortDenyFailureCode int = 500 + +/* +DeleteVsVipPortDenyFailure Service deletion failed + +swagger:response deleteVsVipPortDenyFailure +*/ +type DeleteVsVipPortDenyFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortDenyFailure creates DeleteVsVipPortDenyFailure with default headers values +func NewDeleteVsVipPortDenyFailure() *DeleteVsVipPortDenyFailure { + + return &DeleteVsVipPortDenyFailure{} +} + +// WithPayload adds the payload to the delete vs vip port deny failure response +func (o *DeleteVsVipPortDenyFailure) WithPayload(payload models.Error) *DeleteVsVipPortDenyFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port deny failure response +func (o *DeleteVsVipPortDenyFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortDenyFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_urlbuilder.go new file mode 100644 index 000000000..3254ab8a7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_deny_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortDenyURL generates an URL for the delete vs vip port deny operation +type DeleteVsVipPortDenyURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortDenyURL) WithBasePath(bp string) *DeleteVsVipPortDenyURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortDenyURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortDenyURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/deny" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortDenyURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortDenyURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortDenyURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortDenyURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortDenyURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortDenyURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortDenyURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr.go new file mode 100644 index 000000000..d29b0e7c4 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortLaddrHandlerFunc turns a function with the right signature into a delete vs vip port laddr handler +type DeleteVsVipPortLaddrHandlerFunc func(DeleteVsVipPortLaddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortLaddrHandlerFunc) Handle(params DeleteVsVipPortLaddrParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortLaddrHandler interface for that can handle valid delete vs vip port laddr params +type DeleteVsVipPortLaddrHandler interface { + Handle(DeleteVsVipPortLaddrParams) middleware.Responder +} + +// NewDeleteVsVipPortLaddr creates a new http.Handler for the delete vs vip port laddr operation +func NewDeleteVsVipPortLaddr(ctx *middleware.Context, handler DeleteVsVipPortLaddrHandler) *DeleteVsVipPortLaddr { + return &DeleteVsVipPortLaddr{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPortLaddr swagger:route DELETE /vs/{VipPort}/laddr virtualserver deleteVsVipPortLaddr + +DeleteVsVipPortLaddr delete vs vip port laddr API +*/ +type DeleteVsVipPortLaddr struct { + Context *middleware.Context + Handler DeleteVsVipPortLaddrHandler +} + +func (o *DeleteVsVipPortLaddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortLaddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_parameters.go new file mode 100644 index 000000000..33498eedc --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteVsVipPortLaddrParams creates a new DeleteVsVipPortLaddrParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortLaddrParams() DeleteVsVipPortLaddrParams { + + return DeleteVsVipPortLaddrParams{} +} + +// DeleteVsVipPortLaddrParams contains all the bound params for the delete vs vip port laddr operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPortLaddr +type DeleteVsVipPortLaddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Spec *models.LocalAddressSpecTiny +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortLaddrParams() beforehand. +func (o *DeleteVsVipPortLaddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.LocalAddressSpecTiny + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortLaddrParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_responses.go new file mode 100644 index 000000000..7b474dc5a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_responses.go @@ -0,0 +1,186 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortLaddrOKCode is the HTTP code returned for type DeleteVsVipPortLaddrOK +const DeleteVsVipPortLaddrOKCode int = 200 + +/* +DeleteVsVipPortLaddrOK Success + +swagger:response deleteVsVipPortLaddrOK +*/ +type DeleteVsVipPortLaddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortLaddrOK creates DeleteVsVipPortLaddrOK with default headers values +func NewDeleteVsVipPortLaddrOK() *DeleteVsVipPortLaddrOK { + + return &DeleteVsVipPortLaddrOK{} +} + +// WithPayload adds the payload to the delete vs vip port laddr o k response +func (o *DeleteVsVipPortLaddrOK) WithPayload(payload string) *DeleteVsVipPortLaddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port laddr o k response +func (o *DeleteVsVipPortLaddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortLaddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortLaddrInvalidFrontendCode is the HTTP code returned for type DeleteVsVipPortLaddrInvalidFrontend +const DeleteVsVipPortLaddrInvalidFrontendCode int = 460 + +/* +DeleteVsVipPortLaddrInvalidFrontend Invalid frontend in service configuration + +swagger:response deleteVsVipPortLaddrInvalidFrontend +*/ +type DeleteVsVipPortLaddrInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortLaddrInvalidFrontend creates DeleteVsVipPortLaddrInvalidFrontend with default headers values +func NewDeleteVsVipPortLaddrInvalidFrontend() *DeleteVsVipPortLaddrInvalidFrontend { + + return &DeleteVsVipPortLaddrInvalidFrontend{} +} + +// WithPayload adds the payload to the delete vs vip port laddr invalid frontend response +func (o *DeleteVsVipPortLaddrInvalidFrontend) WithPayload(payload models.Error) *DeleteVsVipPortLaddrInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port laddr invalid frontend response +func (o *DeleteVsVipPortLaddrInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortLaddrInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortLaddrInvalidBackendCode is the HTTP code returned for type DeleteVsVipPortLaddrInvalidBackend +const DeleteVsVipPortLaddrInvalidBackendCode int = 461 + +/* +DeleteVsVipPortLaddrInvalidBackend Invalid backend in service configuration + +swagger:response deleteVsVipPortLaddrInvalidBackend +*/ +type DeleteVsVipPortLaddrInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortLaddrInvalidBackend creates DeleteVsVipPortLaddrInvalidBackend with default headers values +func NewDeleteVsVipPortLaddrInvalidBackend() *DeleteVsVipPortLaddrInvalidBackend { + + return &DeleteVsVipPortLaddrInvalidBackend{} +} + +// WithPayload adds the payload to the delete vs vip port laddr invalid backend response +func (o *DeleteVsVipPortLaddrInvalidBackend) WithPayload(payload models.Error) *DeleteVsVipPortLaddrInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port laddr invalid backend response +func (o *DeleteVsVipPortLaddrInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortLaddrInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortLaddrFailureCode is the HTTP code returned for type DeleteVsVipPortLaddrFailure +const DeleteVsVipPortLaddrFailureCode int = 500 + +/* +DeleteVsVipPortLaddrFailure Error while creating virtual server + +swagger:response deleteVsVipPortLaddrFailure +*/ +type DeleteVsVipPortLaddrFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortLaddrFailure creates DeleteVsVipPortLaddrFailure with default headers values +func NewDeleteVsVipPortLaddrFailure() *DeleteVsVipPortLaddrFailure { + + return &DeleteVsVipPortLaddrFailure{} +} + +// WithPayload adds the payload to the delete vs vip port laddr failure response +func (o *DeleteVsVipPortLaddrFailure) WithPayload(payload models.Error) *DeleteVsVipPortLaddrFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port laddr failure response +func (o *DeleteVsVipPortLaddrFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortLaddrFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_urlbuilder.go new file mode 100644 index 000000000..4926a3d0c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_laddr_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortLaddrURL generates an URL for the delete vs vip port laddr operation +type DeleteVsVipPortLaddrURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortLaddrURL) WithBasePath(bp string) *DeleteVsVipPortLaddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortLaddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortLaddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/laddr" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortLaddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortLaddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortLaddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortLaddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortLaddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortLaddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortLaddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_parameters.go new file mode 100644 index 000000000..d8e528348 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewDeleteVsVipPortParams creates a new DeleteVsVipPortParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortParams() DeleteVsVipPortParams { + + return DeleteVsVipPortParams{} +} + +// DeleteVsVipPortParams contains all the bound params for the delete vs vip port operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPort +type DeleteVsVipPortParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortParams() beforehand. +func (o *DeleteVsVipPortParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_responses.go new file mode 100644 index 000000000..f423fd023 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_responses.go @@ -0,0 +1,143 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortOKCode is the HTTP code returned for type DeleteVsVipPortOK +const DeleteVsVipPortOKCode int = 200 + +/* +DeleteVsVipPortOK Success + +swagger:response deleteVsVipPortOK +*/ +type DeleteVsVipPortOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortOK creates DeleteVsVipPortOK with default headers values +func NewDeleteVsVipPortOK() *DeleteVsVipPortOK { + + return &DeleteVsVipPortOK{} +} + +// WithPayload adds the payload to the delete vs vip port o k response +func (o *DeleteVsVipPortOK) WithPayload(payload string) *DeleteVsVipPortOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port o k response +func (o *DeleteVsVipPortOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortNotFoundCode is the HTTP code returned for type DeleteVsVipPortNotFound +const DeleteVsVipPortNotFoundCode int = 404 + +/* +DeleteVsVipPortNotFound Service not found + +swagger:response deleteVsVipPortNotFound +*/ +type DeleteVsVipPortNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortNotFound creates DeleteVsVipPortNotFound with default headers values +func NewDeleteVsVipPortNotFound() *DeleteVsVipPortNotFound { + + return &DeleteVsVipPortNotFound{} +} + +// WithPayload adds the payload to the delete vs vip port not found response +func (o *DeleteVsVipPortNotFound) WithPayload(payload string) *DeleteVsVipPortNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port not found response +func (o *DeleteVsVipPortNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortFailureCode is the HTTP code returned for type DeleteVsVipPortFailure +const DeleteVsVipPortFailureCode int = 500 + +/* +DeleteVsVipPortFailure Service deletion failed + +swagger:response deleteVsVipPortFailure +*/ +type DeleteVsVipPortFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortFailure creates DeleteVsVipPortFailure with default headers values +func NewDeleteVsVipPortFailure() *DeleteVsVipPortFailure { + + return &DeleteVsVipPortFailure{} +} + +// WithPayload adds the payload to the delete vs vip port failure response +func (o *DeleteVsVipPortFailure) WithPayload(payload models.Error) *DeleteVsVipPortFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port failure response +func (o *DeleteVsVipPortFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs.go new file mode 100644 index 000000000..1598ebfbf --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// DeleteVsVipPortRsHandlerFunc turns a function with the right signature into a delete vs vip port rs handler +type DeleteVsVipPortRsHandlerFunc func(DeleteVsVipPortRsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn DeleteVsVipPortRsHandlerFunc) Handle(params DeleteVsVipPortRsParams) middleware.Responder { + return fn(params) +} + +// DeleteVsVipPortRsHandler interface for that can handle valid delete vs vip port rs params +type DeleteVsVipPortRsHandler interface { + Handle(DeleteVsVipPortRsParams) middleware.Responder +} + +// NewDeleteVsVipPortRs creates a new http.Handler for the delete vs vip port rs operation +func NewDeleteVsVipPortRs(ctx *middleware.Context, handler DeleteVsVipPortRsHandler) *DeleteVsVipPortRs { + return &DeleteVsVipPortRs{Context: ctx, Handler: handler} +} + +/* + DeleteVsVipPortRs swagger:route DELETE /vs/{VipPort}/rs virtualserver deleteVsVipPortRs + +Delete a set of real server from vip:port:proto +*/ +type DeleteVsVipPortRs struct { + Context *middleware.Context + Handler DeleteVsVipPortRsHandler +} + +func (o *DeleteVsVipPortRs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewDeleteVsVipPortRsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_parameters.go new file mode 100644 index 000000000..f643ff30e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewDeleteVsVipPortRsParams creates a new DeleteVsVipPortRsParams object +// +// There are no default values defined in the spec. +func NewDeleteVsVipPortRsParams() DeleteVsVipPortRsParams { + + return DeleteVsVipPortRsParams{} +} + +// DeleteVsVipPortRsParams contains all the bound params for the delete vs vip port rs operation +// typically these are obtained from a http.Request +// +// swagger:parameters DeleteVsVipPortRs +type DeleteVsVipPortRsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Rss *models.RealServerTinyList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewDeleteVsVipPortRsParams() beforehand. +func (o *DeleteVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RealServerTinyList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("rss", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Rss = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *DeleteVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_responses.go new file mode 100644 index 000000000..e51843937 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_responses.go @@ -0,0 +1,211 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// DeleteVsVipPortRsOKCode is the HTTP code returned for type DeleteVsVipPortRsOK +const DeleteVsVipPortRsOKCode int = 200 + +/* +DeleteVsVipPortRsOK Success + +swagger:response deleteVsVipPortRsOK +*/ +type DeleteVsVipPortRsOK struct { +} + +// NewDeleteVsVipPortRsOK creates DeleteVsVipPortRsOK with default headers values +func NewDeleteVsVipPortRsOK() *DeleteVsVipPortRsOK { + + return &DeleteVsVipPortRsOK{} +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(200) +} + +// DeleteVsVipPortRsNotFoundCode is the HTTP code returned for type DeleteVsVipPortRsNotFound +const DeleteVsVipPortRsNotFoundCode int = 404 + +/* +DeleteVsVipPortRsNotFound Service not found + +swagger:response deleteVsVipPortRsNotFound +*/ +type DeleteVsVipPortRsNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewDeleteVsVipPortRsNotFound creates DeleteVsVipPortRsNotFound with default headers values +func NewDeleteVsVipPortRsNotFound() *DeleteVsVipPortRsNotFound { + + return &DeleteVsVipPortRsNotFound{} +} + +// WithPayload adds the payload to the delete vs vip port rs not found response +func (o *DeleteVsVipPortRsNotFound) WithPayload(payload string) *DeleteVsVipPortRsNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port rs not found response +func (o *DeleteVsVipPortRsNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortRsInvalidFrontendCode is the HTTP code returned for type DeleteVsVipPortRsInvalidFrontend +const DeleteVsVipPortRsInvalidFrontendCode int = 460 + +/* +DeleteVsVipPortRsInvalidFrontend Invalid frontend in service configuration + +swagger:response deleteVsVipPortRsInvalidFrontend +*/ +type DeleteVsVipPortRsInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortRsInvalidFrontend creates DeleteVsVipPortRsInvalidFrontend with default headers values +func NewDeleteVsVipPortRsInvalidFrontend() *DeleteVsVipPortRsInvalidFrontend { + + return &DeleteVsVipPortRsInvalidFrontend{} +} + +// WithPayload adds the payload to the delete vs vip port rs invalid frontend response +func (o *DeleteVsVipPortRsInvalidFrontend) WithPayload(payload models.Error) *DeleteVsVipPortRsInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port rs invalid frontend response +func (o *DeleteVsVipPortRsInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortRsInvalidBackendCode is the HTTP code returned for type DeleteVsVipPortRsInvalidBackend +const DeleteVsVipPortRsInvalidBackendCode int = 461 + +/* +DeleteVsVipPortRsInvalidBackend Invalid backend in service configuration + +swagger:response deleteVsVipPortRsInvalidBackend +*/ +type DeleteVsVipPortRsInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortRsInvalidBackend creates DeleteVsVipPortRsInvalidBackend with default headers values +func NewDeleteVsVipPortRsInvalidBackend() *DeleteVsVipPortRsInvalidBackend { + + return &DeleteVsVipPortRsInvalidBackend{} +} + +// WithPayload adds the payload to the delete vs vip port rs invalid backend response +func (o *DeleteVsVipPortRsInvalidBackend) WithPayload(payload models.Error) *DeleteVsVipPortRsInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port rs invalid backend response +func (o *DeleteVsVipPortRsInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// DeleteVsVipPortRsFailureCode is the HTTP code returned for type DeleteVsVipPortRsFailure +const DeleteVsVipPortRsFailureCode int = 500 + +/* +DeleteVsVipPortRsFailure Service deletion failed + +swagger:response deleteVsVipPortRsFailure +*/ +type DeleteVsVipPortRsFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewDeleteVsVipPortRsFailure creates DeleteVsVipPortRsFailure with default headers values +func NewDeleteVsVipPortRsFailure() *DeleteVsVipPortRsFailure { + + return &DeleteVsVipPortRsFailure{} +} + +// WithPayload adds the payload to the delete vs vip port rs failure response +func (o *DeleteVsVipPortRsFailure) WithPayload(payload models.Error) *DeleteVsVipPortRsFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the delete vs vip port rs failure response +func (o *DeleteVsVipPortRsFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *DeleteVsVipPortRsFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_urlbuilder.go new file mode 100644 index 000000000..074cd0068 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_rs_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortRsURL generates an URL for the delete vs vip port rs operation +type DeleteVsVipPortRsURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortRsURL) WithBasePath(bp string) *DeleteVsVipPortRsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortRsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortRsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/rs" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortRsURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortRsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortRsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortRsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortRsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortRsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortRsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_urlbuilder.go new file mode 100644 index 000000000..44d932d71 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/delete_vs_vip_port_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// DeleteVsVipPortURL generates an URL for the delete vs vip port operation +type DeleteVsVipPortURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortURL) WithBasePath(bp string) *DeleteVsVipPortURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *DeleteVsVipPortURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *DeleteVsVipPortURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on DeleteVsVipPortURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *DeleteVsVipPortURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *DeleteVsVipPortURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *DeleteVsVipPortURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on DeleteVsVipPortURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on DeleteVsVipPortURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *DeleteVsVipPortURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs.go new file mode 100644 index 000000000..1e82546f7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsHandlerFunc turns a function with the right signature into a get vs handler +type GetVsHandlerFunc func(GetVsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsHandlerFunc) Handle(params GetVsParams) middleware.Responder { + return fn(params) +} + +// GetVsHandler interface for that can handle valid get vs params +type GetVsHandler interface { + Handle(GetVsParams) middleware.Responder +} + +// NewGetVs creates a new http.Handler for the get vs operation +func NewGetVs(ctx *middleware.Context, handler GetVsHandler) *GetVs { + return &GetVs{Context: ctx, Handler: handler} +} + +/* + GetVs swagger:route GET /vs virtualserver getVs + +display all vip:port:proto and rsip:port list +*/ +type GetVs struct { + Context *middleware.Context + Handler GetVsHandler +} + +func (o *GetVs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_parameters.go new file mode 100644 index 000000000..ac28ba465 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_parameters.go @@ -0,0 +1,92 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetVsParams creates a new GetVsParams object +// with the default values initialized. +func NewGetVsParams() GetVsParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetVsParams{ + Stats: &statsDefault, + } +} + +// GetVsParams contains all the bound params for the get vs operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVs +type GetVsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsParams() beforehand. +func (o *GetVsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetVsParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetVsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_responses.go new file mode 100644 index 000000000..c67eec7a7 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_responses.go @@ -0,0 +1,59 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// GetVsOKCode is the HTTP code returned for type GetVsOK +const GetVsOKCode int = 200 + +/* +GetVsOK Success + +swagger:response getVsOK +*/ +type GetVsOK struct { + + /* + In: Body + */ + Payload *models.VirtualServerList `json:"body,omitempty"` +} + +// NewGetVsOK creates GetVsOK with default headers values +func NewGetVsOK() *GetVsOK { + + return &GetVsOK{} +} + +// WithPayload adds the payload to the get vs o k response +func (o *GetVsOK) WithPayload(payload *models.VirtualServerList) *GetVsOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs o k response +func (o *GetVsOK) SetPayload(payload *models.VirtualServerList) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_urlbuilder.go new file mode 100644 index 000000000..917308dcf --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_urlbuilder.go @@ -0,0 +1,105 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + + "github.com/go-openapi/swag" +) + +// GetVsURL generates an URL for the get vs operation +type GetVsURL struct { + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsURL) WithBasePath(bp string) *GetVsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port.go new file mode 100644 index 000000000..f7e02c0d4 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortHandlerFunc turns a function with the right signature into a get vs vip port handler +type GetVsVipPortHandlerFunc func(GetVsVipPortParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortHandlerFunc) Handle(params GetVsVipPortParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortHandler interface for that can handle valid get vs vip port params +type GetVsVipPortHandler interface { + Handle(GetVsVipPortParams) middleware.Responder +} + +// NewGetVsVipPort creates a new http.Handler for the get vs vip port operation +func NewGetVsVipPort(ctx *middleware.Context, handler GetVsVipPortHandler) *GetVsVipPort { + return &GetVsVipPort{Context: ctx, Handler: handler} +} + +/* + GetVsVipPort swagger:route GET /vs/{VipPort} virtualserver getVsVipPort + +get a specific virtual server +*/ +type GetVsVipPort struct { + Context *middleware.Context + Handler GetVsVipPortHandler +} + +func (o *GetVsVipPort) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow.go new file mode 100644 index 000000000..267a01e25 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortAllowHandlerFunc turns a function with the right signature into a get vs vip port allow handler +type GetVsVipPortAllowHandlerFunc func(GetVsVipPortAllowParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortAllowHandlerFunc) Handle(params GetVsVipPortAllowParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortAllowHandler interface for that can handle valid get vs vip port allow params +type GetVsVipPortAllowHandler interface { + Handle(GetVsVipPortAllowParams) middleware.Responder +} + +// NewGetVsVipPortAllow creates a new http.Handler for the get vs vip port allow operation +func NewGetVsVipPortAllow(ctx *middleware.Context, handler GetVsVipPortAllowHandler) *GetVsVipPortAllow { + return &GetVsVipPortAllow{Context: ctx, Handler: handler} +} + +/* + GetVsVipPortAllow swagger:route GET /vs/{VipPort}/allow virtualserver getVsVipPortAllow + +GetVsVipPortAllow get vs vip port allow API +*/ +type GetVsVipPortAllow struct { + Context *middleware.Context + Handler GetVsVipPortAllowHandler +} + +func (o *GetVsVipPortAllow) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortAllowParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_parameters.go new file mode 100644 index 000000000..df1e98ae2 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewGetVsVipPortAllowParams creates a new GetVsVipPortAllowParams object +// +// There are no default values defined in the spec. +func NewGetVsVipPortAllowParams() GetVsVipPortAllowParams { + + return GetVsVipPortAllowParams{} +} + +// GetVsVipPortAllowParams contains all the bound params for the get vs vip port allow operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPortAllow +type GetVsVipPortAllowParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortAllowParams() beforehand. +func (o *GetVsVipPortAllowParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortAllowParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_responses.go new file mode 100644 index 000000000..21f2eb892 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetVsVipPortAllowOKCode is the HTTP code returned for type GetVsVipPortAllowOK +const GetVsVipPortAllowOKCode int = 200 + +/* +GetVsVipPortAllowOK Success + +swagger:response getVsVipPortAllowOK +*/ +type GetVsVipPortAllowOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortAllowOK creates GetVsVipPortAllowOK with default headers values +func NewGetVsVipPortAllowOK() *GetVsVipPortAllowOK { + + return &GetVsVipPortAllowOK{} +} + +// WithPayload adds the payload to the get vs vip port allow o k response +func (o *GetVsVipPortAllowOK) WithPayload(payload string) *GetVsVipPortAllowOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port allow o k response +func (o *GetVsVipPortAllowOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortAllowOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetVsVipPortAllowNotFoundCode is the HTTP code returned for type GetVsVipPortAllowNotFound +const GetVsVipPortAllowNotFoundCode int = 404 + +/* +GetVsVipPortAllowNotFound Service not found + +swagger:response getVsVipPortAllowNotFound +*/ +type GetVsVipPortAllowNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortAllowNotFound creates GetVsVipPortAllowNotFound with default headers values +func NewGetVsVipPortAllowNotFound() *GetVsVipPortAllowNotFound { + + return &GetVsVipPortAllowNotFound{} +} + +// WithPayload adds the payload to the get vs vip port allow not found response +func (o *GetVsVipPortAllowNotFound) WithPayload(payload string) *GetVsVipPortAllowNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port allow not found response +func (o *GetVsVipPortAllowNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortAllowNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_urlbuilder.go new file mode 100644 index 000000000..9f00c3d27 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_allow_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// GetVsVipPortAllowURL generates an URL for the get vs vip port allow operation +type GetVsVipPortAllowURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortAllowURL) WithBasePath(bp string) *GetVsVipPortAllowURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortAllowURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortAllowURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/allow" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortAllowURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortAllowURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortAllowURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortAllowURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortAllowURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortAllowURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortAllowURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny.go new file mode 100644 index 000000000..92631c107 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortDenyHandlerFunc turns a function with the right signature into a get vs vip port deny handler +type GetVsVipPortDenyHandlerFunc func(GetVsVipPortDenyParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortDenyHandlerFunc) Handle(params GetVsVipPortDenyParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortDenyHandler interface for that can handle valid get vs vip port deny params +type GetVsVipPortDenyHandler interface { + Handle(GetVsVipPortDenyParams) middleware.Responder +} + +// NewGetVsVipPortDeny creates a new http.Handler for the get vs vip port deny operation +func NewGetVsVipPortDeny(ctx *middleware.Context, handler GetVsVipPortDenyHandler) *GetVsVipPortDeny { + return &GetVsVipPortDeny{Context: ctx, Handler: handler} +} + +/* + GetVsVipPortDeny swagger:route GET /vs/{VipPort}/deny virtualserver getVsVipPortDeny + +GetVsVipPortDeny get vs vip port deny API +*/ +type GetVsVipPortDeny struct { + Context *middleware.Context + Handler GetVsVipPortDenyHandler +} + +func (o *GetVsVipPortDeny) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortDenyParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_parameters.go new file mode 100644 index 000000000..3e8046c1e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_parameters.go @@ -0,0 +1,71 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" +) + +// NewGetVsVipPortDenyParams creates a new GetVsVipPortDenyParams object +// +// There are no default values defined in the spec. +func NewGetVsVipPortDenyParams() GetVsVipPortDenyParams { + + return GetVsVipPortDenyParams{} +} + +// GetVsVipPortDenyParams contains all the bound params for the get vs vip port deny operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPortDeny +type GetVsVipPortDenyParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortDenyParams() beforehand. +func (o *GetVsVipPortDenyParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortDenyParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_responses.go new file mode 100644 index 000000000..38dca5634 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetVsVipPortDenyOKCode is the HTTP code returned for type GetVsVipPortDenyOK +const GetVsVipPortDenyOKCode int = 200 + +/* +GetVsVipPortDenyOK Success + +swagger:response getVsVipPortDenyOK +*/ +type GetVsVipPortDenyOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortDenyOK creates GetVsVipPortDenyOK with default headers values +func NewGetVsVipPortDenyOK() *GetVsVipPortDenyOK { + + return &GetVsVipPortDenyOK{} +} + +// WithPayload adds the payload to the get vs vip port deny o k response +func (o *GetVsVipPortDenyOK) WithPayload(payload string) *GetVsVipPortDenyOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port deny o k response +func (o *GetVsVipPortDenyOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortDenyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetVsVipPortDenyNotFoundCode is the HTTP code returned for type GetVsVipPortDenyNotFound +const GetVsVipPortDenyNotFoundCode int = 404 + +/* +GetVsVipPortDenyNotFound Service not found + +swagger:response getVsVipPortDenyNotFound +*/ +type GetVsVipPortDenyNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortDenyNotFound creates GetVsVipPortDenyNotFound with default headers values +func NewGetVsVipPortDenyNotFound() *GetVsVipPortDenyNotFound { + + return &GetVsVipPortDenyNotFound{} +} + +// WithPayload adds the payload to the get vs vip port deny not found response +func (o *GetVsVipPortDenyNotFound) WithPayload(payload string) *GetVsVipPortDenyNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port deny not found response +func (o *GetVsVipPortDenyNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortDenyNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_urlbuilder.go new file mode 100644 index 000000000..4cbbbbc4e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_deny_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// GetVsVipPortDenyURL generates an URL for the get vs vip port deny operation +type GetVsVipPortDenyURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortDenyURL) WithBasePath(bp string) *GetVsVipPortDenyURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortDenyURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortDenyURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/deny" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortDenyURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortDenyURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortDenyURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortDenyURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortDenyURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortDenyURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortDenyURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr.go new file mode 100644 index 000000000..32e70086c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortLaddrHandlerFunc turns a function with the right signature into a get vs vip port laddr handler +type GetVsVipPortLaddrHandlerFunc func(GetVsVipPortLaddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortLaddrHandlerFunc) Handle(params GetVsVipPortLaddrParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortLaddrHandler interface for that can handle valid get vs vip port laddr params +type GetVsVipPortLaddrHandler interface { + Handle(GetVsVipPortLaddrParams) middleware.Responder +} + +// NewGetVsVipPortLaddr creates a new http.Handler for the get vs vip port laddr operation +func NewGetVsVipPortLaddr(ctx *middleware.Context, handler GetVsVipPortLaddrHandler) *GetVsVipPortLaddr { + return &GetVsVipPortLaddr{Context: ctx, Handler: handler} +} + +/* + GetVsVipPortLaddr swagger:route GET /vs/{VipPort}/laddr virtualserver getVsVipPortLaddr + +GetVsVipPortLaddr get vs vip port laddr API +*/ +type GetVsVipPortLaddr struct { + Context *middleware.Context + Handler GetVsVipPortLaddrHandler +} + +func (o *GetVsVipPortLaddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortLaddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_parameters.go new file mode 100644 index 000000000..0fb9cf281 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetVsVipPortLaddrParams creates a new GetVsVipPortLaddrParams object +// with the default values initialized. +func NewGetVsVipPortLaddrParams() GetVsVipPortLaddrParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetVsVipPortLaddrParams{ + Stats: &statsDefault, + } +} + +// GetVsVipPortLaddrParams contains all the bound params for the get vs vip port laddr operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPortLaddr +type GetVsVipPortLaddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortLaddrParams() beforehand. +func (o *GetVsVipPortLaddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortLaddrParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetVsVipPortLaddrParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetVsVipPortLaddrParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_responses.go new file mode 100644 index 000000000..5ba73eeb0 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_responses.go @@ -0,0 +1,102 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// GetVsVipPortLaddrOKCode is the HTTP code returned for type GetVsVipPortLaddrOK +const GetVsVipPortLaddrOKCode int = 200 + +/* +GetVsVipPortLaddrOK Success + +swagger:response getVsVipPortLaddrOK +*/ +type GetVsVipPortLaddrOK struct { + + /* + In: Body + */ + Payload *models.LocalAddressExpandList `json:"body,omitempty"` +} + +// NewGetVsVipPortLaddrOK creates GetVsVipPortLaddrOK with default headers values +func NewGetVsVipPortLaddrOK() *GetVsVipPortLaddrOK { + + return &GetVsVipPortLaddrOK{} +} + +// WithPayload adds the payload to the get vs vip port laddr o k response +func (o *GetVsVipPortLaddrOK) WithPayload(payload *models.LocalAddressExpandList) *GetVsVipPortLaddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port laddr o k response +func (o *GetVsVipPortLaddrOK) SetPayload(payload *models.LocalAddressExpandList) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortLaddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetVsVipPortLaddrNotFoundCode is the HTTP code returned for type GetVsVipPortLaddrNotFound +const GetVsVipPortLaddrNotFoundCode int = 404 + +/* +GetVsVipPortLaddrNotFound Service not found + +swagger:response getVsVipPortLaddrNotFound +*/ +type GetVsVipPortLaddrNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortLaddrNotFound creates GetVsVipPortLaddrNotFound with default headers values +func NewGetVsVipPortLaddrNotFound() *GetVsVipPortLaddrNotFound { + + return &GetVsVipPortLaddrNotFound{} +} + +// WithPayload adds the payload to the get vs vip port laddr not found response +func (o *GetVsVipPortLaddrNotFound) WithPayload(payload string) *GetVsVipPortLaddrNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port laddr not found response +func (o *GetVsVipPortLaddrNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortLaddrNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_urlbuilder.go new file mode 100644 index 000000000..053283e75 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_laddr_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetVsVipPortLaddrURL generates an URL for the get vs vip port laddr operation +type GetVsVipPortLaddrURL struct { + VipPort string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortLaddrURL) WithBasePath(bp string) *GetVsVipPortLaddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortLaddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortLaddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/laddr" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortLaddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortLaddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortLaddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortLaddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortLaddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortLaddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortLaddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_parameters.go new file mode 100644 index 000000000..a917c108a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetVsVipPortParams creates a new GetVsVipPortParams object +// with the default values initialized. +func NewGetVsVipPortParams() GetVsVipPortParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetVsVipPortParams{ + Stats: &statsDefault, + } +} + +// GetVsVipPortParams contains all the bound params for the get vs vip port operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPort +type GetVsVipPortParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortParams() beforehand. +func (o *GetVsVipPortParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetVsVipPortParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetVsVipPortParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_responses.go new file mode 100644 index 000000000..83d209125 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_responses.go @@ -0,0 +1,102 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// GetVsVipPortOKCode is the HTTP code returned for type GetVsVipPortOK +const GetVsVipPortOKCode int = 200 + +/* +GetVsVipPortOK Success + +swagger:response getVsVipPortOK +*/ +type GetVsVipPortOK struct { + + /* + In: Body + */ + Payload *models.VirtualServerList `json:"body,omitempty"` +} + +// NewGetVsVipPortOK creates GetVsVipPortOK with default headers values +func NewGetVsVipPortOK() *GetVsVipPortOK { + + return &GetVsVipPortOK{} +} + +// WithPayload adds the payload to the get vs vip port o k response +func (o *GetVsVipPortOK) WithPayload(payload *models.VirtualServerList) *GetVsVipPortOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port o k response +func (o *GetVsVipPortOK) SetPayload(payload *models.VirtualServerList) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetVsVipPortNotFoundCode is the HTTP code returned for type GetVsVipPortNotFound +const GetVsVipPortNotFoundCode int = 404 + +/* +GetVsVipPortNotFound Service not found + +swagger:response getVsVipPortNotFound +*/ +type GetVsVipPortNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortNotFound creates GetVsVipPortNotFound with default headers values +func NewGetVsVipPortNotFound() *GetVsVipPortNotFound { + + return &GetVsVipPortNotFound{} +} + +// WithPayload adds the payload to the get vs vip port not found response +func (o *GetVsVipPortNotFound) WithPayload(payload string) *GetVsVipPortNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port not found response +func (o *GetVsVipPortNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs.go new file mode 100644 index 000000000..05692a9ba --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// GetVsVipPortRsHandlerFunc turns a function with the right signature into a get vs vip port rs handler +type GetVsVipPortRsHandlerFunc func(GetVsVipPortRsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetVsVipPortRsHandlerFunc) Handle(params GetVsVipPortRsParams) middleware.Responder { + return fn(params) +} + +// GetVsVipPortRsHandler interface for that can handle valid get vs vip port rs params +type GetVsVipPortRsHandler interface { + Handle(GetVsVipPortRsParams) middleware.Responder +} + +// NewGetVsVipPortRs creates a new http.Handler for the get vs vip port rs operation +func NewGetVsVipPortRs(ctx *middleware.Context, handler GetVsVipPortRsHandler) *GetVsVipPortRs { + return &GetVsVipPortRs{Context: ctx, Handler: handler} +} + +/* + GetVsVipPortRs swagger:route GET /vs/{VipPort}/rs virtualserver getVsVipPortRs + +GetVsVipPortRs get vs vip port rs API +*/ +type GetVsVipPortRs struct { + Context *middleware.Context + Handler GetVsVipPortRsHandler +} + +func (o *GetVsVipPortRs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetVsVipPortRsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_parameters.go new file mode 100644 index 000000000..422d711e1 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_parameters.go @@ -0,0 +1,116 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewGetVsVipPortRsParams creates a new GetVsVipPortRsParams object +// with the default values initialized. +func NewGetVsVipPortRsParams() GetVsVipPortRsParams { + + var ( + // initialize parameters with default values + + statsDefault = bool(false) + ) + + return GetVsVipPortRsParams{ + Stats: &statsDefault, + } +} + +// GetVsVipPortRsParams contains all the bound params for the get vs vip port rs operation +// typically these are obtained from a http.Request +// +// swagger:parameters GetVsVipPortRs +type GetVsVipPortRsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: query + Default: false + */ + Stats *bool +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewGetVsVipPortRsParams() beforehand. +func (o *GetVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + qStats, qhkStats, _ := qs.GetOK("stats") + if err := o.bindStats(qStats, qhkStats, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *GetVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} + +// bindStats binds and validates parameter Stats from query. +func (o *GetVsVipPortRsParams) bindStats(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewGetVsVipPortRsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("stats", "query", "bool", raw) + } + o.Stats = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_responses.go new file mode 100644 index 000000000..54df068a5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_responses.go @@ -0,0 +1,98 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" +) + +// GetVsVipPortRsOKCode is the HTTP code returned for type GetVsVipPortRsOK +const GetVsVipPortRsOKCode int = 200 + +/* +GetVsVipPortRsOK Success + +swagger:response getVsVipPortRsOK +*/ +type GetVsVipPortRsOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortRsOK creates GetVsVipPortRsOK with default headers values +func NewGetVsVipPortRsOK() *GetVsVipPortRsOK { + + return &GetVsVipPortRsOK{} +} + +// WithPayload adds the payload to the get vs vip port rs o k response +func (o *GetVsVipPortRsOK) WithPayload(payload string) *GetVsVipPortRsOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port rs o k response +func (o *GetVsVipPortRsOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortRsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// GetVsVipPortRsNotFoundCode is the HTTP code returned for type GetVsVipPortRsNotFound +const GetVsVipPortRsNotFoundCode int = 404 + +/* +GetVsVipPortRsNotFound Service not found + +swagger:response getVsVipPortRsNotFound +*/ +type GetVsVipPortRsNotFound struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewGetVsVipPortRsNotFound creates GetVsVipPortRsNotFound with default headers values +func NewGetVsVipPortRsNotFound() *GetVsVipPortRsNotFound { + + return &GetVsVipPortRsNotFound{} +} + +// WithPayload adds the payload to the get vs vip port rs not found response +func (o *GetVsVipPortRsNotFound) WithPayload(payload string) *GetVsVipPortRsNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get vs vip port rs not found response +func (o *GetVsVipPortRsNotFound) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetVsVipPortRsNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_urlbuilder.go new file mode 100644 index 000000000..f97a471ed --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_rs_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetVsVipPortRsURL generates an URL for the get vs vip port rs operation +type GetVsVipPortRsURL struct { + VipPort string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortRsURL) WithBasePath(bp string) *GetVsVipPortRsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortRsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortRsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/rs" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortRsURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortRsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortRsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortRsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortRsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortRsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortRsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_urlbuilder.go new file mode 100644 index 000000000..699572745 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/get_vs_vip_port_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// GetVsVipPortURL generates an URL for the get vs vip port operation +type GetVsVipPortURL struct { + VipPort string + + Stats *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortURL) WithBasePath(bp string) *GetVsVipPortURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *GetVsVipPortURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetVsVipPortURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on GetVsVipPortURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var statsQ string + if o.Stats != nil { + statsQ = swag.FormatBool(*o.Stats) + } + if statsQ != "" { + qs.Set("stats", statsQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *GetVsVipPortURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *GetVsVipPortURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetVsVipPortURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetVsVipPortURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetVsVipPortURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *GetVsVipPortURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow.go new file mode 100644 index 000000000..d5d55cb5e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PostVsVipPortAllowHandlerFunc turns a function with the right signature into a post vs vip port allow handler +type PostVsVipPortAllowHandlerFunc func(PostVsVipPortAllowParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PostVsVipPortAllowHandlerFunc) Handle(params PostVsVipPortAllowParams) middleware.Responder { + return fn(params) +} + +// PostVsVipPortAllowHandler interface for that can handle valid post vs vip port allow params +type PostVsVipPortAllowHandler interface { + Handle(PostVsVipPortAllowParams) middleware.Responder +} + +// NewPostVsVipPortAllow creates a new http.Handler for the post vs vip port allow operation +func NewPostVsVipPortAllow(ctx *middleware.Context, handler PostVsVipPortAllowHandler) *PostVsVipPortAllow { + return &PostVsVipPortAllow{Context: ctx, Handler: handler} +} + +/* + PostVsVipPortAllow swagger:route POST /vs/{VipPort}/allow virtualserver postVsVipPortAllow + +Update a fully white ip list to vip:port:proto +*/ +type PostVsVipPortAllow struct { + Context *middleware.Context + Handler PostVsVipPortAllowHandler +} + +func (o *PostVsVipPortAllow) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPostVsVipPortAllowParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_parameters.go new file mode 100644 index 000000000..6b2511250 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPostVsVipPortAllowParams creates a new PostVsVipPortAllowParams object +// +// There are no default values defined in the spec. +func NewPostVsVipPortAllowParams() PostVsVipPortAllowParams { + + return PostVsVipPortAllowParams{} +} + +// PostVsVipPortAllowParams contains all the bound params for the post vs vip port allow operation +// typically these are obtained from a http.Request +// +// swagger:parameters PostVsVipPortAllow +type PostVsVipPortAllowParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPostVsVipPortAllowParams() beforehand. +func (o *PostVsVipPortAllowParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PostVsVipPortAllowParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_responses.go new file mode 100644 index 000000000..b1d15b9c8 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PostVsVipPortAllowOKCode is the HTTP code returned for type PostVsVipPortAllowOK +const PostVsVipPortAllowOKCode int = 200 + +/* +PostVsVipPortAllowOK Success + +swagger:response postVsVipPortAllowOK +*/ +type PostVsVipPortAllowOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowOK creates PostVsVipPortAllowOK with default headers values +func NewPostVsVipPortAllowOK() *PostVsVipPortAllowOK { + + return &PostVsVipPortAllowOK{} +} + +// WithPayload adds the payload to the post vs vip port allow o k response +func (o *PostVsVipPortAllowOK) WithPayload(payload string) *PostVsVipPortAllowOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow o k response +func (o *PostVsVipPortAllowOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortAllowCreatedCode is the HTTP code returned for type PostVsVipPortAllowCreated +const PostVsVipPortAllowCreatedCode int = 201 + +/* +PostVsVipPortAllowCreated Created + +swagger:response postVsVipPortAllowCreated +*/ +type PostVsVipPortAllowCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowCreated creates PostVsVipPortAllowCreated with default headers values +func NewPostVsVipPortAllowCreated() *PostVsVipPortAllowCreated { + + return &PostVsVipPortAllowCreated{} +} + +// WithPayload adds the payload to the post vs vip port allow created response +func (o *PostVsVipPortAllowCreated) WithPayload(payload string) *PostVsVipPortAllowCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow created response +func (o *PostVsVipPortAllowCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortAllowInvalidFrontendCode is the HTTP code returned for type PostVsVipPortAllowInvalidFrontend +const PostVsVipPortAllowInvalidFrontendCode int = 460 + +/* +PostVsVipPortAllowInvalidFrontend Invalid frontend in service configuration + +swagger:response postVsVipPortAllowInvalidFrontend +*/ +type PostVsVipPortAllowInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowInvalidFrontend creates PostVsVipPortAllowInvalidFrontend with default headers values +func NewPostVsVipPortAllowInvalidFrontend() *PostVsVipPortAllowInvalidFrontend { + + return &PostVsVipPortAllowInvalidFrontend{} +} + +// WithPayload adds the payload to the post vs vip port allow invalid frontend response +func (o *PostVsVipPortAllowInvalidFrontend) WithPayload(payload models.Error) *PostVsVipPortAllowInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow invalid frontend response +func (o *PostVsVipPortAllowInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortAllowInvalidBackendCode is the HTTP code returned for type PostVsVipPortAllowInvalidBackend +const PostVsVipPortAllowInvalidBackendCode int = 461 + +/* +PostVsVipPortAllowInvalidBackend Invalid backend in service configuration + +swagger:response postVsVipPortAllowInvalidBackend +*/ +type PostVsVipPortAllowInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowInvalidBackend creates PostVsVipPortAllowInvalidBackend with default headers values +func NewPostVsVipPortAllowInvalidBackend() *PostVsVipPortAllowInvalidBackend { + + return &PostVsVipPortAllowInvalidBackend{} +} + +// WithPayload adds the payload to the post vs vip port allow invalid backend response +func (o *PostVsVipPortAllowInvalidBackend) WithPayload(payload models.Error) *PostVsVipPortAllowInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow invalid backend response +func (o *PostVsVipPortAllowInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortAllowFailureCode is the HTTP code returned for type PostVsVipPortAllowFailure +const PostVsVipPortAllowFailureCode int = 500 + +/* +PostVsVipPortAllowFailure Service deletion failed + +swagger:response postVsVipPortAllowFailure +*/ +type PostVsVipPortAllowFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortAllowFailure creates PostVsVipPortAllowFailure with default headers values +func NewPostVsVipPortAllowFailure() *PostVsVipPortAllowFailure { + + return &PostVsVipPortAllowFailure{} +} + +// WithPayload adds the payload to the post vs vip port allow failure response +func (o *PostVsVipPortAllowFailure) WithPayload(payload models.Error) *PostVsVipPortAllowFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port allow failure response +func (o *PostVsVipPortAllowFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortAllowFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_urlbuilder.go new file mode 100644 index 000000000..c7edb0b96 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_allow_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PostVsVipPortAllowURL generates an URL for the post vs vip port allow operation +type PostVsVipPortAllowURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortAllowURL) WithBasePath(bp string) *PostVsVipPortAllowURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortAllowURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PostVsVipPortAllowURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/allow" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PostVsVipPortAllowURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PostVsVipPortAllowURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PostVsVipPortAllowURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PostVsVipPortAllowURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PostVsVipPortAllowURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PostVsVipPortAllowURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PostVsVipPortAllowURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny.go new file mode 100644 index 000000000..d19eee50e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PostVsVipPortDenyHandlerFunc turns a function with the right signature into a post vs vip port deny handler +type PostVsVipPortDenyHandlerFunc func(PostVsVipPortDenyParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PostVsVipPortDenyHandlerFunc) Handle(params PostVsVipPortDenyParams) middleware.Responder { + return fn(params) +} + +// PostVsVipPortDenyHandler interface for that can handle valid post vs vip port deny params +type PostVsVipPortDenyHandler interface { + Handle(PostVsVipPortDenyParams) middleware.Responder +} + +// NewPostVsVipPortDeny creates a new http.Handler for the post vs vip port deny operation +func NewPostVsVipPortDeny(ctx *middleware.Context, handler PostVsVipPortDenyHandler) *PostVsVipPortDeny { + return &PostVsVipPortDeny{Context: ctx, Handler: handler} +} + +/* + PostVsVipPortDeny swagger:route POST /vs/{VipPort}/deny virtualserver postVsVipPortDeny + +Update a fully black ip list to vip:port:proto +*/ +type PostVsVipPortDeny struct { + Context *middleware.Context + Handler PostVsVipPortDenyHandler +} + +func (o *PostVsVipPortDeny) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPostVsVipPortDenyParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_parameters.go new file mode 100644 index 000000000..56f735df3 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPostVsVipPortDenyParams creates a new PostVsVipPortDenyParams object +// +// There are no default values defined in the spec. +func NewPostVsVipPortDenyParams() PostVsVipPortDenyParams { + + return PostVsVipPortDenyParams{} +} + +// PostVsVipPortDenyParams contains all the bound params for the post vs vip port deny operation +// typically these are obtained from a http.Request +// +// swagger:parameters PostVsVipPortDeny +type PostVsVipPortDenyParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPostVsVipPortDenyParams() beforehand. +func (o *PostVsVipPortDenyParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PostVsVipPortDenyParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_responses.go new file mode 100644 index 000000000..8e813626d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PostVsVipPortDenyOKCode is the HTTP code returned for type PostVsVipPortDenyOK +const PostVsVipPortDenyOKCode int = 200 + +/* +PostVsVipPortDenyOK Success + +swagger:response postVsVipPortDenyOK +*/ +type PostVsVipPortDenyOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyOK creates PostVsVipPortDenyOK with default headers values +func NewPostVsVipPortDenyOK() *PostVsVipPortDenyOK { + + return &PostVsVipPortDenyOK{} +} + +// WithPayload adds the payload to the post vs vip port deny o k response +func (o *PostVsVipPortDenyOK) WithPayload(payload string) *PostVsVipPortDenyOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny o k response +func (o *PostVsVipPortDenyOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortDenyCreatedCode is the HTTP code returned for type PostVsVipPortDenyCreated +const PostVsVipPortDenyCreatedCode int = 201 + +/* +PostVsVipPortDenyCreated Created + +swagger:response postVsVipPortDenyCreated +*/ +type PostVsVipPortDenyCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyCreated creates PostVsVipPortDenyCreated with default headers values +func NewPostVsVipPortDenyCreated() *PostVsVipPortDenyCreated { + + return &PostVsVipPortDenyCreated{} +} + +// WithPayload adds the payload to the post vs vip port deny created response +func (o *PostVsVipPortDenyCreated) WithPayload(payload string) *PostVsVipPortDenyCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny created response +func (o *PostVsVipPortDenyCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortDenyInvalidFrontendCode is the HTTP code returned for type PostVsVipPortDenyInvalidFrontend +const PostVsVipPortDenyInvalidFrontendCode int = 460 + +/* +PostVsVipPortDenyInvalidFrontend Invalid frontend in service configuration + +swagger:response postVsVipPortDenyInvalidFrontend +*/ +type PostVsVipPortDenyInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyInvalidFrontend creates PostVsVipPortDenyInvalidFrontend with default headers values +func NewPostVsVipPortDenyInvalidFrontend() *PostVsVipPortDenyInvalidFrontend { + + return &PostVsVipPortDenyInvalidFrontend{} +} + +// WithPayload adds the payload to the post vs vip port deny invalid frontend response +func (o *PostVsVipPortDenyInvalidFrontend) WithPayload(payload models.Error) *PostVsVipPortDenyInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny invalid frontend response +func (o *PostVsVipPortDenyInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortDenyInvalidBackendCode is the HTTP code returned for type PostVsVipPortDenyInvalidBackend +const PostVsVipPortDenyInvalidBackendCode int = 461 + +/* +PostVsVipPortDenyInvalidBackend Invalid backend in service configuration + +swagger:response postVsVipPortDenyInvalidBackend +*/ +type PostVsVipPortDenyInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyInvalidBackend creates PostVsVipPortDenyInvalidBackend with default headers values +func NewPostVsVipPortDenyInvalidBackend() *PostVsVipPortDenyInvalidBackend { + + return &PostVsVipPortDenyInvalidBackend{} +} + +// WithPayload adds the payload to the post vs vip port deny invalid backend response +func (o *PostVsVipPortDenyInvalidBackend) WithPayload(payload models.Error) *PostVsVipPortDenyInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny invalid backend response +func (o *PostVsVipPortDenyInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortDenyFailureCode is the HTTP code returned for type PostVsVipPortDenyFailure +const PostVsVipPortDenyFailureCode int = 500 + +/* +PostVsVipPortDenyFailure Service deletion failed + +swagger:response postVsVipPortDenyFailure +*/ +type PostVsVipPortDenyFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortDenyFailure creates PostVsVipPortDenyFailure with default headers values +func NewPostVsVipPortDenyFailure() *PostVsVipPortDenyFailure { + + return &PostVsVipPortDenyFailure{} +} + +// WithPayload adds the payload to the post vs vip port deny failure response +func (o *PostVsVipPortDenyFailure) WithPayload(payload models.Error) *PostVsVipPortDenyFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port deny failure response +func (o *PostVsVipPortDenyFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortDenyFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_urlbuilder.go new file mode 100644 index 000000000..b63560b1d --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_deny_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PostVsVipPortDenyURL generates an URL for the post vs vip port deny operation +type PostVsVipPortDenyURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortDenyURL) WithBasePath(bp string) *PostVsVipPortDenyURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortDenyURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PostVsVipPortDenyURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/deny" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PostVsVipPortDenyURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PostVsVipPortDenyURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PostVsVipPortDenyURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PostVsVipPortDenyURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PostVsVipPortDenyURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PostVsVipPortDenyURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PostVsVipPortDenyURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs.go new file mode 100644 index 000000000..26ff3ea34 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PostVsVipPortRsHandlerFunc turns a function with the right signature into a post vs vip port rs handler +type PostVsVipPortRsHandlerFunc func(PostVsVipPortRsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PostVsVipPortRsHandlerFunc) Handle(params PostVsVipPortRsParams) middleware.Responder { + return fn(params) +} + +// PostVsVipPortRsHandler interface for that can handle valid post vs vip port rs params +type PostVsVipPortRsHandler interface { + Handle(PostVsVipPortRsParams) middleware.Responder +} + +// NewPostVsVipPortRs creates a new http.Handler for the post vs vip port rs operation +func NewPostVsVipPortRs(ctx *middleware.Context, handler PostVsVipPortRsHandler) *PostVsVipPortRs { + return &PostVsVipPortRs{Context: ctx, Handler: handler} +} + +/* + PostVsVipPortRs swagger:route POST /vs/{VipPort}/rs virtualserver postVsVipPortRs + +Update fully real server list to vip:port:proto +*/ +type PostVsVipPortRs struct { + Context *middleware.Context + Handler PostVsVipPortRsHandler +} + +func (o *PostVsVipPortRs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPostVsVipPortRsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go new file mode 100644 index 000000000..948a9f38b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPostVsVipPortRsParams creates a new PostVsVipPortRsParams object +// +// There are no default values defined in the spec. +func NewPostVsVipPortRsParams() PostVsVipPortRsParams { + + return PostVsVipPortRsParams{} +} + +// PostVsVipPortRsParams contains all the bound params for the post vs vip port rs operation +// typically these are obtained from a http.Request +// +// swagger:parameters PostVsVipPortRs +type PostVsVipPortRsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Rss *models.RealServerTinyList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPostVsVipPortRsParams() beforehand. +func (o *PostVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RealServerTinyList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("rss", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Rss = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PostVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_responses.go new file mode 100644 index 000000000..fd154d53e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PostVsVipPortRsOKCode is the HTTP code returned for type PostVsVipPortRsOK +const PostVsVipPortRsOKCode int = 200 + +/* +PostVsVipPortRsOK Success + +swagger:response postVsVipPortRsOK +*/ +type PostVsVipPortRsOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortRsOK creates PostVsVipPortRsOK with default headers values +func NewPostVsVipPortRsOK() *PostVsVipPortRsOK { + + return &PostVsVipPortRsOK{} +} + +// WithPayload adds the payload to the post vs vip port rs o k response +func (o *PostVsVipPortRsOK) WithPayload(payload string) *PostVsVipPortRsOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs o k response +func (o *PostVsVipPortRsOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortRsCreatedCode is the HTTP code returned for type PostVsVipPortRsCreated +const PostVsVipPortRsCreatedCode int = 201 + +/* +PostVsVipPortRsCreated Created + +swagger:response postVsVipPortRsCreated +*/ +type PostVsVipPortRsCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPostVsVipPortRsCreated creates PostVsVipPortRsCreated with default headers values +func NewPostVsVipPortRsCreated() *PostVsVipPortRsCreated { + + return &PostVsVipPortRsCreated{} +} + +// WithPayload adds the payload to the post vs vip port rs created response +func (o *PostVsVipPortRsCreated) WithPayload(payload string) *PostVsVipPortRsCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs created response +func (o *PostVsVipPortRsCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortRsInvalidFrontendCode is the HTTP code returned for type PostVsVipPortRsInvalidFrontend +const PostVsVipPortRsInvalidFrontendCode int = 460 + +/* +PostVsVipPortRsInvalidFrontend Invalid frontend in service configuration + +swagger:response postVsVipPortRsInvalidFrontend +*/ +type PostVsVipPortRsInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortRsInvalidFrontend creates PostVsVipPortRsInvalidFrontend with default headers values +func NewPostVsVipPortRsInvalidFrontend() *PostVsVipPortRsInvalidFrontend { + + return &PostVsVipPortRsInvalidFrontend{} +} + +// WithPayload adds the payload to the post vs vip port rs invalid frontend response +func (o *PostVsVipPortRsInvalidFrontend) WithPayload(payload models.Error) *PostVsVipPortRsInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs invalid frontend response +func (o *PostVsVipPortRsInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortRsInvalidBackendCode is the HTTP code returned for type PostVsVipPortRsInvalidBackend +const PostVsVipPortRsInvalidBackendCode int = 461 + +/* +PostVsVipPortRsInvalidBackend Invalid backend in service configuration + +swagger:response postVsVipPortRsInvalidBackend +*/ +type PostVsVipPortRsInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortRsInvalidBackend creates PostVsVipPortRsInvalidBackend with default headers values +func NewPostVsVipPortRsInvalidBackend() *PostVsVipPortRsInvalidBackend { + + return &PostVsVipPortRsInvalidBackend{} +} + +// WithPayload adds the payload to the post vs vip port rs invalid backend response +func (o *PostVsVipPortRsInvalidBackend) WithPayload(payload models.Error) *PostVsVipPortRsInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs invalid backend response +func (o *PostVsVipPortRsInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PostVsVipPortRsFailureCode is the HTTP code returned for type PostVsVipPortRsFailure +const PostVsVipPortRsFailureCode int = 500 + +/* +PostVsVipPortRsFailure Service deletion failed + +swagger:response postVsVipPortRsFailure +*/ +type PostVsVipPortRsFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPostVsVipPortRsFailure creates PostVsVipPortRsFailure with default headers values +func NewPostVsVipPortRsFailure() *PostVsVipPortRsFailure { + + return &PostVsVipPortRsFailure{} +} + +// WithPayload adds the payload to the post vs vip port rs failure response +func (o *PostVsVipPortRsFailure) WithPayload(payload models.Error) *PostVsVipPortRsFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the post vs vip port rs failure response +func (o *PostVsVipPortRsFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PostVsVipPortRsFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go new file mode 100644 index 000000000..1c7f7b01e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/post_vs_vip_port_rs_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PostVsVipPortRsURL generates an URL for the post vs vip port rs operation +type PostVsVipPortRsURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortRsURL) WithBasePath(bp string) *PostVsVipPortRsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PostVsVipPortRsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PostVsVipPortRsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/rs" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PostVsVipPortRsURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PostVsVipPortRsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PostVsVipPortRsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PostVsVipPortRsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PostVsVipPortRsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PostVsVipPortRsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PostVsVipPortRsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port.go new file mode 100644 index 000000000..78b20e404 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortHandlerFunc turns a function with the right signature into a put vs vip port handler +type PutVsVipPortHandlerFunc func(PutVsVipPortParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortHandlerFunc) Handle(params PutVsVipPortParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortHandler interface for that can handle valid put vs vip port params +type PutVsVipPortHandler interface { + Handle(PutVsVipPortParams) middleware.Responder +} + +// NewPutVsVipPort creates a new http.Handler for the put vs vip port operation +func NewPutVsVipPort(ctx *middleware.Context, handler PutVsVipPortHandler) *PutVsVipPort { + return &PutVsVipPort{Context: ctx, Handler: handler} +} + +/* + PutVsVipPort swagger:route PUT /vs/{VipPort} virtualserver putVsVipPort + +create or update virtual server +*/ +type PutVsVipPort struct { + Context *middleware.Context + Handler PutVsVipPortHandler +} + +func (o *PutVsVipPort) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow.go new file mode 100644 index 000000000..d3fa4b93c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortAllowHandlerFunc turns a function with the right signature into a put vs vip port allow handler +type PutVsVipPortAllowHandlerFunc func(PutVsVipPortAllowParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortAllowHandlerFunc) Handle(params PutVsVipPortAllowParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortAllowHandler interface for that can handle valid put vs vip port allow params +type PutVsVipPortAllowHandler interface { + Handle(PutVsVipPortAllowParams) middleware.Responder +} + +// NewPutVsVipPortAllow creates a new http.Handler for the put vs vip port allow operation +func NewPutVsVipPortAllow(ctx *middleware.Context, handler PutVsVipPortAllowHandler) *PutVsVipPortAllow { + return &PutVsVipPortAllow{Context: ctx, Handler: handler} +} + +/* + PutVsVipPortAllow swagger:route PUT /vs/{VipPort}/allow virtualserver putVsVipPortAllow + +Add a set of ip from white list to vip:port:proto +*/ +type PutVsVipPortAllow struct { + Context *middleware.Context + Handler PutVsVipPortAllowHandler +} + +func (o *PutVsVipPortAllow) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortAllowParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_parameters.go new file mode 100644 index 000000000..dfb8da2e2 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortAllowParams creates a new PutVsVipPortAllowParams object +// +// There are no default values defined in the spec. +func NewPutVsVipPortAllowParams() PutVsVipPortAllowParams { + + return PutVsVipPortAllowParams{} +} + +// PutVsVipPortAllowParams contains all the bound params for the put vs vip port allow operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPortAllow +type PutVsVipPortAllowParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortAllowParams() beforehand. +func (o *PutVsVipPortAllowParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortAllowParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_responses.go new file mode 100644 index 000000000..38d69cf91 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortAllowOKCode is the HTTP code returned for type PutVsVipPortAllowOK +const PutVsVipPortAllowOKCode int = 200 + +/* +PutVsVipPortAllowOK Success + +swagger:response putVsVipPortAllowOK +*/ +type PutVsVipPortAllowOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowOK creates PutVsVipPortAllowOK with default headers values +func NewPutVsVipPortAllowOK() *PutVsVipPortAllowOK { + + return &PutVsVipPortAllowOK{} +} + +// WithPayload adds the payload to the put vs vip port allow o k response +func (o *PutVsVipPortAllowOK) WithPayload(payload string) *PutVsVipPortAllowOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow o k response +func (o *PutVsVipPortAllowOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortAllowCreatedCode is the HTTP code returned for type PutVsVipPortAllowCreated +const PutVsVipPortAllowCreatedCode int = 201 + +/* +PutVsVipPortAllowCreated Created + +swagger:response putVsVipPortAllowCreated +*/ +type PutVsVipPortAllowCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowCreated creates PutVsVipPortAllowCreated with default headers values +func NewPutVsVipPortAllowCreated() *PutVsVipPortAllowCreated { + + return &PutVsVipPortAllowCreated{} +} + +// WithPayload adds the payload to the put vs vip port allow created response +func (o *PutVsVipPortAllowCreated) WithPayload(payload string) *PutVsVipPortAllowCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow created response +func (o *PutVsVipPortAllowCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortAllowInvalidFrontendCode is the HTTP code returned for type PutVsVipPortAllowInvalidFrontend +const PutVsVipPortAllowInvalidFrontendCode int = 460 + +/* +PutVsVipPortAllowInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortAllowInvalidFrontend +*/ +type PutVsVipPortAllowInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowInvalidFrontend creates PutVsVipPortAllowInvalidFrontend with default headers values +func NewPutVsVipPortAllowInvalidFrontend() *PutVsVipPortAllowInvalidFrontend { + + return &PutVsVipPortAllowInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port allow invalid frontend response +func (o *PutVsVipPortAllowInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortAllowInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow invalid frontend response +func (o *PutVsVipPortAllowInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortAllowInvalidBackendCode is the HTTP code returned for type PutVsVipPortAllowInvalidBackend +const PutVsVipPortAllowInvalidBackendCode int = 461 + +/* +PutVsVipPortAllowInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortAllowInvalidBackend +*/ +type PutVsVipPortAllowInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowInvalidBackend creates PutVsVipPortAllowInvalidBackend with default headers values +func NewPutVsVipPortAllowInvalidBackend() *PutVsVipPortAllowInvalidBackend { + + return &PutVsVipPortAllowInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port allow invalid backend response +func (o *PutVsVipPortAllowInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortAllowInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow invalid backend response +func (o *PutVsVipPortAllowInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortAllowFailureCode is the HTTP code returned for type PutVsVipPortAllowFailure +const PutVsVipPortAllowFailureCode int = 500 + +/* +PutVsVipPortAllowFailure Service deletion failed + +swagger:response putVsVipPortAllowFailure +*/ +type PutVsVipPortAllowFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortAllowFailure creates PutVsVipPortAllowFailure with default headers values +func NewPutVsVipPortAllowFailure() *PutVsVipPortAllowFailure { + + return &PutVsVipPortAllowFailure{} +} + +// WithPayload adds the payload to the put vs vip port allow failure response +func (o *PutVsVipPortAllowFailure) WithPayload(payload models.Error) *PutVsVipPortAllowFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port allow failure response +func (o *PutVsVipPortAllowFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortAllowFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_urlbuilder.go new file mode 100644 index 000000000..ba8719936 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_allow_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutVsVipPortAllowURL generates an URL for the put vs vip port allow operation +type PutVsVipPortAllowURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortAllowURL) WithBasePath(bp string) *PutVsVipPortAllowURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortAllowURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortAllowURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/allow" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortAllowURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortAllowURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortAllowURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortAllowURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortAllowURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortAllowURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortAllowURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny.go new file mode 100644 index 000000000..180e1242b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortDenyHandlerFunc turns a function with the right signature into a put vs vip port deny handler +type PutVsVipPortDenyHandlerFunc func(PutVsVipPortDenyParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortDenyHandlerFunc) Handle(params PutVsVipPortDenyParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortDenyHandler interface for that can handle valid put vs vip port deny params +type PutVsVipPortDenyHandler interface { + Handle(PutVsVipPortDenyParams) middleware.Responder +} + +// NewPutVsVipPortDeny creates a new http.Handler for the put vs vip port deny operation +func NewPutVsVipPortDeny(ctx *middleware.Context, handler PutVsVipPortDenyHandler) *PutVsVipPortDeny { + return &PutVsVipPortDeny{Context: ctx, Handler: handler} +} + +/* + PutVsVipPortDeny swagger:route PUT /vs/{VipPort}/deny virtualserver putVsVipPortDeny + +Add a set of ip from black list to vip:port:proto +*/ +type PutVsVipPortDeny struct { + Context *middleware.Context + Handler PutVsVipPortDenyHandler +} + +func (o *PutVsVipPortDeny) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortDenyParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_parameters.go new file mode 100644 index 000000000..6d28ff26e --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortDenyParams creates a new PutVsVipPortDenyParams object +// +// There are no default values defined in the spec. +func NewPutVsVipPortDenyParams() PutVsVipPortDenyParams { + + return PutVsVipPortDenyParams{} +} + +// PutVsVipPortDenyParams contains all the bound params for the put vs vip port deny operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPortDeny +type PutVsVipPortDenyParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + ACL *models.ACLAddrList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortDenyParams() beforehand. +func (o *PutVsVipPortDenyParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.ACLAddrList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("acl", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.ACL = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortDenyParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_responses.go new file mode 100644 index 000000000..aae11334f --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortDenyOKCode is the HTTP code returned for type PutVsVipPortDenyOK +const PutVsVipPortDenyOKCode int = 200 + +/* +PutVsVipPortDenyOK Success + +swagger:response putVsVipPortDenyOK +*/ +type PutVsVipPortDenyOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyOK creates PutVsVipPortDenyOK with default headers values +func NewPutVsVipPortDenyOK() *PutVsVipPortDenyOK { + + return &PutVsVipPortDenyOK{} +} + +// WithPayload adds the payload to the put vs vip port deny o k response +func (o *PutVsVipPortDenyOK) WithPayload(payload string) *PutVsVipPortDenyOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny o k response +func (o *PutVsVipPortDenyOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortDenyCreatedCode is the HTTP code returned for type PutVsVipPortDenyCreated +const PutVsVipPortDenyCreatedCode int = 201 + +/* +PutVsVipPortDenyCreated Created + +swagger:response putVsVipPortDenyCreated +*/ +type PutVsVipPortDenyCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyCreated creates PutVsVipPortDenyCreated with default headers values +func NewPutVsVipPortDenyCreated() *PutVsVipPortDenyCreated { + + return &PutVsVipPortDenyCreated{} +} + +// WithPayload adds the payload to the put vs vip port deny created response +func (o *PutVsVipPortDenyCreated) WithPayload(payload string) *PutVsVipPortDenyCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny created response +func (o *PutVsVipPortDenyCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortDenyInvalidFrontendCode is the HTTP code returned for type PutVsVipPortDenyInvalidFrontend +const PutVsVipPortDenyInvalidFrontendCode int = 460 + +/* +PutVsVipPortDenyInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortDenyInvalidFrontend +*/ +type PutVsVipPortDenyInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyInvalidFrontend creates PutVsVipPortDenyInvalidFrontend with default headers values +func NewPutVsVipPortDenyInvalidFrontend() *PutVsVipPortDenyInvalidFrontend { + + return &PutVsVipPortDenyInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port deny invalid frontend response +func (o *PutVsVipPortDenyInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortDenyInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny invalid frontend response +func (o *PutVsVipPortDenyInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortDenyInvalidBackendCode is the HTTP code returned for type PutVsVipPortDenyInvalidBackend +const PutVsVipPortDenyInvalidBackendCode int = 461 + +/* +PutVsVipPortDenyInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortDenyInvalidBackend +*/ +type PutVsVipPortDenyInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyInvalidBackend creates PutVsVipPortDenyInvalidBackend with default headers values +func NewPutVsVipPortDenyInvalidBackend() *PutVsVipPortDenyInvalidBackend { + + return &PutVsVipPortDenyInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port deny invalid backend response +func (o *PutVsVipPortDenyInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortDenyInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny invalid backend response +func (o *PutVsVipPortDenyInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortDenyFailureCode is the HTTP code returned for type PutVsVipPortDenyFailure +const PutVsVipPortDenyFailureCode int = 500 + +/* +PutVsVipPortDenyFailure Service deletion failed + +swagger:response putVsVipPortDenyFailure +*/ +type PutVsVipPortDenyFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortDenyFailure creates PutVsVipPortDenyFailure with default headers values +func NewPutVsVipPortDenyFailure() *PutVsVipPortDenyFailure { + + return &PutVsVipPortDenyFailure{} +} + +// WithPayload adds the payload to the put vs vip port deny failure response +func (o *PutVsVipPortDenyFailure) WithPayload(payload models.Error) *PutVsVipPortDenyFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port deny failure response +func (o *PutVsVipPortDenyFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortDenyFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_urlbuilder.go new file mode 100644 index 000000000..48450185b --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_deny_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutVsVipPortDenyURL generates an URL for the put vs vip port deny operation +type PutVsVipPortDenyURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortDenyURL) WithBasePath(bp string) *PutVsVipPortDenyURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortDenyURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortDenyURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/deny" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortDenyURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortDenyURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortDenyURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortDenyURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortDenyURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortDenyURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortDenyURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr.go new file mode 100644 index 000000000..a75db0dc4 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortLaddrHandlerFunc turns a function with the right signature into a put vs vip port laddr handler +type PutVsVipPortLaddrHandlerFunc func(PutVsVipPortLaddrParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortLaddrHandlerFunc) Handle(params PutVsVipPortLaddrParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortLaddrHandler interface for that can handle valid put vs vip port laddr params +type PutVsVipPortLaddrHandler interface { + Handle(PutVsVipPortLaddrParams) middleware.Responder +} + +// NewPutVsVipPortLaddr creates a new http.Handler for the put vs vip port laddr operation +func NewPutVsVipPortLaddr(ctx *middleware.Context, handler PutVsVipPortLaddrHandler) *PutVsVipPortLaddr { + return &PutVsVipPortLaddr{Context: ctx, Handler: handler} +} + +/* + PutVsVipPortLaddr swagger:route PUT /vs/{VipPort}/laddr virtualserver putVsVipPortLaddr + +PutVsVipPortLaddr put vs vip port laddr API +*/ +type PutVsVipPortLaddr struct { + Context *middleware.Context + Handler PutVsVipPortLaddrHandler +} + +func (o *PutVsVipPortLaddr) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortLaddrParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_parameters.go new file mode 100644 index 000000000..94c97a03a --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortLaddrParams creates a new PutVsVipPortLaddrParams object +// +// There are no default values defined in the spec. +func NewPutVsVipPortLaddrParams() PutVsVipPortLaddrParams { + + return PutVsVipPortLaddrParams{} +} + +// PutVsVipPortLaddrParams contains all the bound params for the put vs vip port laddr operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPortLaddr +type PutVsVipPortLaddrParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Spec *models.LocalAddressSpecTiny +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortLaddrParams() beforehand. +func (o *PutVsVipPortLaddrParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.LocalAddressSpecTiny + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortLaddrParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_responses.go new file mode 100644 index 000000000..9d4f6bc00 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortLaddrOKCode is the HTTP code returned for type PutVsVipPortLaddrOK +const PutVsVipPortLaddrOKCode int = 200 + +/* +PutVsVipPortLaddrOK Success + +swagger:response putVsVipPortLaddrOK +*/ +type PutVsVipPortLaddrOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrOK creates PutVsVipPortLaddrOK with default headers values +func NewPutVsVipPortLaddrOK() *PutVsVipPortLaddrOK { + + return &PutVsVipPortLaddrOK{} +} + +// WithPayload adds the payload to the put vs vip port laddr o k response +func (o *PutVsVipPortLaddrOK) WithPayload(payload string) *PutVsVipPortLaddrOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr o k response +func (o *PutVsVipPortLaddrOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortLaddrCreatedCode is the HTTP code returned for type PutVsVipPortLaddrCreated +const PutVsVipPortLaddrCreatedCode int = 201 + +/* +PutVsVipPortLaddrCreated Created + +swagger:response putVsVipPortLaddrCreated +*/ +type PutVsVipPortLaddrCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrCreated creates PutVsVipPortLaddrCreated with default headers values +func NewPutVsVipPortLaddrCreated() *PutVsVipPortLaddrCreated { + + return &PutVsVipPortLaddrCreated{} +} + +// WithPayload adds the payload to the put vs vip port laddr created response +func (o *PutVsVipPortLaddrCreated) WithPayload(payload string) *PutVsVipPortLaddrCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr created response +func (o *PutVsVipPortLaddrCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortLaddrInvalidFrontendCode is the HTTP code returned for type PutVsVipPortLaddrInvalidFrontend +const PutVsVipPortLaddrInvalidFrontendCode int = 460 + +/* +PutVsVipPortLaddrInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortLaddrInvalidFrontend +*/ +type PutVsVipPortLaddrInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrInvalidFrontend creates PutVsVipPortLaddrInvalidFrontend with default headers values +func NewPutVsVipPortLaddrInvalidFrontend() *PutVsVipPortLaddrInvalidFrontend { + + return &PutVsVipPortLaddrInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port laddr invalid frontend response +func (o *PutVsVipPortLaddrInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortLaddrInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr invalid frontend response +func (o *PutVsVipPortLaddrInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortLaddrInvalidBackendCode is the HTTP code returned for type PutVsVipPortLaddrInvalidBackend +const PutVsVipPortLaddrInvalidBackendCode int = 461 + +/* +PutVsVipPortLaddrInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortLaddrInvalidBackend +*/ +type PutVsVipPortLaddrInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrInvalidBackend creates PutVsVipPortLaddrInvalidBackend with default headers values +func NewPutVsVipPortLaddrInvalidBackend() *PutVsVipPortLaddrInvalidBackend { + + return &PutVsVipPortLaddrInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port laddr invalid backend response +func (o *PutVsVipPortLaddrInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortLaddrInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr invalid backend response +func (o *PutVsVipPortLaddrInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortLaddrFailureCode is the HTTP code returned for type PutVsVipPortLaddrFailure +const PutVsVipPortLaddrFailureCode int = 500 + +/* +PutVsVipPortLaddrFailure Error while creating virtual server + +swagger:response putVsVipPortLaddrFailure +*/ +type PutVsVipPortLaddrFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortLaddrFailure creates PutVsVipPortLaddrFailure with default headers values +func NewPutVsVipPortLaddrFailure() *PutVsVipPortLaddrFailure { + + return &PutVsVipPortLaddrFailure{} +} + +// WithPayload adds the payload to the put vs vip port laddr failure response +func (o *PutVsVipPortLaddrFailure) WithPayload(payload models.Error) *PutVsVipPortLaddrFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port laddr failure response +func (o *PutVsVipPortLaddrFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortLaddrFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_urlbuilder.go new file mode 100644 index 000000000..c0dc2d7d5 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_laddr_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutVsVipPortLaddrURL generates an URL for the put vs vip port laddr operation +type PutVsVipPortLaddrURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortLaddrURL) WithBasePath(bp string) *PutVsVipPortLaddrURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortLaddrURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortLaddrURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/laddr" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortLaddrURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortLaddrURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortLaddrURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortLaddrURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortLaddrURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortLaddrURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortLaddrURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go new file mode 100644 index 000000000..8dc0c2030 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_parameters.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortParams creates a new PutVsVipPortParams object +// +// There are no default values defined in the spec. +func NewPutVsVipPortParams() PutVsVipPortParams { + + return PutVsVipPortParams{} +} + +// PutVsVipPortParams contains all the bound params for the put vs vip port operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPort +type PutVsVipPortParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: body + */ + Spec *models.VirtualServerSpecTiny +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortParams() beforehand. +func (o *PutVsVipPortParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.VirtualServerSpecTiny + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("spec", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Spec = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_responses.go new file mode 100644 index 000000000..19946ac56 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortOKCode is the HTTP code returned for type PutVsVipPortOK +const PutVsVipPortOKCode int = 200 + +/* +PutVsVipPortOK Updated + +swagger:response putVsVipPortOK +*/ +type PutVsVipPortOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortOK creates PutVsVipPortOK with default headers values +func NewPutVsVipPortOK() *PutVsVipPortOK { + + return &PutVsVipPortOK{} +} + +// WithPayload adds the payload to the put vs vip port o k response +func (o *PutVsVipPortOK) WithPayload(payload string) *PutVsVipPortOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port o k response +func (o *PutVsVipPortOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortCreatedCode is the HTTP code returned for type PutVsVipPortCreated +const PutVsVipPortCreatedCode int = 201 + +/* +PutVsVipPortCreated Created + +swagger:response putVsVipPortCreated +*/ +type PutVsVipPortCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortCreated creates PutVsVipPortCreated with default headers values +func NewPutVsVipPortCreated() *PutVsVipPortCreated { + + return &PutVsVipPortCreated{} +} + +// WithPayload adds the payload to the put vs vip port created response +func (o *PutVsVipPortCreated) WithPayload(payload string) *PutVsVipPortCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port created response +func (o *PutVsVipPortCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortInvalidFrontendCode is the HTTP code returned for type PutVsVipPortInvalidFrontend +const PutVsVipPortInvalidFrontendCode int = 460 + +/* +PutVsVipPortInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortInvalidFrontend +*/ +type PutVsVipPortInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortInvalidFrontend creates PutVsVipPortInvalidFrontend with default headers values +func NewPutVsVipPortInvalidFrontend() *PutVsVipPortInvalidFrontend { + + return &PutVsVipPortInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port invalid frontend response +func (o *PutVsVipPortInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port invalid frontend response +func (o *PutVsVipPortInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortInvalidBackendCode is the HTTP code returned for type PutVsVipPortInvalidBackend +const PutVsVipPortInvalidBackendCode int = 461 + +/* +PutVsVipPortInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortInvalidBackend +*/ +type PutVsVipPortInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortInvalidBackend creates PutVsVipPortInvalidBackend with default headers values +func NewPutVsVipPortInvalidBackend() *PutVsVipPortInvalidBackend { + + return &PutVsVipPortInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port invalid backend response +func (o *PutVsVipPortInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port invalid backend response +func (o *PutVsVipPortInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortFailureCode is the HTTP code returned for type PutVsVipPortFailure +const PutVsVipPortFailureCode int = 500 + +/* +PutVsVipPortFailure Error while creating virtual server + +swagger:response putVsVipPortFailure +*/ +type PutVsVipPortFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortFailure creates PutVsVipPortFailure with default headers values +func NewPutVsVipPortFailure() *PutVsVipPortFailure { + + return &PutVsVipPortFailure{} +} + +// WithPayload adds the payload to the put vs vip port failure response +func (o *PutVsVipPortFailure) WithPayload(payload models.Error) *PutVsVipPortFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port failure response +func (o *PutVsVipPortFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs.go new file mode 100644 index 000000000..475833200 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs.go @@ -0,0 +1,56 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// PutVsVipPortRsHandlerFunc turns a function with the right signature into a put vs vip port rs handler +type PutVsVipPortRsHandlerFunc func(PutVsVipPortRsParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn PutVsVipPortRsHandlerFunc) Handle(params PutVsVipPortRsParams) middleware.Responder { + return fn(params) +} + +// PutVsVipPortRsHandler interface for that can handle valid put vs vip port rs params +type PutVsVipPortRsHandler interface { + Handle(PutVsVipPortRsParams) middleware.Responder +} + +// NewPutVsVipPortRs creates a new http.Handler for the put vs vip port rs operation +func NewPutVsVipPortRs(ctx *middleware.Context, handler PutVsVipPortRsHandler) *PutVsVipPortRs { + return &PutVsVipPortRs{Context: ctx, Handler: handler} +} + +/* + PutVsVipPortRs swagger:route PUT /vs/{VipPort}/rs virtualserver putVsVipPortRs + +Add a set of real server to vip:port:proto +*/ +type PutVsVipPortRs struct { + Context *middleware.Context + Handler PutVsVipPortRsHandler +} + +func (o *PutVsVipPortRs) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewPutVsVipPortRsParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_parameters.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_parameters.go new file mode 100644 index 000000000..0e36def24 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_parameters.go @@ -0,0 +1,145 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" + + "github.com/dpvs-agent/models" +) + +// NewPutVsVipPortRsParams creates a new PutVsVipPortRsParams object +// with the default values initialized. +func NewPutVsVipPortRsParams() PutVsVipPortRsParams { + + var ( + // initialize parameters with default values + + healthcheckDefault = bool(false) + ) + + return PutVsVipPortRsParams{ + Healthcheck: &healthcheckDefault, + } +} + +// PutVsVipPortRsParams contains all the bound params for the put vs vip port rs operation +// typically these are obtained from a http.Request +// +// swagger:parameters PutVsVipPortRs +type PutVsVipPortRsParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + VipPort string + /* + In: query + Default: false + */ + Healthcheck *bool + /* + In: body + */ + Rss *models.RealServerTinyList +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewPutVsVipPortRsParams() beforehand. +func (o *PutVsVipPortRsParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + rVipPort, rhkVipPort, _ := route.Params.GetOK("VipPort") + if err := o.bindVipPort(rVipPort, rhkVipPort, route.Formats); err != nil { + res = append(res, err) + } + + qHealthcheck, qhkHealthcheck, _ := qs.GetOK("healthcheck") + if err := o.bindHealthcheck(qHealthcheck, qhkHealthcheck, route.Formats); err != nil { + res = append(res, err) + } + + if runtime.HasBody(r) { + defer r.Body.Close() + var body models.RealServerTinyList + if err := route.Consumer.Consume(r.Body, &body); err != nil { + res = append(res, errors.NewParseError("rss", "body", "", err)) + } else { + // validate body object + if err := body.Validate(route.Formats); err != nil { + res = append(res, err) + } + + ctx := validate.WithOperationRequest(r.Context()) + if err := body.ContextValidate(ctx, route.Formats); err != nil { + res = append(res, err) + } + + if len(res) == 0 { + o.Rss = &body + } + } + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindVipPort binds and validates parameter VipPort from path. +func (o *PutVsVipPortRsParams) bindVipPort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + o.VipPort = raw + + return nil +} + +// bindHealthcheck binds and validates parameter Healthcheck from query. +func (o *PutVsVipPortRsParams) bindHealthcheck(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + // Default values have been previously initialized by NewPutVsVipPortRsParams() + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("healthcheck", "query", "bool", raw) + } + o.Healthcheck = &value + + return nil +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_responses.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_responses.go new file mode 100644 index 000000000..8dd6b9737 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_responses.go @@ -0,0 +1,229 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/dpvs-agent/models" +) + +// PutVsVipPortRsOKCode is the HTTP code returned for type PutVsVipPortRsOK +const PutVsVipPortRsOKCode int = 200 + +/* +PutVsVipPortRsOK Success + +swagger:response putVsVipPortRsOK +*/ +type PutVsVipPortRsOK struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortRsOK creates PutVsVipPortRsOK with default headers values +func NewPutVsVipPortRsOK() *PutVsVipPortRsOK { + + return &PutVsVipPortRsOK{} +} + +// WithPayload adds the payload to the put vs vip port rs o k response +func (o *PutVsVipPortRsOK) WithPayload(payload string) *PutVsVipPortRsOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs o k response +func (o *PutVsVipPortRsOK) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortRsCreatedCode is the HTTP code returned for type PutVsVipPortRsCreated +const PutVsVipPortRsCreatedCode int = 201 + +/* +PutVsVipPortRsCreated Created + +swagger:response putVsVipPortRsCreated +*/ +type PutVsVipPortRsCreated struct { + + /* + In: Body + */ + Payload string `json:"body,omitempty"` +} + +// NewPutVsVipPortRsCreated creates PutVsVipPortRsCreated with default headers values +func NewPutVsVipPortRsCreated() *PutVsVipPortRsCreated { + + return &PutVsVipPortRsCreated{} +} + +// WithPayload adds the payload to the put vs vip port rs created response +func (o *PutVsVipPortRsCreated) WithPayload(payload string) *PutVsVipPortRsCreated { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs created response +func (o *PutVsVipPortRsCreated) SetPayload(payload string) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsCreated) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(201) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortRsInvalidFrontendCode is the HTTP code returned for type PutVsVipPortRsInvalidFrontend +const PutVsVipPortRsInvalidFrontendCode int = 460 + +/* +PutVsVipPortRsInvalidFrontend Invalid frontend in service configuration + +swagger:response putVsVipPortRsInvalidFrontend +*/ +type PutVsVipPortRsInvalidFrontend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortRsInvalidFrontend creates PutVsVipPortRsInvalidFrontend with default headers values +func NewPutVsVipPortRsInvalidFrontend() *PutVsVipPortRsInvalidFrontend { + + return &PutVsVipPortRsInvalidFrontend{} +} + +// WithPayload adds the payload to the put vs vip port rs invalid frontend response +func (o *PutVsVipPortRsInvalidFrontend) WithPayload(payload models.Error) *PutVsVipPortRsInvalidFrontend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs invalid frontend response +func (o *PutVsVipPortRsInvalidFrontend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsInvalidFrontend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(460) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortRsInvalidBackendCode is the HTTP code returned for type PutVsVipPortRsInvalidBackend +const PutVsVipPortRsInvalidBackendCode int = 461 + +/* +PutVsVipPortRsInvalidBackend Invalid backend in service configuration + +swagger:response putVsVipPortRsInvalidBackend +*/ +type PutVsVipPortRsInvalidBackend struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortRsInvalidBackend creates PutVsVipPortRsInvalidBackend with default headers values +func NewPutVsVipPortRsInvalidBackend() *PutVsVipPortRsInvalidBackend { + + return &PutVsVipPortRsInvalidBackend{} +} + +// WithPayload adds the payload to the put vs vip port rs invalid backend response +func (o *PutVsVipPortRsInvalidBackend) WithPayload(payload models.Error) *PutVsVipPortRsInvalidBackend { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs invalid backend response +func (o *PutVsVipPortRsInvalidBackend) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsInvalidBackend) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(461) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// PutVsVipPortRsFailureCode is the HTTP code returned for type PutVsVipPortRsFailure +const PutVsVipPortRsFailureCode int = 500 + +/* +PutVsVipPortRsFailure Service deletion failed + +swagger:response putVsVipPortRsFailure +*/ +type PutVsVipPortRsFailure struct { + + /* + In: Body + */ + Payload models.Error `json:"body,omitempty"` +} + +// NewPutVsVipPortRsFailure creates PutVsVipPortRsFailure with default headers values +func NewPutVsVipPortRsFailure() *PutVsVipPortRsFailure { + + return &PutVsVipPortRsFailure{} +} + +// WithPayload adds the payload to the put vs vip port rs failure response +func (o *PutVsVipPortRsFailure) WithPayload(payload models.Error) *PutVsVipPortRsFailure { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the put vs vip port rs failure response +func (o *PutVsVipPortRsFailure) SetPayload(payload models.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *PutVsVipPortRsFailure) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(500) + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_urlbuilder.go new file mode 100644 index 000000000..d906fae36 --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_rs_urlbuilder.go @@ -0,0 +1,115 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/swag" +) + +// PutVsVipPortRsURL generates an URL for the put vs vip port rs operation +type PutVsVipPortRsURL struct { + VipPort string + + Healthcheck *bool + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortRsURL) WithBasePath(bp string) *PutVsVipPortRsURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortRsURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortRsURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}/rs" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortRsURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var healthcheckQ string + if o.Healthcheck != nil { + healthcheckQ = swag.FormatBool(*o.Healthcheck) + } + if healthcheckQ != "" { + qs.Set("healthcheck", healthcheckQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortRsURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortRsURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortRsURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortRsURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortRsURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortRsURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go new file mode 100644 index 000000000..01adfb16c --- /dev/null +++ b/tools/dpvs-agent/restapi/operations/virtualserver/put_vs_vip_port_urlbuilder.go @@ -0,0 +1,99 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package virtualserver + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" +) + +// PutVsVipPortURL generates an URL for the put vs vip port operation +type PutVsVipPortURL struct { + VipPort string + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortURL) WithBasePath(bp string) *PutVsVipPortURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *PutVsVipPortURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *PutVsVipPortURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/vs/{VipPort}" + + vipPort := o.VipPort + if vipPort != "" { + _path = strings.Replace(_path, "{VipPort}", vipPort, -1) + } else { + return nil, errors.New("vipPort is required on PutVsVipPortURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/v2" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *PutVsVipPortURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *PutVsVipPortURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *PutVsVipPortURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on PutVsVipPortURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on PutVsVipPortURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *PutVsVipPortURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/tools/dpvs-agent/restapi/server.go b/tools/dpvs-agent/restapi/server.go new file mode 100644 index 000000000..2c8225403 --- /dev/null +++ b/tools/dpvs-agent/restapi/server.go @@ -0,0 +1,507 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package restapi + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "log" + "net" + "net/http" + "os" + "os/signal" + "strconv" + "sync" + "sync/atomic" + "syscall" + "time" + + "github.com/go-openapi/runtime/flagext" + "github.com/go-openapi/swag" + flags "github.com/jessevdk/go-flags" + "golang.org/x/net/netutil" + + "github.com/dpvs-agent/restapi/operations" +) + +const ( + schemeHTTP = "http" + schemeHTTPS = "https" + schemeUnix = "unix" +) + +var defaultSchemes []string + +func init() { + defaultSchemes = []string{ + schemeHTTP, + } +} + +// NewServer creates a new api dpvs agent server but does not configure it +func NewServer(api *operations.DpvsAgentAPI) *Server { + s := new(Server) + + s.shutdown = make(chan struct{}) + s.api = api + s.interrupt = make(chan os.Signal, 1) + return s +} + +// ConfigureAPI configures the API and handlers. +func (s *Server) ConfigureAPI() { + if s.api != nil { + s.handler = configureAPI(s.api) + } +} + +// ConfigureFlags configures the additional flags defined by the handlers. Needs to be called before the parser.Parse +func (s *Server) ConfigureFlags() { + if s.api != nil { + configureFlags(s.api) + } +} + +// Server for the dpvs agent API +type Server struct { + EnabledListeners []string `long:"scheme" description:"the listeners to enable, this can be repeated and defaults to the schemes in the swagger spec"` + CleanupTimeout time.Duration `long:"cleanup-timeout" description:"grace period for which to wait before killing idle connections" default:"10s"` + GracefulTimeout time.Duration `long:"graceful-timeout" description:"grace period for which to wait before shutting down the server" default:"15s"` + MaxHeaderSize flagext.ByteSize `long:"max-header-size" description:"controls the maximum number of bytes the server will read parsing the request header's keys and values, including the request line. It does not limit the size of the request body." default:"1MiB"` + + SocketPath flags.Filename `long:"socket-path" description:"the unix socket to listen on" default:"/var/run/dpvs-agent.sock"` + domainSocketL net.Listener + + Host string `long:"host" description:"the IP to listen on" default:"localhost" env:"HOST"` + Port int `long:"port" description:"the port to listen on for insecure connections, defaults to a random value" env:"PORT"` + ListenLimit int `long:"listen-limit" description:"limit the number of outstanding requests"` + KeepAlive time.Duration `long:"keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)" default:"3m"` + ReadTimeout time.Duration `long:"read-timeout" description:"maximum duration before timing out read of the request" default:"30s"` + WriteTimeout time.Duration `long:"write-timeout" description:"maximum duration before timing out write of the response" default:"60s"` + httpServerL net.Listener + + TLSHost string `long:"tls-host" description:"the IP to listen on for tls, when not specified it's the same as --host" env:"TLS_HOST"` + TLSPort int `long:"tls-port" description:"the port to listen on for secure connections, defaults to a random value" env:"TLS_PORT"` + TLSCertificate flags.Filename `long:"tls-certificate" description:"the certificate to use for secure connections" env:"TLS_CERTIFICATE"` + TLSCertificateKey flags.Filename `long:"tls-key" description:"the private key to use for secure connections" env:"TLS_PRIVATE_KEY"` + TLSCACertificate flags.Filename `long:"tls-ca" description:"the certificate authority file to be used with mutual tls auth" env:"TLS_CA_CERTIFICATE"` + TLSListenLimit int `long:"tls-listen-limit" description:"limit the number of outstanding requests"` + TLSKeepAlive time.Duration `long:"tls-keep-alive" description:"sets the TCP keep-alive timeouts on accepted connections. It prunes dead TCP connections ( e.g. closing laptop mid-download)"` + TLSReadTimeout time.Duration `long:"tls-read-timeout" description:"maximum duration before timing out read of the request"` + TLSWriteTimeout time.Duration `long:"tls-write-timeout" description:"maximum duration before timing out write of the response"` + httpsServerL net.Listener + + api *operations.DpvsAgentAPI + handler http.Handler + hasListeners bool + shutdown chan struct{} + shuttingDown int32 + interrupted bool + interrupt chan os.Signal +} + +// Logf logs message either via defined user logger or via system one if no user logger is defined. +func (s *Server) Logf(f string, args ...interface{}) { + if s.api != nil && s.api.Logger != nil { + s.api.Logger(f, args...) + } else { + log.Printf(f, args...) + } +} + +// Fatalf logs message either via defined user logger or via system one if no user logger is defined. +// Exits with non-zero status after printing +func (s *Server) Fatalf(f string, args ...interface{}) { + if s.api != nil && s.api.Logger != nil { + s.api.Logger(f, args...) + os.Exit(1) + } else { + log.Fatalf(f, args...) + } +} + +// SetAPI configures the server with the specified API. Needs to be called before Serve +func (s *Server) SetAPI(api *operations.DpvsAgentAPI) { + if api == nil { + s.api = nil + s.handler = nil + return + } + + s.api = api + s.handler = configureAPI(api) +} + +func (s *Server) hasScheme(scheme string) bool { + schemes := s.EnabledListeners + if len(schemes) == 0 { + schemes = defaultSchemes + } + + for _, v := range schemes { + if v == scheme { + return true + } + } + return false +} + +// Serve the api +func (s *Server) Serve() (err error) { + if !s.hasListeners { + if err = s.Listen(); err != nil { + return err + } + } + + // set default handler, if none is set + if s.handler == nil { + if s.api == nil { + return errors.New("can't create the default handler, as no api is set") + } + + s.SetHandler(s.api.Serve(nil)) + } + + wg := new(sync.WaitGroup) + once := new(sync.Once) + signalNotify(s.interrupt) + go handleInterrupt(once, s) + + servers := []*http.Server{} + + if s.hasScheme(schemeUnix) { + domainSocket := new(http.Server) + domainSocket.MaxHeaderBytes = int(s.MaxHeaderSize) + domainSocket.Handler = s.handler + if int64(s.CleanupTimeout) > 0 { + domainSocket.IdleTimeout = s.CleanupTimeout + } + + configureServer(domainSocket, "unix", string(s.SocketPath)) + + servers = append(servers, domainSocket) + wg.Add(1) + s.Logf("Serving dpvs agent at unix://%s", s.SocketPath) + go func(l net.Listener) { + defer wg.Done() + if err := domainSocket.Serve(l); err != nil && err != http.ErrServerClosed { + s.Fatalf("%v", err) + } + s.Logf("Stopped serving dpvs agent at unix://%s", s.SocketPath) + }(s.domainSocketL) + } + + if s.hasScheme(schemeHTTP) { + httpServer := new(http.Server) + httpServer.MaxHeaderBytes = int(s.MaxHeaderSize) + httpServer.ReadTimeout = s.ReadTimeout + httpServer.WriteTimeout = s.WriteTimeout + httpServer.SetKeepAlivesEnabled(int64(s.KeepAlive) > 0) + if s.ListenLimit > 0 { + s.httpServerL = netutil.LimitListener(s.httpServerL, s.ListenLimit) + } + + if int64(s.CleanupTimeout) > 0 { + httpServer.IdleTimeout = s.CleanupTimeout + } + + httpServer.Handler = s.handler + + configureServer(httpServer, "http", s.httpServerL.Addr().String()) + + servers = append(servers, httpServer) + wg.Add(1) + s.Logf("Serving dpvs agent at http://%s", s.httpServerL.Addr()) + go func(l net.Listener) { + defer wg.Done() + if err := httpServer.Serve(l); err != nil && err != http.ErrServerClosed { + s.Fatalf("%v", err) + } + s.Logf("Stopped serving dpvs agent at http://%s", l.Addr()) + }(s.httpServerL) + } + + if s.hasScheme(schemeHTTPS) { + httpsServer := new(http.Server) + httpsServer.MaxHeaderBytes = int(s.MaxHeaderSize) + httpsServer.ReadTimeout = s.TLSReadTimeout + httpsServer.WriteTimeout = s.TLSWriteTimeout + httpsServer.SetKeepAlivesEnabled(int64(s.TLSKeepAlive) > 0) + if s.TLSListenLimit > 0 { + s.httpsServerL = netutil.LimitListener(s.httpsServerL, s.TLSListenLimit) + } + if int64(s.CleanupTimeout) > 0 { + httpsServer.IdleTimeout = s.CleanupTimeout + } + httpsServer.Handler = s.handler + + // Inspired by https://blog.bracebin.com/achieving-perfect-ssl-labs-score-with-go + httpsServer.TLSConfig = &tls.Config{ + // Causes servers to use Go's default ciphersuite preferences, + // which are tuned to avoid attacks. Does nothing on clients. + PreferServerCipherSuites: true, + // Only use curves which have assembly implementations + // https://github.com/golang/go/tree/master/src/crypto/elliptic + CurvePreferences: []tls.CurveID{tls.CurveP256}, + // Use modern tls mode https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility + NextProtos: []string{"h2", "http/1.1"}, + // https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Rule_-_Only_Support_Strong_Protocols + MinVersion: tls.VersionTLS12, + // These ciphersuites support Forward Secrecy: https://en.wikipedia.org/wiki/Forward_secrecy + CipherSuites: []uint16{ + tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, + tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, + }, + } + + // build standard config from server options + if s.TLSCertificate != "" && s.TLSCertificateKey != "" { + httpsServer.TLSConfig.Certificates = make([]tls.Certificate, 1) + httpsServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(string(s.TLSCertificate), string(s.TLSCertificateKey)) + if err != nil { + return err + } + } + + if s.TLSCACertificate != "" { + // include specified CA certificate + caCert, caCertErr := os.ReadFile(string(s.TLSCACertificate)) + if caCertErr != nil { + return caCertErr + } + caCertPool := x509.NewCertPool() + ok := caCertPool.AppendCertsFromPEM(caCert) + if !ok { + return fmt.Errorf("cannot parse CA certificate") + } + httpsServer.TLSConfig.ClientCAs = caCertPool + httpsServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert + } + + // call custom TLS configurator + configureTLS(httpsServer.TLSConfig) + + if len(httpsServer.TLSConfig.Certificates) == 0 && httpsServer.TLSConfig.GetCertificate == nil { + // after standard and custom config are passed, this ends up with no certificate + if s.TLSCertificate == "" { + if s.TLSCertificateKey == "" { + s.Fatalf("the required flags `--tls-certificate` and `--tls-key` were not specified") + } + s.Fatalf("the required flag `--tls-certificate` was not specified") + } + if s.TLSCertificateKey == "" { + s.Fatalf("the required flag `--tls-key` was not specified") + } + // this happens with a wrong custom TLS configurator + s.Fatalf("no certificate was configured for TLS") + } + + configureServer(httpsServer, "https", s.httpsServerL.Addr().String()) + + servers = append(servers, httpsServer) + wg.Add(1) + s.Logf("Serving dpvs agent at https://%s", s.httpsServerL.Addr()) + go func(l net.Listener) { + defer wg.Done() + if err := httpsServer.Serve(l); err != nil && err != http.ErrServerClosed { + s.Fatalf("%v", err) + } + s.Logf("Stopped serving dpvs agent at https://%s", l.Addr()) + }(tls.NewListener(s.httpsServerL, httpsServer.TLSConfig)) + } + + wg.Add(1) + go s.handleShutdown(wg, &servers) + + wg.Wait() + return nil +} + +// Listen creates the listeners for the server +func (s *Server) Listen() error { + if s.hasListeners { // already done this + return nil + } + + if s.hasScheme(schemeHTTPS) { + // Use http host if https host wasn't defined + if s.TLSHost == "" { + s.TLSHost = s.Host + } + // Use http listen limit if https listen limit wasn't defined + if s.TLSListenLimit == 0 { + s.TLSListenLimit = s.ListenLimit + } + // Use http tcp keep alive if https tcp keep alive wasn't defined + if int64(s.TLSKeepAlive) == 0 { + s.TLSKeepAlive = s.KeepAlive + } + // Use http read timeout if https read timeout wasn't defined + if int64(s.TLSReadTimeout) == 0 { + s.TLSReadTimeout = s.ReadTimeout + } + // Use http write timeout if https write timeout wasn't defined + if int64(s.TLSWriteTimeout) == 0 { + s.TLSWriteTimeout = s.WriteTimeout + } + } + + if s.hasScheme(schemeUnix) { + domSockListener, err := net.Listen("unix", string(s.SocketPath)) + if err != nil { + return err + } + s.domainSocketL = domSockListener + } + + if s.hasScheme(schemeHTTP) { + listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port))) + if err != nil { + return err + } + + h, p, err := swag.SplitHostPort(listener.Addr().String()) + if err != nil { + return err + } + s.Host = h + s.Port = p + s.httpServerL = listener + } + + if s.hasScheme(schemeHTTPS) { + tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.TLSHost, strconv.Itoa(s.TLSPort))) + if err != nil { + return err + } + + sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String()) + if err != nil { + return err + } + s.TLSHost = sh + s.TLSPort = sp + s.httpsServerL = tlsListener + } + + s.hasListeners = true + return nil +} + +// Shutdown server and clean up resources +func (s *Server) Shutdown() error { + if atomic.CompareAndSwapInt32(&s.shuttingDown, 0, 1) { + close(s.shutdown) + } + return nil +} + +func (s *Server) handleShutdown(wg *sync.WaitGroup, serversPtr *[]*http.Server) { + // wg.Done must occur last, after s.api.ServerShutdown() + // (to preserve old behaviour) + defer wg.Done() + + <-s.shutdown + + servers := *serversPtr + + ctx, cancel := context.WithTimeout(context.TODO(), s.GracefulTimeout) + defer cancel() + + // first execute the pre-shutdown hook + s.api.PreServerShutdown() + + shutdownChan := make(chan bool) + for i := range servers { + server := servers[i] + go func() { + var success bool + defer func() { + shutdownChan <- success + }() + if err := server.Shutdown(ctx); err != nil { + // Error from closing listeners, or context timeout: + s.Logf("HTTP server Shutdown: %v", err) + } else { + success = true + } + }() + } + + // Wait until all listeners have successfully shut down before calling ServerShutdown + success := true + for range servers { + success = success && <-shutdownChan + } + if success { + s.api.ServerShutdown() + } +} + +// GetHandler returns a handler useful for testing +func (s *Server) GetHandler() http.Handler { + return s.handler +} + +// SetHandler allows for setting a http handler on this server +func (s *Server) SetHandler(handler http.Handler) { + s.handler = handler +} + +// UnixListener returns the domain socket listener +func (s *Server) UnixListener() (net.Listener, error) { + if !s.hasListeners { + if err := s.Listen(); err != nil { + return nil, err + } + } + return s.domainSocketL, nil +} + +// HTTPListener returns the http listener +func (s *Server) HTTPListener() (net.Listener, error) { + if !s.hasListeners { + if err := s.Listen(); err != nil { + return nil, err + } + } + return s.httpServerL, nil +} + +// TLSListener returns the https listener +func (s *Server) TLSListener() (net.Listener, error) { + if !s.hasListeners { + if err := s.Listen(); err != nil { + return nil, err + } + } + return s.httpsServerL, nil +} + +func handleInterrupt(once *sync.Once, s *Server) { + once.Do(func() { + for range s.interrupt { + if s.interrupted { + s.Logf("Server already shutting down") + continue + } + s.interrupted = true + s.Logf("Shutting down... ") + if err := s.Shutdown(); err != nil { + s.Logf("HTTP server Shutdown: %v", err) + } + } + }) +} + +func signalNotify(interrupt chan<- os.Signal) { + signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) +} From 861916a33643c52a0cc44c7d3de8192ace114782 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Tue, 11 Jul 2023 11:39:14 +0800 Subject: [PATCH 050/105] building dpvs-agent --- tools/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/Makefile b/tools/Makefile index 832a568d1..72bffcc75 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -22,6 +22,7 @@ SUBDIRS = keepalived ipvsadm dpip ifeq ($(CONFIG_DPVS_AGENT), y) SUBDIRS += healthcheck +SUBDIRS += dpvs-agent endif all: config @@ -48,4 +49,5 @@ install: install -m 744 dpip/build/dpip $(INSDIR)/dpip ifeq ($(CONFIG_DPVS_AGENT), y) install -m 744 healthcheck/healthcheck $(INSDIR)/healthcheck + install -m 744 dpvs-agent/cmd/dpvs-agent-server/dpvs-agent $(INSDIR)/dpvs-agent endif From 49d0f2aa9b2398ffb05630d9232bf5cfd39864e6 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Tue, 11 Jul 2023 13:36:03 +0800 Subject: [PATCH 051/105] add license --- tools/dpvs-agent/Makefile | 1 + .../cmd/device/delete_device_name_addr.go | 14 + .../cmd/device/delete_device_name_netlink.go | 14 + .../device/delete_device_name_netlink_addr.go | 14 + .../cmd/device/delete_device_name_route.go | 14 + .../cmd/device/delete_device_name_vlan.go | 14 + .../cmd/device/get_device_name_nic.go | 14 + tools/dpvs-agent/cmd/device/ioctl.go | 14 + .../cmd/device/put_device_name_addr.go | 14 + .../cmd/device/put_device_name_netlink.go | 14 + .../device/put_device_name_netlink_addr.go | 14 + .../cmd/device/put_device_name_nic.go | 14 + .../cmd/device/put_device_name_route.go | 14 + .../cmd/device/put_device_name_vlan.go | 14 + .../device/todo_delete_device_name_linux.go | 14 + .../todo_delete_device_name_linux_addr.go | 14 + .../dpvs-agent/cmd/device/todo_get_device.go | 14 + .../cmd/device/todo_get_device_name_addr.go | 14 + .../cmd/device/todo_get_device_name_linux.go | 14 + .../device/todo_get_device_name_linux_addr.go | 14 + .../cmd/device/todo_get_device_name_route.go | 14 + .../cmd/device/todo_get_device_name_vlan.go | 14 + .../cmd/device/todo_put_device_name_linux.go | 14 + .../device/todo_put_device_name_linux_addr.go | 14 + .../cmd/dpvs-agent-server/api_init.go | 14 + .../dpvs-agent/cmd/ipvs/delete_vs_vip_port.go | 14 + .../cmd/ipvs/delete_vs_vip_port_allow.go | 14 + .../cmd/ipvs/delete_vs_vip_port_deny.go | 14 + .../cmd/ipvs/delete_vs_vip_port_laddr.go | 14 + .../cmd/ipvs/delete_vs_vip_port_rs.go | 14 + tools/dpvs-agent/cmd/ipvs/get_vs.go | 14 + tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go | 14 + .../cmd/ipvs/get_vs_vip_port_laddr.go | 14 + .../cmd/ipvs/post_vs_vip_port_rs.go | 14 + tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go | 14 + .../cmd/ipvs/put_vs_vip_port_allow.go | 14 + .../cmd/ipvs/put_vs_vip_port_deny.go | 14 + .../cmd/ipvs/put_vs_vip_port_laddr.go | 14 + .../dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go | 14 + .../cmd/ipvs/todo_get_vs_vip_port_rs.go | 14 + tools/dpvs-agent/dpvs-agent-api.yaml | 14 + tools/dpvs-agent/license.txt | 13 + tools/dpvs-agent/pkg/ipc/pool/conn.go | 14 + tools/dpvs-agent/pkg/ipc/pool/pool.go | 14 + tools/dpvs-agent/pkg/ipc/pool/util.go | 14 + tools/dpvs-agent/pkg/ipc/proto/reader.go | 283 +----------------- tools/dpvs-agent/pkg/ipc/proto/writer.go | 14 + tools/dpvs-agent/pkg/ipc/types/certificate.go | 14 + tools/dpvs-agent/pkg/ipc/types/const.go | 14 + tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go | 14 + tools/dpvs-agent/pkg/ipc/types/dpvsstats.go | 14 + tools/dpvs-agent/pkg/ipc/types/getmodel.go | 14 + tools/dpvs-agent/pkg/ipc/types/inetaddr.go | 14 + tools/dpvs-agent/pkg/ipc/types/iprange.go | 14 + tools/dpvs-agent/pkg/ipc/types/kni.go | 14 + tools/dpvs-agent/pkg/ipc/types/laddr.go | 14 + tools/dpvs-agent/pkg/ipc/types/method.go | 14 + tools/dpvs-agent/pkg/ipc/types/netif.go | 14 + tools/dpvs-agent/pkg/ipc/types/realserver.go | 14 + tools/dpvs-agent/pkg/ipc/types/route.go | 14 + tools/dpvs-agent/pkg/ipc/types/sockmsg.go | 14 + tools/dpvs-agent/pkg/ipc/types/utility.go | 14 + .../dpvs-agent/pkg/ipc/types/virtualserver.go | 14 + tools/dpvs-agent/pkg/ipc/types/vlan.go | 14 + .../restapi/configure_dpvs_agent.go | 14 + 65 files changed, 896 insertions(+), 269 deletions(-) create mode 100644 tools/dpvs-agent/license.txt diff --git a/tools/dpvs-agent/Makefile b/tools/dpvs-agent/Makefile index fb8e5ff18..e6d192824 100644 --- a/tools/dpvs-agent/Makefile +++ b/tools/dpvs-agent/Makefile @@ -30,3 +30,4 @@ ifeq ($(shell addlicense 2>&1|grep Usage),) $(error "`addlicense` command not found. You can install it with `go install github.com/google/addlicense`") endif @addlicense -check -c "IQiYi Inc." -l apache -ignore dpvs/** . || /bin/true + -addlicense -f license.txt -v . diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_addr.go b/tools/dpvs-agent/cmd/device/delete_device_name_addr.go index 68635af05..716d47718 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_addr.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go b/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go index d4fd6ba54..0bc24ef08 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_netlink.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go b/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go index 0ed8b943e..35eb17ef7 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_netlink_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_route.go b/tools/dpvs-agent/cmd/device/delete_device_name_route.go index eabc0f976..74d5b5254 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_route.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_route.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go b/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go index abd2e5620..0144c0ea9 100644 --- a/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go +++ b/tools/dpvs-agent/cmd/device/delete_device_name_vlan.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/get_device_name_nic.go b/tools/dpvs-agent/cmd/device/get_device_name_nic.go index 2cedd92a2..6d35e45cd 100644 --- a/tools/dpvs-agent/cmd/device/get_device_name_nic.go +++ b/tools/dpvs-agent/cmd/device/get_device_name_nic.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/ioctl.go b/tools/dpvs-agent/cmd/device/ioctl.go index ab3297857..5511c47ba 100644 --- a/tools/dpvs-agent/cmd/device/ioctl.go +++ b/tools/dpvs-agent/cmd/device/ioctl.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_addr.go b/tools/dpvs-agent/cmd/device/put_device_name_addr.go index 03cd75c82..275e33100 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_addr.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_netlink.go b/tools/dpvs-agent/cmd/device/put_device_name_netlink.go index 1a643647c..be683f8db 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_netlink.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_netlink.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go b/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go index a114ba8fe..1b093b431 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_netlink_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_nic.go b/tools/dpvs-agent/cmd/device/put_device_name_nic.go index 419026058..695381a91 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_nic.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_nic.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_route.go b/tools/dpvs-agent/cmd/device/put_device_name_route.go index d9ddea942..14bbb92d3 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_route.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_route.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/put_device_name_vlan.go b/tools/dpvs-agent/cmd/device/put_device_name_vlan.go index 4ec011bd7..c3d8098e5 100644 --- a/tools/dpvs-agent/cmd/device/put_device_name_vlan.go +++ b/tools/dpvs-agent/cmd/device/put_device_name_vlan.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device import ( diff --git a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go index 9e8771521..6032a7945 100644 --- a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go +++ b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device /* diff --git a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go index ce1c644e4..bc1ff5230 100644 --- a/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go +++ b/tools/dpvs-agent/cmd/device/todo_delete_device_name_linux_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device /* diff --git a/tools/dpvs-agent/cmd/device/todo_get_device.go b/tools/dpvs-agent/cmd/device/todo_get_device.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_addr.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_linux_addr.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_route.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go b/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go index 76a9bfa32..3dfd22c28 100644 --- a/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go +++ b/tools/dpvs-agent/cmd/device/todo_get_device_name_vlan.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device diff --git a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go index a1f95a889..34972bb0c 100644 --- a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go +++ b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device // http://blog.pytool.com/language/clang/socket/linux-socket-ifreq/ diff --git a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go index b56f455b6..976e708c9 100644 --- a/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go +++ b/tools/dpvs-agent/cmd/device/todo_put_device_name_linux_addr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package device /* diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go index f4d5393e9..c9b885685 100644 --- a/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package main import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go index f9c4a645c..280827cee 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go index 0d8678f2b..f1e068e5d 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_allow.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go index 1352386d8..54d2bb9d2 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_deny.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go index 4780c7424..ec1cb9bd8 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_laddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go index 222635645..8870fdd7f 100644 --- a/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/delete_vs_vip_port_rs.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs.go b/tools/dpvs-agent/cmd/ipvs/get_vs.go index a6d8c1025..700931f75 100644 --- a/tools/dpvs-agent/cmd/ipvs/get_vs.go +++ b/tools/dpvs-agent/cmd/ipvs/get_vs.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go index 873e6d533..c9f907876 100644 --- a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go index adac60936..b8754eb84 100644 --- a/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go +++ b/tools/dpvs-agent/cmd/ipvs/get_vs_vip_port_laddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go index 4f577cca0..76520bc12 100644 --- a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go index c6c09f285..1b3fc1997 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go index dabcc000b..a5ff5753a 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_allow.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go index 984dff17a..632b563f6 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_deny.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go index 6551abea3..d8765ba6d 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go index 05380108c..a472be1e7 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs import ( diff --git a/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go index 91ce6808a..2a5d23eaf 100644 --- a/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/todo_get_vs_vip_port_rs.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package ipvs diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml index 230751c80..ac8487bef 100644 --- a/tools/dpvs-agent/dpvs-agent-api.yaml +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -1,3 +1,17 @@ +# Copyright 2023 IQiYi Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + swagger: "2.0" info: description: "dpvs agent api" diff --git a/tools/dpvs-agent/license.txt b/tools/dpvs-agent/license.txt new file mode 100644 index 000000000..d61a47c47 --- /dev/null +++ b/tools/dpvs-agent/license.txt @@ -0,0 +1,13 @@ +Copyright 2023 IQiYi Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/tools/dpvs-agent/pkg/ipc/pool/conn.go b/tools/dpvs-agent/pkg/ipc/pool/conn.go index 6f7034653..721eb113c 100644 --- a/tools/dpvs-agent/pkg/ipc/pool/conn.go +++ b/tools/dpvs-agent/pkg/ipc/pool/conn.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pool import ( diff --git a/tools/dpvs-agent/pkg/ipc/pool/pool.go b/tools/dpvs-agent/pkg/ipc/pool/pool.go index c88d9d82d..0f19b4bed 100644 --- a/tools/dpvs-agent/pkg/ipc/pool/pool.go +++ b/tools/dpvs-agent/pkg/ipc/pool/pool.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pool import ( diff --git a/tools/dpvs-agent/pkg/ipc/pool/util.go b/tools/dpvs-agent/pkg/ipc/pool/util.go index 3bd67fbed..9b0e4f08c 100644 --- a/tools/dpvs-agent/pkg/ipc/pool/util.go +++ b/tools/dpvs-agent/pkg/ipc/pool/util.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package pool import ( diff --git a/tools/dpvs-agent/pkg/ipc/proto/reader.go b/tools/dpvs-agent/pkg/ipc/proto/reader.go index b77dee8d1..6fd670115 100644 --- a/tools/dpvs-agent/pkg/ipc/proto/reader.go +++ b/tools/dpvs-agent/pkg/ipc/proto/reader.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package proto import ( @@ -62,274 +76,5 @@ func (r *Reader) buf(n int) []byte { } func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) { - /* - line, err := r.ReadLine() - - if err != nil { - return nil, err - } - - switch line[0] { - case ErrorReply: - return nil, ParseErrorReply(line) - case StatusReply: - return string(line[1:]), nil - case IntReply: - return util.ParseInt(line[1:], 10, 64) - case StringReply: - return r.readStringReply(line) - case ArrayReply: - n, err := parseArrayLen(line) - if err != nil { - return nil, err - } - if m == nil { - err := fmt.Errorf("dpvs: got %.100q, but multi bulk parser is nil", line) - return nil, err - } - return m(r, n) - } - */ return nil, fmt.Errorf("dpvs read failed") } - -/* -func (r *Reader) ReadLine() ([]byte, error) { - line, err := r.readLine() - if err != nil { - return nil, err - } - if isNilReply(line) { - return nil, Nil - } - return line, nil -} - -// readLine that returns an error if: -// - there is a pending read error; -// - or line does not end with \r\n. -func (r *Reader) readLine() ([]byte, error) { - b, err := r.rd.ReadSlice('\n') - if err != nil { - if err != bufio.ErrBufferFull { - return nil, err - } - - full := make([]byte, len(b)) - copy(full, b) - - b, err = r.rd.ReadBytes('\n') - if err != nil { - return nil, err - } - - full = append(full, b...) - b = full - } - if len(b) <= 2 || b[len(b)-1] != '\n' || b[len(b)-2] != '\r' { - return nil, fmt.Errorf("dpvs: invalid reply: %q", b) - } - return b[:len(b)-2], nil -} - -func (r *Reader) ReadIntReply() (int64, error) { - line, err := r.ReadLine() - if err != nil { - return 0, err - } - switch line[0] { - case ErrorReply: - return 0, ParseErrorReply(line) - case IntReply: - return util.ParseInt(line[1:], 10, 64) - default: - return 0, fmt.Errorf("dpvs: can't parse int reply: %.100q", line) - } -} - -func (r *Reader) ReadString() (string, error) { - line, err := r.ReadLine() - if err != nil { - return "", err - } - switch line[0] { - case ErrorReply: - return "", ParseErrorReply(line) - case StringReply: - return r.readStringReply(line) - case StatusReply: - return string(line[1:]), nil - case IntReply: - return string(line[1:]), nil - default: - return "", fmt.Errorf("dpvs: can't parse reply=%.100q reading string", line) - } -} - -func (r *Reader) readStringReply(line []byte) (string, error) { - if isNilReply(line) { - return "", Nil - } - - replyLen, err := util.Atoi(line[1:]) - if err != nil { - return "", err - } - - b := make([]byte, replyLen+2) - _, err = io.ReadFull(r.rd, b) - if err != nil { - return "", err - } - - return util.BytesToString(b[:replyLen]), nil -} - -func (r *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) { - line, err := r.ReadLine() - if err != nil { - return nil, err - } - switch line[0] { - case ErrorReply: - return nil, ParseErrorReply(line) - case ArrayReply: - n, err := parseArrayLen(line) - if err != nil { - return nil, err - } - return m(r, n) - default: - return nil, fmt.Errorf("dpvs: can't parse array reply: %.100q", line) - } -} - -func (r *Reader) ReadArrayLen() (int, error) { - line, err := r.ReadLine() - if err != nil { - return 0, err - } - switch line[0] { - case ErrorReply: - return 0, ParseErrorReply(line) - case ArrayReply: - n, err := parseArrayLen(line) - if err != nil { - return 0, err - } - return int(n), nil - default: - return 0, fmt.Errorf("dpvs: can't parse array reply: %.100q", line) - } -} -func (r *Reader) ReadScanReply() ([]string, uint64, error) { - n, err := r.ReadArrayLen() - if err != nil { - return nil, 0, err - } - if n != 2 { - return nil, 0, fmt.Errorf("dpvs: got %d elements in scan reply, expected 2", n) - } - - cursor, err := r.ReadUint() - if err != nil { - return nil, 0, err - } - - n, err = r.ReadArrayLen() - if err != nil { - return nil, 0, err - } - - keys := make([]string, n) - - for i := 0; i < n; i++ { - key, err := r.ReadString() - if err != nil { - return nil, 0, err - } - keys[i] = key - } - - return keys, cursor, err -} -*/ -/* -func (r *Reader) ReadInt() (int64, error) { - b, err := r.readTmpBytesReply() - if err != nil { - return 0, err - } - return util.ParseInt(b, 10, 64) -} - -func (r *Reader) ReadUint() (uint64, error) { - b, err := r.readTmpBytesReply() - if err != nil { - return 0, err - } - return util.ParseUint(b, 10, 64) -} - -func (r *Reader) ReadFloatReply() (float64, error) { - b, err := r.readTmpBytesReply() - if err != nil { - return 0, err - } - return util.ParseFloat(b, 64) -} - -func (r *Reader) readTmpBytesReply() ([]byte, error) { - line, err := r.ReadLine() - if err != nil { - return nil, err - } - switch line[0] { - case ErrorReply: - return nil, ParseErrorReply(line) - case StringReply: - return r._readTmpBytesReply(line) - case StatusReply: - return line[1:], nil - default: - return nil, fmt.Errorf("dpvs: can't parse string reply: %.100q", line) - } -} - -func (r *Reader) _readTmpBytesReply(line []byte) ([]byte, error) { - if isNilReply(line) { - return nil, Nil - } - - replyLen, err := util.Atoi(line[1:]) - if err != nil { - return nil, err - } - - buf := r.buf(replyLen + 2) - _, err = io.ReadFull(r.rd, buf) - if err != nil { - return nil, err - } - - return buf[:replyLen], nil -} -*/ -/* -func isNilReply(b []byte) bool { - return len(b) == 3 && - (b[0] == StringReply || b[0] == ArrayReply) && - b[1] == '-' && b[2] == '1' -} - -func ParseErrorReply(line []byte) error { - return DpvsError(string(line[1:])) -} - -func parseArrayLen(line []byte) (int64, error) { - if isNilReply(line) { - return 0, Nil - } - return util.ParseInt(line[1:], 10, 64) -} -*/ diff --git a/tools/dpvs-agent/pkg/ipc/proto/writer.go b/tools/dpvs-agent/pkg/ipc/proto/writer.go index a4aced90d..09dfde88e 100644 --- a/tools/dpvs-agent/pkg/ipc/proto/writer.go +++ b/tools/dpvs-agent/pkg/ipc/proto/writer.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package proto import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/certificate.go b/tools/dpvs-agent/pkg/ipc/types/certificate.go index b0b7b74a4..5f8ea82a5 100644 --- a/tools/dpvs-agent/pkg/ipc/types/certificate.go +++ b/tools/dpvs-agent/pkg/ipc/types/certificate.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/const.go b/tools/dpvs-agent/pkg/ipc/types/const.go index 9cbc3d49a..d210cf83e 100644 --- a/tools/dpvs-agent/pkg/ipc/types/const.go +++ b/tools/dpvs-agent/pkg/ipc/types/const.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go b/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go index 97c180ce7..80d37e20a 100644 --- a/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go +++ b/tools/dpvs-agent/pkg/ipc/types/dpvsmatch.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types type dpvsMatch struct { diff --git a/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go b/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go index dfd02c1e0..f9c16e3ee 100644 --- a/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go +++ b/tools/dpvs-agent/pkg/ipc/types/dpvsstats.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types type dpvsStats struct { diff --git a/tools/dpvs-agent/pkg/ipc/types/getmodel.go b/tools/dpvs-agent/pkg/ipc/types/getmodel.go index 6196594b2..673e4c8ee 100644 --- a/tools/dpvs-agent/pkg/ipc/types/getmodel.go +++ b/tools/dpvs-agent/pkg/ipc/types/getmodel.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/inetaddr.go b/tools/dpvs-agent/pkg/ipc/types/inetaddr.go index 661c31f09..0efb71f9e 100644 --- a/tools/dpvs-agent/pkg/ipc/types/inetaddr.go +++ b/tools/dpvs-agent/pkg/ipc/types/inetaddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/iprange.go b/tools/dpvs-agent/pkg/ipc/types/iprange.go index d35182498..5006f3424 100644 --- a/tools/dpvs-agent/pkg/ipc/types/iprange.go +++ b/tools/dpvs-agent/pkg/ipc/types/iprange.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types type ipRange struct { diff --git a/tools/dpvs-agent/pkg/ipc/types/kni.go b/tools/dpvs-agent/pkg/ipc/types/kni.go index afa2d0cff..2107464be 100644 --- a/tools/dpvs-agent/pkg/ipc/types/kni.go +++ b/tools/dpvs-agent/pkg/ipc/types/kni.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/laddr.go b/tools/dpvs-agent/pkg/ipc/types/laddr.go index 7e16f8763..ed26f5069 100644 --- a/tools/dpvs-agent/pkg/ipc/types/laddr.go +++ b/tools/dpvs-agent/pkg/ipc/types/laddr.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/method.go b/tools/dpvs-agent/pkg/ipc/types/method.go index ab1254f4c..2a73a0973 100644 --- a/tools/dpvs-agent/pkg/ipc/types/method.go +++ b/tools/dpvs-agent/pkg/ipc/types/method.go @@ -1 +1,15 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types diff --git a/tools/dpvs-agent/pkg/ipc/types/netif.go b/tools/dpvs-agent/pkg/ipc/types/netif.go index f403ebb03..4e7cccbac 100644 --- a/tools/dpvs-agent/pkg/ipc/types/netif.go +++ b/tools/dpvs-agent/pkg/ipc/types/netif.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/realserver.go b/tools/dpvs-agent/pkg/ipc/types/realserver.go index bd56a7eb6..1f7a36839 100644 --- a/tools/dpvs-agent/pkg/ipc/types/realserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/realserver.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/route.go b/tools/dpvs-agent/pkg/ipc/types/route.go index e428ff621..052df52c8 100644 --- a/tools/dpvs-agent/pkg/ipc/types/route.go +++ b/tools/dpvs-agent/pkg/ipc/types/route.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/sockmsg.go b/tools/dpvs-agent/pkg/ipc/types/sockmsg.go index 3db2543e5..8e889e0e9 100644 --- a/tools/dpvs-agent/pkg/ipc/types/sockmsg.go +++ b/tools/dpvs-agent/pkg/ipc/types/sockmsg.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/utility.go b/tools/dpvs-agent/pkg/ipc/types/utility.go index d887d9a19..d034883e5 100644 --- a/tools/dpvs-agent/pkg/ipc/types/utility.go +++ b/tools/dpvs-agent/pkg/ipc/types/utility.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import "strings" diff --git a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go index bb7cc409d..ca4e28e21 100644 --- a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/pkg/ipc/types/vlan.go b/tools/dpvs-agent/pkg/ipc/types/vlan.go index ece83c0ef..47a0417e9 100644 --- a/tools/dpvs-agent/pkg/ipc/types/vlan.go +++ b/tools/dpvs-agent/pkg/ipc/types/vlan.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package types import ( diff --git a/tools/dpvs-agent/restapi/configure_dpvs_agent.go b/tools/dpvs-agent/restapi/configure_dpvs_agent.go index f37abf18a..6875fef90 100644 --- a/tools/dpvs-agent/restapi/configure_dpvs_agent.go +++ b/tools/dpvs-agent/restapi/configure_dpvs_agent.go @@ -1,3 +1,17 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // This file is safe to edit. Once it exists it will not be overwritten package restapi From 4601c78c16f6ead84d8602080d415662e2409310 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Wed, 12 Jul 2023 20:48:18 +0800 Subject: [PATCH 052/105] update readme --- tools/dpvs-agent/README.md | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/tools/dpvs-agent/README.md b/tools/dpvs-agent/README.md index 0c25a01d1..23439e0a1 100644 --- a/tools/dpvs-agent/README.md +++ b/tools/dpvs-agent/README.md @@ -1,4 +1,38 @@ -#build +##setup a dpvs virtual service + +- set dpdk device (dpip vlan add dpdk0.102 link dpdk0 id 102) ``` -swagger generate server -A dpvs-agent -f ./dpvs-agent-api.yaml +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/vlan" -H "Content-type:application/json" -d "{\"device\":\"dpdk0\", \"id\":\"102\"}" +``` + +- set linux device up (ip link set dpdk0.102.kni up) +``` +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink" +``` +- add virtual service (ipvsadm -At 192.168.177.130:80 -s wrr) +``` +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp" -H "Content-type:application/json" -d "{\"SchedName\":\"wrr\"}" +``` + +- add vip to dpdk device (dpip addr add 192.168.77.130 dev dpdk0.102) +``` +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.177.130\"}" +``` + +- add vip to kni device (ip addr add 192.168.177.130 dev dpdk0.102.kni) +``` +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.177.130\"}" + +- set laddr of service (ipvsadm --add-laddr -z 192.168.188.247 -t 192.168.177.130:80 -F dpdk0.102) +``` +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.188.247\"}" +``` +- set laddr to device (dpip addr add 192.168.188.247/32 dev dpdk0.102) +``` +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.188.247\"}" +``` + +- add rss to service (ipvsadm -at 192.168.177.130:80 -r 192.168.188.101:80 -b) +``` +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"192.168.188.101\", \"port\":80, \"weight\":101}]}" ``` From f8b7f0b993cd68674907b0d314bf4c8bbf896982 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Wed, 12 Jul 2023 20:49:18 +0800 Subject: [PATCH 053/105] standardization logfmt --- tools/dpvs-agent/pkg/ipc/types/realserver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dpvs-agent/pkg/ipc/types/realserver.go b/tools/dpvs-agent/pkg/ipc/types/realserver.go index 1f7a36839..3ecb8a4a1 100644 --- a/tools/dpvs-agent/pkg/ipc/types/realserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/realserver.go @@ -642,6 +642,6 @@ func (front *RealServerFront) Update(rss []*RealServerSpec, cp *pool.ConnPool, p errCode := front.Del(unreserved, cp, logger) result := errCode.String() - logger.Info("Set", "rss", rss, "Done", "result", result) + logger.Info("Set real servers done", "rss", rss, "result", result) return errCode } From 250c0d131e131ed3f5fa6b91f1862609f2d9fe31 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 13 Jul 2023 14:41:25 +0800 Subject: [PATCH 054/105] version: release v1.9.5 Signed-off-by: ywc689 --- config.mk | 4 +-- src/VERSION | 25 ++++++------------- src/config.mk | 4 +-- .../dpvs-agent/cmd/dpvs-agent-server/Makefile | 1 + tools/dpvs-agent/restapi/embedded_spec.go | 12 ++++----- .../device/delete_device_name_netlink_addr.go | 2 +- .../device/get_device_name_netlink_addr.go | 2 +- .../device/put_device_name_netlink_addr.go | 2 +- 8 files changed, 21 insertions(+), 31 deletions(-) diff --git a/config.mk b/config.mk index 5d8648f12..91673dc93 100644 --- a/config.mk +++ b/config.mk @@ -19,8 +19,8 @@ export CONFIG_DPVS_SERVICE_DEBUG=n export CONFIG_SYNPROXY_DEBUG=n export CONFIG_TIMER_MEASURE=n export CONFIG_TIMER_DEBUG=n -export DPVS_CFG_PARSER_DEBUG=n -export NETIF_BONDING_DEBUG=n +export CONFIG_DPVS_CFG_PARSER_DEBUG=n +export CONFIG_NETIF_BONDING_DEBUG=n export CONFIG_TC_DEBUG=n export CONFIG_DPVS_IPVS_STATS_DEBUG=n export CONFIG_DPVS_IP_HEADER_DEBUG=n diff --git a/src/VERSION b/src/VERSION index b6b0a2641..1c9eb11df 100755 --- a/src/VERSION +++ b/src/VERSION @@ -1,28 +1,17 @@ #!/bin/sh # program: dpvs -# Apr 20, 2023 +# Jul 13, 2023 # # Features -# - Dpvs: Multiple instance deployment support. -# - Dpvs: IPC improvements between keepalived/ipvsadm and dpvs by combining data structs. +# - Add new tools: dpvs-agent and healthcheck. # # Bugfixes -# - Dpvs: Fix memory problem when setting MATCH service. -# - Ipvsadm: Fix service list problem when dpvs lcore ids are not continuous. -# - Ipvsadm: Fix the problem that service/dest/laddr cannot be listed per-lcore. -# - Ipvsadm: Support version info. -# - Fix several spelling mistakes. -# - Fix compiling errors on RHEL 9, Ubuntu 22.04 and microsoft standard WSL2. -# - Keepalived: Fix service deletion by mistake problem caused by uninitialized local variable. -# - Dpvs: Do not increase service num unless it's hashed sucessfully. -# - Dpvs: Fix sa_entry leak when flushing snat connections. -# - Keepalived: Fix ipvs allow/deny list config problem caused by incorrect parameters. -# - Dpvs: Fix dead lock problem of eal-mem show and rte_free. -# - Dpvs: Fix crash problem caused by msg_destroy when msg->refcnt==0. -# - Dpvs: Fix eal-mem module uninitialized problem. -# - Dpvs: Fix memory leak problem in ipvs allow list. +# - Dpvs: Improve config of adding/removing multicast ether addresses. +# - Dpvs: Fix synproxy config problems. +# - Keepalived: Fix session disturbance problem when vs/rs updated and reloaded. +# export VERSION=1.9 -export RELEASE=4 +export RELEASE=5 echo $VERSION-$RELEASE diff --git a/src/config.mk b/src/config.mk index 2a1ef13dc..0ba3597d0 100644 --- a/src/config.mk +++ b/src/config.mk @@ -71,11 +71,11 @@ ifeq ($(CONFIG_TIMER_DEBUG), y) CFLAGS += -D CONFIG_TIMER_DEBUG endif -ifeq ($(DPVS_CFG_PARSER_DEBUG), y) +ifeq ($(CONFIG_DPVS_CFG_PARSER_DEBUG), y) CFLAGS += -D DPVS_CFG_PARSER_DEBUG endif -ifeq ($(NETIF_BONDING_DEBUG), y) +ifeq ($(CONFIG_NETIF_BONDING_DEBUG), y) CFLAGS += -D NETIF_BONDING_DEBUG endif diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile b/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile index 9ba2dd914..84f6c3105 100644 --- a/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/Makefile @@ -12,6 +12,7 @@ RM = rm all: $(TARGET) $(TARGET): + -$(GO) mod tidy $(GO_BUILD) -o $@ clean: diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go index 488b7f0fe..797f664d2 100644 --- a/tools/dpvs-agent/restapi/embedded_spec.go +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -237,7 +237,7 @@ func init() { "tags": [ "device" ], - "summary": "display special linux net device addr detail", + "summary": "ip addr show lo: Display special linux net device addr detail", "parameters": [ { "$ref": "#/parameters/device-name" @@ -265,7 +265,7 @@ func init() { "tags": [ "device" ], - "summary": "set ip cird to linux net device", + "summary": "ip addr add 10.0.0.1/32 dev eth0: Set ip cird to linux net device", "parameters": [ { "$ref": "#/parameters/device-name" @@ -293,7 +293,7 @@ func init() { "tags": [ "device" ], - "summary": "delete ip cird fron linux net device", + "summary": "ip addr del 10.0.0.1/32 dev eth0: Delete ip cird fron linux net device", "parameters": [ { "$ref": "#/parameters/device-name" @@ -2369,7 +2369,7 @@ func init() { "tags": [ "device" ], - "summary": "display special linux net device addr detail", + "summary": "ip addr show lo: Display special linux net device addr detail", "parameters": [ { "type": "string", @@ -2403,7 +2403,7 @@ func init() { "tags": [ "device" ], - "summary": "set ip cird to linux net device", + "summary": "ip addr add 10.0.0.1/32 dev eth0: Set ip cird to linux net device", "parameters": [ { "type": "string", @@ -2438,7 +2438,7 @@ func init() { "tags": [ "device" ], - "summary": "delete ip cird fron linux net device", + "summary": "ip addr del 10.0.0.1/32 dev eth0: Delete ip cird fron linux net device", "parameters": [ { "type": "string", diff --git a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go index 63cb56c24..82e76ce12 100644 --- a/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go +++ b/tools/dpvs-agent/restapi/operations/device/delete_device_name_netlink_addr.go @@ -32,7 +32,7 @@ func NewDeleteDeviceNameNetlinkAddr(ctx *middleware.Context, handler DeleteDevic /* DeleteDeviceNameNetlinkAddr swagger:route DELETE /device/{name}/netlink/addr device deleteDeviceNameNetlinkAddr -delete ip cird fron linux net device +ip addr del 10.0.0.1/32 dev eth0: Delete ip cird fron linux net device */ type DeleteDeviceNameNetlinkAddr struct { Context *middleware.Context diff --git a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go index d9670c047..dde2ce7dd 100644 --- a/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go +++ b/tools/dpvs-agent/restapi/operations/device/get_device_name_netlink_addr.go @@ -32,7 +32,7 @@ func NewGetDeviceNameNetlinkAddr(ctx *middleware.Context, handler GetDeviceNameN /* GetDeviceNameNetlinkAddr swagger:route GET /device/{name}/netlink/addr device getDeviceNameNetlinkAddr -display special linux net device addr detail +ip addr show lo: Display special linux net device addr detail */ type GetDeviceNameNetlinkAddr struct { Context *middleware.Context diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go index b08ea86b7..5a05d698c 100644 --- a/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_netlink_addr.go @@ -32,7 +32,7 @@ func NewPutDeviceNameNetlinkAddr(ctx *middleware.Context, handler PutDeviceNameN /* PutDeviceNameNetlinkAddr swagger:route PUT /device/{name}/netlink/addr device putDeviceNameNetlinkAddr -set ip cird to linux net device +ip addr add 10.0.0.1/32 dev eth0: Set ip cird to linux net device */ type PutDeviceNameNetlinkAddr struct { Context *middleware.Context From 2b904447c2c8ba84530f6237430e36758a03da91 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Thu, 13 Jul 2023 17:52:38 +0800 Subject: [PATCH 055/105] aligning readme code block --- tools/dpvs-agent/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/dpvs-agent/README.md b/tools/dpvs-agent/README.md index 23439e0a1..29b10d3f9 100644 --- a/tools/dpvs-agent/README.md +++ b/tools/dpvs-agent/README.md @@ -9,6 +9,7 @@ curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/vlan" -H "Content-type:a ``` curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink" ``` + - add virtual service (ipvsadm -At 192.168.177.130:80 -s wrr) ``` curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp" -H "Content-type:application/json" -d "{\"SchedName\":\"wrr\"}" @@ -22,11 +23,13 @@ curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr" -H "Content-type:a - add vip to kni device (ip addr add 192.168.177.130 dev dpdk0.102.kni) ``` curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.177.130\"}" +``` - set laddr of service (ipvsadm --add-laddr -z 192.168.188.247 -t 192.168.177.130:80 -F dpdk0.102) ``` curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.188.247\"}" ``` + - set laddr to device (dpip addr add 192.168.188.247/32 dev dpdk0.102) ``` curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.188.247\"}" From 50b8372089ac0d3b9f1c5d16676931ef330a4c2a Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 13 Jul 2023 18:01:31 +0800 Subject: [PATCH 056/105] dpvs-agent: update README doc Signed-off-by: ywc689 --- tools/dpvs-agent/README.md | 100 ++++++++++++++++++++++++++++++------- 1 file changed, 82 insertions(+), 18 deletions(-) diff --git a/tools/dpvs-agent/README.md b/tools/dpvs-agent/README.md index 23439e0a1..89d5592e4 100644 --- a/tools/dpvs-agent/README.md +++ b/tools/dpvs-agent/README.md @@ -1,38 +1,102 @@ -##setup a dpvs virtual service +Demo: Setup a DPVS Virtual Service +------ + +> This is a demo to setup a miminal fullnat virtual service with dpvs-agent API. Not all supported APIs are involved. We haven't document the dpvs-agent API yet. Refer to [dpvs-agent openapi definition](./dpvs-agent-api.yaml) for a full view of supported API. + +The demo shows how to setup the service from scratch with dpvs-agent API. -- set dpdk device (dpip vlan add dpdk0.102 link dpdk0 id 102) ``` -curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/vlan" -H "Content-type:application/json" -d "{\"device\":\"dpdk0\", \"id\":\"102\"}" +[root@dpvs-devel 17:53:46 dpvs-agent]# ipvsadm -ln +IP Virtual Server version 1.9.5 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.88.100:80 wrr + -> 192.168.88.30:80 FullNat 101 0 0 +[root@dpvs-devel 17:53:54 dpvs-agent]# ipvsadm -G +VIP:VPORT TOTAL SNAT_IP CONFLICTS CONNS +192.168.88.100:80 1 + 192.168.88.241 0 0 +[root@dpvs-devel 17:53:56 dpvs-agent]# dpip addr show -s +inet 192.168.88.100/32 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet 192.168.88.28/24 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet 192.168.88.241/32 scope global dpdk0.102 + valid_lft forever preferred_lft forever sa_used 0 sa_free 1032176 sa_miss 0 +[root@dpvs-devel 17:53:59 dpvs-agent]# ip addr show dev dpdk0.102.kni +172: dpdk0.102.kni: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + link/ether 24:6e:96:75:7c:fa brd ff:ff:ff:ff:ff:ff + inet 192.168.88.128/24 brd 192.168.88.255 scope global dpdk0.102.kni + valid_lft forever preferred_lft forever + inet 192.168.88.100/32 scope global dpdk0.102.kni + valid_lft forever preferred_lft forever + inet6 fe80::266e:96ff:fe75:7cfa/64 scope link + valid_lft forever preferred_lft forever ``` -- set linux device up (ip link set dpdk0.102.kni up) +- Create a vlan device (dpip vlan add dpdk0.102 link dpdk0 id 102) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/vlan" -H "Content-type:application/json" -d "{\"device\":\"dpdk0\", \"id\":\"102\"}" ``` + +- Set kni device up (ip link set dpdk0.102.kni up) + +```sh curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink" ``` -- add virtual service (ipvsadm -At 192.168.177.130:80 -s wrr) -``` -curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp" -H "Content-type:application/json" -d "{\"SchedName\":\"wrr\"}" -``` -- add vip to dpdk device (dpip addr add 192.168.77.130 dev dpdk0.102) +- Config host IP for dpdk0.102 (dpip addr add 192.168.88.28/24 dev dpdk0.102) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.28/24\"}" ``` -curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.177.130\"}" + +- Config host IP for dpdk0.102.kni (dpip addr add 192.168.88.128/24 dev dpdk0.102.kni) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.128/24\"}" ``` -- add vip to kni device (ip addr add 192.168.177.130 dev dpdk0.102.kni) +- Config kni route for host IP of dpdk0.102.kni (dpip route add 192.168.88.128/32 dev dpdk.102 scope kni_host) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/route" -H "Content-type:application/json" -d "{\"dst\":\"192.168.88.128\", \"scope\":\"kni_host\"}" ``` -curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.177.130\"}" -- set laddr of service (ipvsadm --add-laddr -z 192.168.188.247 -t 192.168.177.130:80 -F dpdk0.102) +- Add a virtual service (ipvsadm -At 192.168.88.100:80 -s wrr) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.88.100-80-tcp" -H "Content-type:application/json" -d "{\"SchedName\":\"wrr\"}" ``` -curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.188.247\"}" + +- Add vip onto dpdk0.102 (dpip addr add 192.168.88.100 dev dpdk0.102) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.100\"}" ``` -- set laddr to device (dpip addr add 192.168.188.247/32 dev dpdk0.102) + +- Add vip onto dpdk0.102.kni (ip addr add 192.168.88.100 dev dpdk0.102.kni) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.100\"}" ``` -curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.188.247\"}" +- Set laddr for the service (ipvsadm --add-laddr -z 192.168.88.241 -t 192.168.88.100:80 -F dpdk0.102) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.88.100-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.88.241\"}" ``` -- add rss to service (ipvsadm -at 192.168.177.130:80 -r 192.168.188.101:80 -b) +- Add laddr onto dpdk0.102 (dpip addr add 192.168.88.241/32 dev dpdk0.102) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.241\"}" ``` -curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.177.130-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"192.168.188.101\", \"port\":80, \"weight\":101}]}" + +- Add backend server(s) to the service (ipvsadm -at 192.168.88.100:80 -r 192.168.88.30:80 -w 101 -b) + +```sh +curl -X PUT "http://127.0.0.1:53225/v2/vs/192.168.88.100-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"192.168.88.30\", \"port\":80, \"weight\":101}]}" ``` + +Finally, deploy a http service on backend server `192.168.88.30:80`, and make a request to virtual service `192.168.88.100:80` from another server in this network. Hopefully, you may get a success response. From 192e38747bf76c1b83beb94cc6de75a1cf16e6c0 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 17 Jul 2023 21:06:28 +0800 Subject: [PATCH 057/105] tools/healthcheck: use the same port number as dpvs-agent for lb_iface_addr Signed-off-by: ywc689 --- tools/healthcheck/Makefile | 3 ++- tools/healthcheck/pkg/helthcheck/configs.go | 2 +- tools/healthcheck/pkg/lb/dpvs_agent.go | 2 +- tools/healthcheck/test/dpvs-agent-api.sh | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/healthcheck/Makefile b/tools/healthcheck/Makefile index 27e506bba..6e866e140 100644 --- a/tools/healthcheck/Makefile +++ b/tools/healthcheck/Makefile @@ -1,7 +1,8 @@ TARGET := healthcheck GO ?= go -GO_BUILD = CGO_ENABLED=0 $(GO) build +LD_FLAGS = -ldflags="-s -w" +GO_BUILD = CGO_ENABLED=0 $(GO) build $(LD_FLAGS) GO_CLEAN = $(GO) clean .PHONY: all $(TARGET) clean diff --git a/tools/healthcheck/pkg/helthcheck/configs.go b/tools/healthcheck/pkg/helthcheck/configs.go index 3d95a6ec1..7759928b5 100644 --- a/tools/healthcheck/pkg/helthcheck/configs.go +++ b/tools/healthcheck/pkg/helthcheck/configs.go @@ -48,7 +48,7 @@ var defaultServerConfig = ServerConfig{ NotifyInterval: 15 * time.Second, FetchInterval: 15 * time.Second, LbIfaceType: "dpvs-agent", // only type supported now - LbIfaceAddr: "localhost:6600", + LbIfaceAddr: "localhost:53225", LbAutoMethod: true, DryRun: false, Debug: false, diff --git a/tools/healthcheck/pkg/lb/dpvs_agent.go b/tools/healthcheck/pkg/lb/dpvs_agent.go index 0e0072785..29d403430 100644 --- a/tools/healthcheck/pkg/lb/dpvs_agent.go +++ b/tools/healthcheck/pkg/lb/dpvs_agent.go @@ -30,7 +30,7 @@ import ( var _ Comm = (*DpvsAgentComm)(nil) var ( - serverDefault = "localhost:6600" + serverDefault = "localhost:53225" listUri = LbApi{"/v2/vs", http.MethodGet} noticeUri = LbApi{"/v2/vs/%s/rs?healthcheck=true", http.MethodPut} diff --git a/tools/healthcheck/test/dpvs-agent-api.sh b/tools/healthcheck/test/dpvs-agent-api.sh index a5013c206..136dd4346 100755 --- a/tools/healthcheck/test/dpvs-agent-api.sh +++ b/tools/healthcheck/test/dpvs-agent-api.sh @@ -17,12 +17,12 @@ import json def UpdateService(): payload="{\"Items\":[{\"inhibited\":false,\"ip\":\"192.168.88.68\",\"port\":80,\"weight\":100}]}" - url = "http://127.0.0.1:6600/v2/vs/192.168.88.1-80-TCP/rs?healthcheck=true" + url = "http://127.0.0.1:53225/v2/vs/192.168.88.1-80-TCP/rs?healthcheck=true" headers = {'content-type': 'application/json'} r = requests.put(url, headers=headers, data=payload) print(r, r.json()) - url = "http://127.0.0.1:6600/v2/vs/192.168.88.1-80-TCP" + url = "http://127.0.0.1:53225/v2/vs/192.168.88.1-80-TCP" headers = {'content-type': 'application/json'} r = requests.get(url, headers=headers, data=payload) print(r, r.json()) From 622044d8d02bab4ceeaaa0dc91306173b336f583 Mon Sep 17 00:00:00 2001 From: huangyichen Date: Thu, 20 Jul 2023 17:01:34 +0800 Subject: [PATCH 058/105] set byte-order of rs.ID() --- tools/dpvs-agent/pkg/ipc/types/realserver.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/dpvs-agent/pkg/ipc/types/realserver.go b/tools/dpvs-agent/pkg/ipc/types/realserver.go index 3ecb8a4a1..e1264358c 100644 --- a/tools/dpvs-agent/pkg/ipc/types/realserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/realserver.go @@ -244,7 +244,11 @@ func (rs *RealServerSpec) GetFwdModeString() string { } func (rs *RealServerSpec) ID() string { - return fmt.Sprintf("%s:%d", rs.GetAddr(), rs.port) + // proto := "tcp" + // if rs.proto == unix.IPPROTO_UDP { + // proto = "udp" + // } + return fmt.Sprintf("%s:%d", rs.GetAddr(), rs.GetPort()) } func (rs *RealServerSpec) Format(kind string) string { @@ -303,7 +307,10 @@ func (rs *RealServerFront) GetAf() uint32 { } func (rs *RealServerFront) GetPort() uint16 { - return rs.port + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16(rs.port)) + return binary.BigEndian.Uint16(buf.Bytes()) + //return rs.port } func (rs *RealServerFront) GetProto() uint16 { From 0cad593c640647bdc842a90fbd9ae45118547dbe Mon Sep 17 00:00:00 2001 From: huangyichen Date: Thu, 20 Jul 2023 18:02:53 +0800 Subject: [PATCH 059/105] virtual service flags(synproxy&expire_quiescent) value has changed at ae1820c3 --- tools/dpvs-agent/pkg/ipc/types/const.go | 82 +++++++++---------- tools/dpvs-agent/pkg/ipc/types/getmodel.go | 4 +- .../dpvs-agent/pkg/ipc/types/virtualserver.go | 12 +-- 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/tools/dpvs-agent/pkg/ipc/types/const.go b/tools/dpvs-agent/pkg/ipc/types/const.go index d210cf83e..30be74fdb 100644 --- a/tools/dpvs-agent/pkg/ipc/types/const.go +++ b/tools/dpvs-agent/pkg/ipc/types/const.go @@ -24,67 +24,67 @@ type DpvsErrType int32 type DpvsFwdMode uint32 const ( - DPVS_FWD_MASQ DpvsFwdMode = iota - DPVS_FWD_LOCALNODE - DPVS_FWD_MODE_TUNNEL - DPVS_FWD_MODE_DR - DPVS_FWD_MODE_BYPASS - DPVS_FWD_MODE_FNAT - DPVS_FWD_MODE_SNAT + DPVS_FWD_MASQ DpvsFwdMode = iota // 0x0 + DPVS_FWD_LOCALNODE // 0x1 + DPVS_FWD_MODE_TUNNEL // 0x2 + DPVS_FWD_MODE_DR // 0x3 + DPVS_FWD_MODE_BYPASS // 0x4 + DPVS_FWD_MODE_FNAT // 0x5 + DPVS_FWD_MODE_SNAT // 0x6 ) -const DPVS_FWD_MODE_NAT DpvsFwdMode = DPVS_FWD_MASQ -const ( - DPVS_SVC_F_PERSISTENT = 0x1 << iota - DPVS_SVC_F_HASHED - DPVS_SVC_F_ONEPACKET - DPVS_SVC_F_SCHED1 - DPVS_SVC_F_SCHED2 - DPVS_SVC_F_SCHED3 -) +const DPVS_FWD_MODE_NAT DpvsFwdMode = DPVS_FWD_MASQ const ( - DPVS_SVC_F_SIP_HASH uint32 = 0x100 << iota - DPVS_SVC_F_QID_HASH - DPVS_SVC_F_MATCH + DPVS_SVC_F_PERSISTENT uint32 = 0x1 << iota + DPVS_SVC_F_HASHED // 0x2 + DPVS_SVC_F_ONEPACKET // 0x4 + DPVS_SVC_F_SYNPROXY // 0x8 + DPVS_SVC_F_EXPIRE_QUIESCENT // 0x10 + DPVS_SVC_F_SCHED1 // 0x20 + DPVS_SVC_F_SCHED2 // 0x40 + DPVS_SVC_F_SCHED3 // 0x80 + DPVS_SVC_F_SIP_HASH // 0x100 + DPVS_SVC_F_QID_HASH // 0x200 + DPVS_SVC_F_MATCH // 0x400 ) const ( DPVS_DEST_HC_PASSIVE = 0x1 << iota - DPVS_DEST_HC_TCP - DPVS_DEST_HC_UDP - DPVS_DEST_HC_PING + DPVS_DEST_HC_TCP // 0x2 + DPVS_DEST_HC_UDP // 0x4 + DPVS_DEST_HC_PING // 0x8 ) const ( DPVS_DEST_F_AVAILABLE = 0x1 << iota - DPVS_DEST_F_OVERLOAD - DPVS_DEST_F_INHIBITED + DPVS_DEST_F_OVERLOAD // 0x2 + DPVS_DEST_F_INHIBITED // 0x4 ) const ( - DPVS_CONN_F_MASQ = iota - DPVS_CONN_F_LOCALNODE - DPVS_CONN_F_TUNNEL - DPVS_CONN_F_DROUTE - DPVS_CONN_F_BYPASS - DPVS_CONN_F_FULLNAT - DPVS_CONN_F_SNAT - DPVS_CONN_F_FWD_MASK + DPVS_CONN_F_MASQ = iota + DPVS_CONN_F_LOCALNODE // 0x1 + DPVS_CONN_F_TUNNEL // 0x2 + DPVS_CONN_F_DROUTE // 0x3 + DPVS_CONN_F_BYPASS // 0x4 + DPVS_CONN_F_FULLNAT // 0x5 + DPVS_CONN_F_SNAT // 0x6 + DPVS_CONN_F_FWD_MASK // 0x7 ) const ( - DPVS_CONN_F_SYNPROXY = 0x10 << iota - DPVS_CONN_F_EXPIRE_QUIESCENT + DPVS_CONN_F_SYNPROXY = 0x10 << iota + DPVS_CONN_F_EXPIRE_QUIESCENT // 0x20 _ _ - DPVS_CONN_F_HASHED - DPVS_CONN_F_INACTIVE - DPVS_CONN_F_TEMPLATE - DPVS_CONN_F_ONE_PACKET - DPVS_CONN_F_IN_TIMER - DPVS_CONN_F_REDIRECT_HASHED - DPVS_CONN_F_NOFASTXMIT + DPVS_CONN_F_HASHED // 0x100 + DPVS_CONN_F_INACTIVE // 0x200 + DPVS_CONN_F_TEMPLATE // 0x400 + DPVS_CONN_F_ONE_PACKET // 0x800 + DPVS_CONN_F_IN_TIMER // 0x1000 + DPVS_CONN_F_REDIRECT_HASHED // 0x2000 + DPVS_CONN_F_NOFASTXMIT // 0x4000 ) func (e *DpvsFwdMode) String() string { diff --git a/tools/dpvs-agent/pkg/ipc/types/getmodel.go b/tools/dpvs-agent/pkg/ipc/types/getmodel.go index 673e4c8ee..7e3a1b392 100644 --- a/tools/dpvs-agent/pkg/ipc/types/getmodel.go +++ b/tools/dpvs-agent/pkg/ipc/types/getmodel.go @@ -39,12 +39,12 @@ func (vs *VirtualServerSpec) GetModel() *models.VirtualServerSpecExpand { } flags := "" - if (vs.GetFlags() & DPVS_CONN_F_SYNPROXY) != 0 { + if (vs.GetFlags() & DPVS_SVC_F_SYNPROXY) != 0 { modelVs.SyncProxy = "true" flags += "SynProxy|" } - if (vs.GetFlags() & DPVS_CONN_F_EXPIRE_QUIESCENT) != 0 { + if (vs.GetFlags() & DPVS_SVC_F_EXPIRE_QUIESCENT) != 0 { modelVs.ExpireQuiescent = "true" flags += "ExpireQuiescent|" } diff --git a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go index ca4e28e21..a3e1c6456 100644 --- a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go @@ -266,11 +266,11 @@ func (vs *VirtualServerSpec) GetFwmark() uint32 { } func (vs *VirtualServerSpec) SetFlagsSyncProxy() { - vs.setFlags(DPVS_CONN_F_SYNPROXY) + vs.setFlags(DPVS_SVC_F_SYNPROXY) } func (vs *VirtualServerSpec) SetFlagsExpireQuiescent() { - vs.setFlags(DPVS_CONN_F_EXPIRE_QUIESCENT) + vs.setFlags(DPVS_SVC_F_EXPIRE_QUIESCENT) } func (vs *VirtualServerSpec) SetFlagsPersistent() { @@ -278,15 +278,15 @@ func (vs *VirtualServerSpec) SetFlagsPersistent() { } func (vs *VirtualServerSpec) SetFlagsHashSrcIP() { - vs.flags &= (uint32)(^DPVS_SVC_F_QID_HASH) - vs.flags &= (uint32)(^DPVS_SVC_F_SIP_HASH) + vs.flags &= ^DPVS_SVC_F_QID_HASH + vs.flags &= ^DPVS_SVC_F_SIP_HASH vs.setFlags(DPVS_SVC_F_SIP_HASH) } func (vs *VirtualServerSpec) SetFlagsHashQuicID() { - vs.flags &= (uint32)(^DPVS_SVC_F_QID_HASH) - vs.flags &= (uint32)(^DPVS_SVC_F_SIP_HASH) + vs.flags &= ^DPVS_SVC_F_QID_HASH + vs.flags &= ^DPVS_SVC_F_SIP_HASH vs.setFlags(DPVS_SVC_F_QID_HASH) } From c893ae6fba5489485c61dd7274856f9d896c03bc Mon Sep 17 00:00:00 2001 From: you-looks-not-tasty <42596733+you-looks-not-tasty@users.noreply.github.com> Date: Wed, 26 Jul 2023 09:42:02 +0800 Subject: [PATCH 060/105] set ipc socket by options --ipc-sockopt-path (#11) --- tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go index c9b885685..bc269e4ff 100644 --- a/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go +++ b/tools/dpvs-agent/cmd/dpvs-agent-server/api_init.go @@ -45,7 +45,7 @@ type DpvsAgentServer struct { func unixDialer(ctx context.Context) (net.Conn, error) { retry := 0 d := net.Dialer{Timeout: 10 * time.Second} - raddr := net.UnixAddr{Name: "/var/run/dpvs.ipc", Net: "unix"} + raddr := net.UnixAddr{Name: IpcSocket, Net: "unix"} for { conn, err := d.DialContext(ctx, "unix", raddr.String()) if err == nil { From 07509fc4874629db0a2706736231206b660121e0 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 28 Jul 2023 11:44:47 +0800 Subject: [PATCH 061/105] ip_vs_conn: fix dest::dfc.master.timer deadlock problem when rs in persistent service is deleted The deadlock problem is triggered when persistent templated session timed out and the realserver was deleted previously. All timer functions called in timer's session expiration should use the -nolock version. Signed-off-by: ywc689 --- include/ipvs/dest.h | 2 +- src/ipvs/ip_vs_conhash.c | 2 +- src/ipvs/ip_vs_conn.c | 10 +++++----- src/ipvs/ip_vs_dest.c | 12 ++++++++---- src/ipvs/ip_vs_mh.c | 4 ++-- src/ipvs/ip_vs_service.c | 2 +- 6 files changed, 18 insertions(+), 14 deletions(-) diff --git a/include/ipvs/dest.h b/include/ipvs/dest.h index 1e1c70c5b..ff5d2f3c1 100644 --- a/include/ipvs/dest.h +++ b/include/ipvs/dest.h @@ -151,7 +151,7 @@ int dp_vs_dest_edit_health(struct dp_vs_service *svc, struct dp_vs_dest_conf *ud void dp_vs_dest_unlink(struct dp_vs_service *svc, struct dp_vs_dest *dest, int svcupd); -void dp_vs_dest_put(struct dp_vs_dest *dest); +void dp_vs_dest_put(struct dp_vs_dest *dest, bool timerlock); int dp_vs_dest_del(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest); diff --git a/src/ipvs/ip_vs_conhash.c b/src/ipvs/ip_vs_conhash.c index 858c4b503..6c0ecbb6c 100644 --- a/src/ipvs/ip_vs_conhash.c +++ b/src/ipvs/ip_vs_conhash.c @@ -141,7 +141,7 @@ static void node_fini(struct node_s *node) return; if (node->data) { - dp_vs_dest_put((struct dp_vs_dest *)node->data); + dp_vs_dest_put((struct dp_vs_dest *)node->data, true); node->data = NULL; } diff --git a/src/ipvs/ip_vs_conn.c b/src/ipvs/ip_vs_conn.c index 82a30a06f..f88ae0e29 100644 --- a/src/ipvs/ip_vs_conn.c +++ b/src/ipvs/ip_vs_conn.c @@ -388,7 +388,7 @@ static int dp_vs_conn_bind_dest(struct dp_vs_conn *conn, return EDPVS_OK; } -static int dp_vs_conn_unbind_dest(struct dp_vs_conn *conn) +static int dp_vs_conn_unbind_dest(struct dp_vs_conn *conn, bool timerlock) { struct dp_vs_dest *dest = conn->dest; @@ -407,7 +407,7 @@ static int dp_vs_conn_unbind_dest(struct dp_vs_conn *conn) dest->flags &= ~DPVS_DEST_F_OVERLOAD; } - dp_vs_dest_put(dest); + dp_vs_dest_put(dest, timerlock); conn->dest = NULL; return EDPVS_OK; @@ -680,7 +680,7 @@ static int dp_vs_conn_expire(void *priv) pp->conn_expire(pp, conn); dp_vs_conn_sa_release(conn); - dp_vs_conn_unbind_dest(conn); + dp_vs_conn_unbind_dest(conn, false); dp_vs_laddr_unbind(conn); dp_vs_conn_free_packets(conn); @@ -784,7 +784,7 @@ static void conn_flush(void) (struct sockaddr_storage *)&saddr); } - dp_vs_conn_unbind_dest(conn); + dp_vs_conn_unbind_dest(conn, true); dp_vs_laddr_unbind(conn); rte_atomic32_dec(&conn->refcnt); @@ -987,7 +987,7 @@ struct dp_vs_conn *dp_vs_conn_new(struct rte_mbuf *mbuf, unbind_laddr: dp_vs_laddr_unbind(new); unbind_dest: - dp_vs_conn_unbind_dest(new); + dp_vs_conn_unbind_dest(new, true); errout: dp_vs_conn_free(new); return NULL; diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 9d0c93198..0a337f9a9 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -268,14 +268,18 @@ int dp_vs_dest_edit_health(struct dp_vs_service *svc, struct dp_vs_dest_conf *ud return EDPVS_OK; } -void dp_vs_dest_put(struct dp_vs_dest *dest) +void dp_vs_dest_put(struct dp_vs_dest *dest, bool timerlock) { if (!dest) return; if (rte_atomic32_dec_and_test(&dest->refcnt)) { - if (rte_lcore_id() == g_master_lcore_id) - dpvs_timer_cancel(&dest->dfc.master.timer, true); + if (rte_lcore_id() == g_master_lcore_id) { + if (timerlock) + dpvs_timer_cancel(&dest->dfc.master.timer, true); + else + dpvs_timer_cancel_nolock(&dest->dfc.master.timer, true); + } dp_vs_service_unbind(dest); rte_free(dest); } @@ -333,7 +337,7 @@ dp_vs_dest_del(struct dp_vs_service *svc, struct dp_vs_dest_conf *udest) /* * Delete the destination */ - dp_vs_dest_put(dest); + dp_vs_dest_put(dest, true); return EDPVS_OK; } diff --git a/src/ipvs/ip_vs_mh.c b/src/ipvs/ip_vs_mh.c index b14cc05af..eba4781f8 100644 --- a/src/ipvs/ip_vs_mh.c +++ b/src/ipvs/ip_vs_mh.c @@ -97,7 +97,7 @@ static void dp_vs_mh_reset(struct dp_vs_mh_state *s) l = &s->lookup[0]; for (i = 0; i < DP_VS_MH_TAB_SIZE; i++) { if (l->dest) { - dp_vs_dest_put(l->dest); + dp_vs_dest_put(l->dest, true); l->dest = NULL; } l++; @@ -195,7 +195,7 @@ static int dp_vs_mh_populate(struct dp_vs_mh_state *s, new_dest = list_entry(p, struct dp_vs_dest, n_list); if (dest != new_dest) { if (dest) - dp_vs_dest_put(dest); + dp_vs_dest_put(dest, true); rte_atomic32_inc(&new_dest->refcnt); s->lookup[c].dest = new_dest; } diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index 039c3738c..839b4828e 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -614,7 +614,7 @@ static void __dp_vs_service_del(struct dp_vs_service *svc) */ list_for_each_entry_safe(dest, nxt, &svc->dests, n_list) { dp_vs_dest_unlink(svc, dest, 0); - dp_vs_dest_put(dest); + dp_vs_dest_put(dest, true); } /* From b64dae77fa5099a2ee013e8ad08a4453dde8e412 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 31 Jul 2023 09:35:01 +0800 Subject: [PATCH 062/105] dpip: fix line break problem in help message Signed-off-by: ywc689 --- tools/dpip/route.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dpip/route.c b/tools/dpip/route.c index d89e40939..a2fe4dfe8 100644 --- a/tools/dpip/route.c +++ b/tools/dpip/route.c @@ -42,7 +42,7 @@ static void route_help(void) " dpip route add default via 10.0.0.1\n" " dpip route add 172.0.0.0/16 via 172.0.0.3 dev dpdk0\n" " dpip route add 192.168.0.0/24 dev dpdk0\n" - " dpip -6 route add ffe1::/128 dev dpdk0" + " dpip -6 route add ffe1::/128 dev dpdk0\n" " dpip -6 route add 2001:db8:1::/64 via 2001:db8:1::1 dev dpdk0\n" " dpip route del 172.0.0.0/16\n" " dpip route set 172.0.0.0/16 via 172.0.0.1\n" From 89e8c30efbe92f6b93a7d6818d066804c3a1cb75 Mon Sep 17 00:00:00 2001 From: roykingz Date: Thu, 10 Aug 2023 09:27:04 +0800 Subject: [PATCH 063/105] dpvs: fix ipo option length bug when insert ipo. Length of ipo is sizeof(struct ipopt_uoa) + IPv4_addr_length = 8. --- src/ipvs/ip_vs_proto_udp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ipvs/ip_vs_proto_udp.c b/src/ipvs/ip_vs_proto_udp.c index 4adecb4bf..0a3a51b85 100644 --- a/src/ipvs/ip_vs_proto_udp.c +++ b/src/ipvs/ip_vs_proto_udp.c @@ -454,9 +454,9 @@ static int insert_ipopt_uoa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, struct ipopt_uoa *optuoa; assert(AF_INET == tuplehash_in(conn).af && AF_INET == tuplehash_out(conn).af); - if ((ip4_hdrlen(mbuf) + sizeof(struct ipopt_uoa) > + if ((ip4_hdrlen(mbuf) + IPOLEN_UOA_IPV4 > sizeof(struct iphdr) + MAX_IPOPTLEN) - || (mbuf->pkt_len + sizeof(struct ipopt_uoa) > mtu)) + || (mbuf->pkt_len + IPOLEN_UOA_IPV4 > mtu)) goto standalone_uoa; /* From 5e0ff90b0ae95bdb5c1cc71188ca9f62d97a2df1 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 14 Aug 2023 17:25:42 +0800 Subject: [PATCH 064/105] dpvs-agent: fix conhash service setup problem caused by spelling mistake Signed-off-by: ywc689 --- src/ipvs/ip_vs_conhash.c | 2 +- src/ipvs/libconhash/conhash.c | 2 +- tools/dpvs-agent/dpvs-agent-api.yaml | 4 ++-- tools/dpvs-agent/models/virtual_server_spec_expand.go | 8 ++++---- tools/dpvs-agent/models/virtual_server_spec_tiny.go | 8 ++++---- tools/dpvs-agent/restapi/embedded_spec.go | 8 ++++---- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ipvs/ip_vs_conhash.c b/src/ipvs/ip_vs_conhash.c index 6c0ecbb6c..360346ad2 100644 --- a/src/ipvs/ip_vs_conhash.c +++ b/src/ipvs/ip_vs_conhash.c @@ -311,7 +311,7 @@ static int dp_vs_conhash_edit_dest(struct dp_vs_service *svc, } /* - * Assign dest to connhash. + * Assign dest to conhash. */ static int dp_vs_conhash_assign(struct dp_vs_service *svc) diff --git a/src/ipvs/libconhash/conhash.c b/src/ipvs/libconhash/conhash.c index 3e6b14869..a747d810a 100644 --- a/src/ipvs/libconhash/conhash.c +++ b/src/ipvs/libconhash/conhash.c @@ -7,7 +7,7 @@ struct conhash_s* conhash_init(conhash_cb_hashfunc pfhash) { /* alloc memory and set to zero */ - struct conhash_s *conhash = (struct conhash_s*)rte_zmalloc("connhash",sizeof(struct conhash_s), RTE_CACHE_LINE_SIZE); + struct conhash_s *conhash = (struct conhash_s*)rte_zmalloc("conhash",sizeof(struct conhash_s), RTE_CACHE_LINE_SIZE); if(conhash == NULL) { return NULL; diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml index ac8487bef..ae92725ee 100644 --- a/tools/dpvs-agent/dpvs-agent-api.yaml +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -530,7 +530,7 @@ definitions: - rr - wrr - wlc - - connhash + - conhash DestCheck: type: array items: @@ -585,7 +585,7 @@ definitions: - rr - wrr - wlc - - connhash + - conhash Match: "$ref": "#/definitions/MatchSpec" paths: diff --git a/tools/dpvs-agent/models/virtual_server_spec_expand.go b/tools/dpvs-agent/models/virtual_server_spec_expand.go index dd887a72d..bf04aa918 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_expand.go +++ b/tools/dpvs-agent/models/virtual_server_spec_expand.go @@ -65,7 +65,7 @@ type VirtualServerSpecExpand struct { RSs *RealServerExpandList `json:"RSs,omitempty"` // sched name - // Enum: [rr wrr wlc connhash] + // Enum: [rr wrr wlc conhash] SchedName string `json:"SchedName,omitempty"` // stats @@ -222,7 +222,7 @@ var virtualServerSpecExpandTypeSchedNamePropEnum []interface{} func init() { var res []string - if err := json.Unmarshal([]byte(`["rr","wrr","wlc","connhash"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["rr","wrr","wlc","conhash"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -241,8 +241,8 @@ const ( // VirtualServerSpecExpandSchedNameWlc captures enum value "wlc" VirtualServerSpecExpandSchedNameWlc string = "wlc" - // VirtualServerSpecExpandSchedNameConnhash captures enum value "connhash" - VirtualServerSpecExpandSchedNameConnhash string = "connhash" + // VirtualServerSpecExpandSchedNameConhash captures enum value "conhash" + VirtualServerSpecExpandSchedNameConhash string = "conhash" ) // prop value enum diff --git a/tools/dpvs-agent/models/virtual_server_spec_tiny.go b/tools/dpvs-agent/models/virtual_server_spec_tiny.go index 3ebfd849c..e0c285584 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_tiny.go +++ b/tools/dpvs-agent/models/virtual_server_spec_tiny.go @@ -39,7 +39,7 @@ type VirtualServerSpecTiny struct { Match *MatchSpec `json:"Match,omitempty"` // sched name - // Enum: [rr wrr wlc connhash] + // Enum: [rr wrr wlc conhash] SchedName string `json:"SchedName,omitempty"` // sync proxy @@ -90,7 +90,7 @@ var virtualServerSpecTinyTypeSchedNamePropEnum []interface{} func init() { var res []string - if err := json.Unmarshal([]byte(`["rr","wrr","wlc","connhash"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["rr","wrr","wlc","conhash"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -109,8 +109,8 @@ const ( // VirtualServerSpecTinySchedNameWlc captures enum value "wlc" VirtualServerSpecTinySchedNameWlc string = "wlc" - // VirtualServerSpecTinySchedNameConnhash captures enum value "connhash" - VirtualServerSpecTinySchedNameConnhash string = "connhash" + // VirtualServerSpecTinySchedNameConhash captures enum value "conhash" + VirtualServerSpecTinySchedNameConhash string = "conhash" ) // prop value enum diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go index 797f664d2..24dc5f659 100644 --- a/tools/dpvs-agent/restapi/embedded_spec.go +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -1859,7 +1859,7 @@ func init() { "rr", "wrr", "wlc", - "connhash" + "conhash" ] }, "Stats": { @@ -1910,7 +1910,7 @@ func init() { "rr", "wrr", "wlc", - "connhash" + "conhash" ] }, "SyncProxy": { @@ -4200,7 +4200,7 @@ func init() { "rr", "wrr", "wlc", - "connhash" + "conhash" ] }, "Stats": { @@ -4251,7 +4251,7 @@ func init() { "rr", "wrr", "wlc", - "connhash" + "conhash" ] }, "SyncProxy": { From 0c6152e40b73af2fc369ecd1ae5721b6e0a40b3e Mon Sep 17 00:00:00 2001 From: you-looks-not-tasty <42596733+you-looks-not-tasty@users.noreply.github.com> Date: Tue, 15 Aug 2023 11:36:17 +0800 Subject: [PATCH 065/105] bugfix and fix spelling mistake (#12) dpvs-agent: fix synproxy spelling mistakes and correctify ipv6 laddr ip family problem for nat64 --- tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go | 4 +-- .../cmd/ipvs/put_vs_vip_port_laddr.go | 1 - tools/dpvs-agent/dpvs-agent-api.yaml | 4 +-- .../models/virtual_server_spec_expand.go | 28 ++++++++-------- .../models/virtual_server_spec_tiny.go | 4 +-- tools/dpvs-agent/pkg/ipc/types/getmodel.go | 4 +-- tools/dpvs-agent/pkg/ipc/types/laddr.go | 7 +++- .../dpvs-agent/pkg/ipc/types/virtualserver.go | 2 +- tools/dpvs-agent/restapi/embedded_spec.go | 32 +++++++++---------- .../device/put_device_name_nic_parameters.go | 4 +-- tools/dpvs-agent/restapi/server.go | 3 +- 11 files changed, 49 insertions(+), 44 deletions(-) diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go index 1b3fc1997..1ba7a08e3 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go @@ -69,8 +69,8 @@ func (h *putVsItem) Handle(params apiVs.PutVsVipPortParams) middleware.Responder vs.SetFlagsExpireQuiescent() } - if params.Spec.SyncProxy != nil && *params.Spec.SyncProxy { - vs.SetFlagsSyncProxy() + if params.Spec.SynProxy != nil && *params.Spec.SynProxy { + vs.SetFlagsSynProxy() } } diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go index d8765ba6d..36eb19e0d 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_laddr.go @@ -49,7 +49,6 @@ func (h *putVsLaddr) Handle(params apiVs.PutVsVipPortLaddrParams) middleware.Res lds := make([]*types.LocalAddrDetail, 1) lds[0] = types.NewLocalAddrDetail() - lds[0].SetAf(laddr.GetAf()) lds[0].SetAddr(params.Spec.Addr) lds[0].SetIfName(params.Spec.Device) diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml index ae92725ee..9d9f3a91e 100644 --- a/tools/dpvs-agent/dpvs-agent-api.yaml +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -497,7 +497,7 @@ definitions: format: "uint32" Flags: type: "string" - SyncProxy: + SynProxy: type: "string" enum: - "true" @@ -556,7 +556,7 @@ definitions: #Flags: # type: "integer" # format: "uint32" - SyncProxy: + SynProxy: type: "boolean" default: false ExpireQuiescent: diff --git a/tools/dpvs-agent/models/virtual_server_spec_expand.go b/tools/dpvs-agent/models/virtual_server_spec_expand.go index bf04aa918..88525c785 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_expand.go +++ b/tools/dpvs-agent/models/virtual_server_spec_expand.go @@ -71,9 +71,9 @@ type VirtualServerSpecExpand struct { // stats Stats *ServerStats `json:"Stats,omitempty"` - // sync proxy + // syn proxy // Enum: [true false] - SyncProxy string `json:"SyncProxy,omitempty"` + SynProxy string `json:"SynProxy,omitempty"` // timeout Timeout uint32 `json:"Timeout,omitempty"` @@ -107,7 +107,7 @@ func (m *VirtualServerSpecExpand) Validate(formats strfmt.Registry) error { res = append(res, err) } - if err := m.validateSyncProxy(formats); err != nil { + if err := m.validateSynProxy(formats); err != nil { res = append(res, err) } @@ -285,7 +285,7 @@ func (m *VirtualServerSpecExpand) validateStats(formats strfmt.Registry) error { return nil } -var virtualServerSpecExpandTypeSyncProxyPropEnum []interface{} +var virtualServerSpecExpandTypeSynProxyPropEnum []interface{} func init() { var res []string @@ -293,34 +293,34 @@ func init() { panic(err) } for _, v := range res { - virtualServerSpecExpandTypeSyncProxyPropEnum = append(virtualServerSpecExpandTypeSyncProxyPropEnum, v) + virtualServerSpecExpandTypeSynProxyPropEnum = append(virtualServerSpecExpandTypeSynProxyPropEnum, v) } } const ( - // VirtualServerSpecExpandSyncProxyTrue captures enum value "true" - VirtualServerSpecExpandSyncProxyTrue string = "true" + // VirtualServerSpecExpandSynProxyTrue captures enum value "true" + VirtualServerSpecExpandSynProxyTrue string = "true" - // VirtualServerSpecExpandSyncProxyFalse captures enum value "false" - VirtualServerSpecExpandSyncProxyFalse string = "false" + // VirtualServerSpecExpandSynProxyFalse captures enum value "false" + VirtualServerSpecExpandSynProxyFalse string = "false" ) // prop value enum -func (m *VirtualServerSpecExpand) validateSyncProxyEnum(path, location string, value string) error { - if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeSyncProxyPropEnum, true); err != nil { +func (m *VirtualServerSpecExpand) validateSynProxyEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeSynProxyPropEnum, true); err != nil { return err } return nil } -func (m *VirtualServerSpecExpand) validateSyncProxy(formats strfmt.Registry) error { - if swag.IsZero(m.SyncProxy) { // not required +func (m *VirtualServerSpecExpand) validateSynProxy(formats strfmt.Registry) error { + if swag.IsZero(m.SynProxy) { // not required return nil } // value enum - if err := m.validateSyncProxyEnum("SyncProxy", "body", m.SyncProxy); err != nil { + if err := m.validateSynProxyEnum("SynProxy", "body", m.SynProxy); err != nil { return err } diff --git a/tools/dpvs-agent/models/virtual_server_spec_tiny.go b/tools/dpvs-agent/models/virtual_server_spec_tiny.go index e0c285584..837040a94 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_tiny.go +++ b/tools/dpvs-agent/models/virtual_server_spec_tiny.go @@ -42,8 +42,8 @@ type VirtualServerSpecTiny struct { // Enum: [rr wrr wlc conhash] SchedName string `json:"SchedName,omitempty"` - // sync proxy - SyncProxy *bool `json:"SyncProxy,omitempty"` + // syn proxy + SynProxy *bool `json:"SynProxy,omitempty"` // timeout Timeout uint32 `json:"Timeout,omitempty"` diff --git a/tools/dpvs-agent/pkg/ipc/types/getmodel.go b/tools/dpvs-agent/pkg/ipc/types/getmodel.go index 7e3a1b392..a1d0e30f8 100644 --- a/tools/dpvs-agent/pkg/ipc/types/getmodel.go +++ b/tools/dpvs-agent/pkg/ipc/types/getmodel.go @@ -29,7 +29,7 @@ func (vs *VirtualServerSpec) GetModel() *models.VirtualServerSpecExpand { Port: vs.GetPort(), Proto: vs.GetProto(), Fwmark: vs.GetFwmark(), - SyncProxy: "false", + SynProxy: "false", ExpireQuiescent: "false", SchedName: vs.GetSchedName(), Timeout: vs.GetTimeout(), @@ -40,7 +40,7 @@ func (vs *VirtualServerSpec) GetModel() *models.VirtualServerSpecExpand { flags := "" if (vs.GetFlags() & DPVS_SVC_F_SYNPROXY) != 0 { - modelVs.SyncProxy = "true" + modelVs.SynProxy = "true" flags += "SynProxy|" } diff --git a/tools/dpvs-agent/pkg/ipc/types/laddr.go b/tools/dpvs-agent/pkg/ipc/types/laddr.go index ed26f5069..1a4272796 100644 --- a/tools/dpvs-agent/pkg/ipc/types/laddr.go +++ b/tools/dpvs-agent/pkg/ipc/types/laddr.go @@ -85,6 +85,7 @@ func (o *LocalAddrFront) GetAf() uint32 { func (o *LocalAddrFront) SetAf(af uint32) { o.af = af } + func (o *LocalAddrFront) SetAfByAddr(addr string) { i := strings.Index(addr, "/") if i != -1 { @@ -243,7 +244,7 @@ func (o *LocalAddrDetail) Dump(buf []byte) bool { return o.Copy(tmp) } -func (o *LocalAddrDetail) SetAf(af uint32) { +func (o *LocalAddrDetail) setAf(af uint32) { o.af = af } @@ -292,10 +293,14 @@ func (o *LocalAddrDetail) GetAddr() string { func (o *LocalAddrDetail) SetAddr(addr string) { if strings.Contains(addr, ":") { copy(o.addr[:], net.ParseIP(addr)) + // o.af = unix.AF_INET6 + o.setAf(unix.AF_INET6) } else { buf := new(bytes.Buffer) binary.Write(buf, binary.LittleEndian, net.ParseIP(addr)) copy(o.addr[:], buf.Bytes()[12:]) + // o.af = unix.AF_INET + o.setAf(unix.AF_INET) } } diff --git a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go index a3e1c6456..f2a397fec 100644 --- a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go @@ -265,7 +265,7 @@ func (vs *VirtualServerSpec) GetFwmark() uint32 { return vs.fwmark } -func (vs *VirtualServerSpec) SetFlagsSyncProxy() { +func (vs *VirtualServerSpec) SetFlagsSynProxy() { vs.setFlags(DPVS_SVC_F_SYNPROXY) } diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go index 24dc5f659..7eaf606be 100644 --- a/tools/dpvs-agent/restapi/embedded_spec.go +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -1865,7 +1865,7 @@ func init() { "Stats": { "$ref": "#/definitions/ServerStats" }, - "SyncProxy": { + "SynProxy": { "type": "string", "enum": [ "true", @@ -1913,7 +1913,7 @@ func init() { "conhash" ] }, - "SyncProxy": { + "SynProxy": { "type": "boolean", "default": false }, @@ -1961,8 +1961,8 @@ func init() { "forward2kni": { "enum": [ "unset", - "on", - "off" + true, + false ], "type": "string", "default": "unset", @@ -1996,8 +1996,8 @@ func init() { "promisc": { "enum": [ "unset", - "on", - "off" + true, + false ], "type": "string", "default": "unset", @@ -2526,8 +2526,8 @@ func init() { { "enum": [ "unset", - "on", - "off" + true, + false ], "type": "string", "default": "unset", @@ -2548,8 +2548,8 @@ func init() { { "enum": [ "unset", - "on", - "off" + true, + false ], "type": "string", "default": "unset", @@ -4206,7 +4206,7 @@ func init() { "Stats": { "$ref": "#/definitions/ServerStats" }, - "SyncProxy": { + "SynProxy": { "type": "string", "enum": [ "true", @@ -4254,7 +4254,7 @@ func init() { "conhash" ] }, - "SyncProxy": { + "SynProxy": { "type": "boolean", "default": false }, @@ -4302,8 +4302,8 @@ func init() { "forward2kni": { "enum": [ "unset", - "on", - "off" + true, + false ], "type": "string", "default": "unset", @@ -4337,8 +4337,8 @@ func init() { "promisc": { "enum": [ "unset", - "on", - "off" + true, + false ], "type": "string", "default": "unset", diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go index a8cd915e3..cf56efd5f 100644 --- a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go @@ -130,7 +130,7 @@ func (o *PutDeviceNameNicParams) bindForward2Kni(rawData []string, hasKey bool, // validateForward2Kni carries on validations for parameter Forward2Kni func (o *PutDeviceNameNicParams) validateForward2Kni(formats strfmt.Registry) error { - if err := validate.EnumCase("forward2Kni", "query", *o.Forward2Kni, []interface{}{"unset", "on", "off"}, true); err != nil { + if err := validate.EnumCase("forward2Kni", "query", *o.Forward2Kni, []interface{}{"unset", true, false}, true); err != nil { return err } @@ -210,7 +210,7 @@ func (o *PutDeviceNameNicParams) bindPromisc(rawData []string, hasKey bool, form // validatePromisc carries on validations for parameter Promisc func (o *PutDeviceNameNicParams) validatePromisc(formats strfmt.Registry) error { - if err := validate.EnumCase("promisc", "query", *o.Promisc, []interface{}{"unset", "on", "off"}, true); err != nil { + if err := validate.EnumCase("promisc", "query", *o.Promisc, []interface{}{"unset", true, false}, true); err != nil { return err } diff --git a/tools/dpvs-agent/restapi/server.go b/tools/dpvs-agent/restapi/server.go index 2c8225403..c5ede575b 100644 --- a/tools/dpvs-agent/restapi/server.go +++ b/tools/dpvs-agent/restapi/server.go @@ -8,6 +8,7 @@ import ( "crypto/x509" "errors" "fmt" + "io/ioutil" "log" "net" "net/http" @@ -273,7 +274,7 @@ func (s *Server) Serve() (err error) { if s.TLSCACertificate != "" { // include specified CA certificate - caCert, caCertErr := os.ReadFile(string(s.TLSCACertificate)) + caCert, caCertErr := ioutil.ReadFile(string(s.TLSCACertificate)) if caCertErr != nil { return caCertErr } From b1cdb7c96af00c74366613baedd5d8984733ab04 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 15 Aug 2023 14:50:59 +0800 Subject: [PATCH 066/105] dpvs-agent: add swagger version requirement in Makefile Signed-off-by: ywc689 --- tools/dpvs-agent/Makefile | 9 ++++--- tools/dpvs-agent/restapi/embedded_spec.go | 24 +++++++++---------- .../device/put_device_name_nic_parameters.go | 4 ++-- tools/dpvs-agent/restapi/server.go | 3 +-- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/tools/dpvs-agent/Makefile b/tools/dpvs-agent/Makefile index e6d192824..cccd6ebfc 100644 --- a/tools/dpvs-agent/Makefile +++ b/tools/dpvs-agent/Makefile @@ -5,6 +5,9 @@ export INSDIR OPENAPISPEC = dpvs-agent-api.yaml +SWAGGER_REQUIRED_VERSION := v0.30.4 +SWAGGER_VERSION := $(shell swagger version 2>/dev/null | awk '/^version:/{print $$2}') + all: for i in $(SUBDIRS); do $(MAKE) -C $$i || exit 1; done @@ -19,15 +22,15 @@ uninstall: for i in $(SUBDIRS); do $(MAKE) -C $$i uninstall || exit 1; done openapi: $(OPENAPISPEC) -ifeq ($(shell swagger version),) - $(error "golang `swagger` command not found. You can install it with `go get github.com/go-swagger/go-swagger@v0.30.4`") +ifneq ($(SWAGGER_VERSION),$(SWAGGER_REQUIRED_VERSION)) + $(error Golang `swagger` $(SWAGGER_REQUIRED_VERSION) is not found. You can install it with 'go get github.com/go-swagger/go-swagger@$(SWAGGER_REQUIRED_VERSION)' or download it from 'https://github.com/go-swagger/go-swagger/releases/download/$(SWAGGER_REQUIRED_VERSION)') endif swagger generate server -A dpvs-agent -f $< git checkout cmd/dpvs-agent-server/main.go license: ifeq ($(shell addlicense 2>&1|grep Usage),) - $(error "`addlicense` command not found. You can install it with `go install github.com/google/addlicense`") + $(error `addlicense` command not found. You can install it with 'go install github.com/google/addlicense') endif @addlicense -check -c "IQiYi Inc." -l apache -ignore dpvs/** . || /bin/true -addlicense -f license.txt -v . diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go index 7eaf606be..f1052021b 100644 --- a/tools/dpvs-agent/restapi/embedded_spec.go +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -1961,8 +1961,8 @@ func init() { "forward2kni": { "enum": [ "unset", - true, - false + "on", + "off" ], "type": "string", "default": "unset", @@ -1996,8 +1996,8 @@ func init() { "promisc": { "enum": [ "unset", - true, - false + "on", + "off" ], "type": "string", "default": "unset", @@ -2526,8 +2526,8 @@ func init() { { "enum": [ "unset", - true, - false + "on", + "off" ], "type": "string", "default": "unset", @@ -2548,8 +2548,8 @@ func init() { { "enum": [ "unset", - true, - false + "on", + "off" ], "type": "string", "default": "unset", @@ -4302,8 +4302,8 @@ func init() { "forward2kni": { "enum": [ "unset", - true, - false + "on", + "off" ], "type": "string", "default": "unset", @@ -4337,8 +4337,8 @@ func init() { "promisc": { "enum": [ "unset", - true, - false + "on", + "off" ], "type": "string", "default": "unset", diff --git a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go index cf56efd5f..a8cd915e3 100644 --- a/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go +++ b/tools/dpvs-agent/restapi/operations/device/put_device_name_nic_parameters.go @@ -130,7 +130,7 @@ func (o *PutDeviceNameNicParams) bindForward2Kni(rawData []string, hasKey bool, // validateForward2Kni carries on validations for parameter Forward2Kni func (o *PutDeviceNameNicParams) validateForward2Kni(formats strfmt.Registry) error { - if err := validate.EnumCase("forward2Kni", "query", *o.Forward2Kni, []interface{}{"unset", true, false}, true); err != nil { + if err := validate.EnumCase("forward2Kni", "query", *o.Forward2Kni, []interface{}{"unset", "on", "off"}, true); err != nil { return err } @@ -210,7 +210,7 @@ func (o *PutDeviceNameNicParams) bindPromisc(rawData []string, hasKey bool, form // validatePromisc carries on validations for parameter Promisc func (o *PutDeviceNameNicParams) validatePromisc(formats strfmt.Registry) error { - if err := validate.EnumCase("promisc", "query", *o.Promisc, []interface{}{"unset", true, false}, true); err != nil { + if err := validate.EnumCase("promisc", "query", *o.Promisc, []interface{}{"unset", "on", "off"}, true); err != nil { return err } diff --git a/tools/dpvs-agent/restapi/server.go b/tools/dpvs-agent/restapi/server.go index c5ede575b..2c8225403 100644 --- a/tools/dpvs-agent/restapi/server.go +++ b/tools/dpvs-agent/restapi/server.go @@ -8,7 +8,6 @@ import ( "crypto/x509" "errors" "fmt" - "io/ioutil" "log" "net" "net/http" @@ -274,7 +273,7 @@ func (s *Server) Serve() (err error) { if s.TLSCACertificate != "" { // include specified CA certificate - caCert, caCertErr := ioutil.ReadFile(string(s.TLSCACertificate)) + caCert, caCertErr := os.ReadFile(string(s.TLSCACertificate)) if caCertErr != nil { return caCertErr } From 5ff809ec06c9bb243aa0c7a062e9814b50a0163e Mon Sep 17 00:00:00 2001 From: roykingz Date: Mon, 21 Aug 2023 16:36:46 +0800 Subject: [PATCH 067/105] dpvs: fix cfgfile parser malloc problem --- src/parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser.c b/src/parser.c index 24c800ec8..6ac4313e2 100644 --- a/src/parser.c +++ b/src/parser.c @@ -404,8 +404,8 @@ void *set_value(vector_t tokens) strncat(alloc, str, strlen(str)); } } else { - alloc = MALLOC(sizeof(char *) * (size + 1)); - memcpy(alloc, str, size); + alloc = MALLOC(sizeof(char) * (size + 1)); + memcpy(alloc, str, size + 1); } return alloc; From 279a549fe618f342688ccea0cee8f42a86e96a3f Mon Sep 17 00:00:00 2001 From: roykingz Date: Mon, 21 Aug 2023 16:57:33 +0800 Subject: [PATCH 068/105] ipvsadm: fix icmpv6 option and improve help message --- tools/ipvsadm/ipvsadm.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index 0c29b36b4..89ebc3d8e 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -665,6 +665,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, case 't': case 'u': case 'q': + case '1': set_option(options, OPT_SERVICE); if (c == 't') { ce->dpvs_svc.proto = IPPROTO_TCP; @@ -1721,7 +1722,10 @@ static void usage_exit(const char *program, const int exit_status) " --dest-check CHECK_CONF config health check, inhibit scheduling to failed backends\n" " CHECK_CONF:=disable|default(passive)|DETAIL(passive)|tcp|udp|ping, DETAIL:=UPDOWN|DOWNONLY\n" " UPDOWN:=down_retry,up_confirm,down_wait,inhibit_min-inhibit_max, for example, the default is 1,1,3s,5-3600s\n" - " DOWNONLY:=down_retry,down_wait, for example, --dest-check=1,3s\n", + " DOWNONLY:=down_retry,down_wait, for example, --dest-check=1,3s\n" + " --laddr -z local-ip local IP\n" + " --blklst -k blacklist-ip blacklist IP for specific service\n" + " --whtlst -2 whitelist-ip whitelist IP for specific service\n", DEF_SCHED); exit(exit_status); From d3279f08ea79ab1a3c453f8189d12dc8b0c47c05 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 24 Aug 2023 17:41:09 +0800 Subject: [PATCH 069/105] add a Dockerfile for DPVS Signed-off-by: ywc689 --- Dockerfile | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..0b47109a1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,164 @@ +# Important Notes: +# +# Two local dependencies should be ready before build container image with the Dockerfile. +# - MLNX_OFED: Please download it from the official website +# `https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/` +# to the local fileserver indicated by the ARG `MLNX_OFED`. +# We cannot download it in the Dockerfile automatically for the authentication +# restriction of the website. +# - RPM_PKGCONFIG: The `pkg-config` tool of v0.29.2 is required to build DPVS. +# However, the default installation version on centos7 is v0.27.1. You need to +# download or build the v0.29.2 RPM for pkgconfig and put it to the the local +# fileserver indicated by the ARG `RPM_PKGCONFIG`. Alternatively, building a +# binary `pkg-config` and installing it in the local binary path is also ok. +# +# No kernel dependencies of dpdk/dpvs or network driver are built and installed. +# You should ensure the host the server has installed the drivers before running +# a dpvs container on it. +# + +ARG BASE_IMAGE=centos:centos7.9.2009 + +###### `builder` stage builds the docker image for DPVS devel environments ###### +FROM $BASE_IMAGE as builder + +# replace it with the address of your own file server +ARG FILE_SERVER=127.0.0.1 + +LABEL maintainer="IQiYi/QLB team" +LABEL email="iig_cloud_qlb@qiyi.com" +LABEL project="https://github.com/iqiyi/dpvs" +LABEL image_maker="docker build --target builder -t github.com/iqiyi/dpvs-builder:{version} ." + +# download the tarball from https://network.nvidia.com/products/infiniband-drivers/linux/mlnx_ofed/ +# FIXME: remove thefile server dependency +ARG MLNX_OFED=http://$FILE_SERVER/deploy/MLNX_OFED/MLNX_OFED_LINUX-5.6-2.0.9.0-rhel7.9-x86_64.tgz + +# the pkgconfig default installed version is 0.27.1 on centos7, update it to 0.29.2 +# the 0.29.2 rpm is built from source based on the rpm spec file of 0.27.1. +# FIXME: remove thefile server dependency +ARG RPM_PKGCONFIG=http://$FILE_SERVER/deploy/rpms/centos7/pkgconfig-0.29.2-1.el7.x86_64.rpm + +# golang install files +ARG GO_PACKAGE=https://go.dev/dl/go1.20.4.linux-amd64.tar.gz + +# go-swagger binary +ARG GO_SWAGGER_BIN=https://github.com/go-swagger/go-swagger/releases/download/v0.30.4/swagger_darwin_amd64 + +ENV PKG_CONFIG_PATH=/dpvs/dpdk/dpdklib/lib64/pkgconfig +ENV PATH=$PATH:/usr/local/go/bin + +COPY . /dpvs/ +WORKDIR /dpvs + +RUN set -x \ + && yum install -y epel-release \ + && yum install -y tcl tk iproute wget vim patch meson python36 emacs-filesystem \ + gcc make lsof libnl3 ethtool libpcap pciutils numactl-libs numactl-devel \ + openssl-devel automake popt-devel ninja-build meson \ + && mkdir deps \ + && rpm -Uvh $RPM_PKGCONFIG \ + && wget $GO_PACKAGE -P deps \ + && tar -C /usr/local -xzf deps/go*.gz \ + && curl -L -o /usr/local/bin/swagger $GO_SWAGGER_BIN \ + && chmod 544 /usr/local/bin/swagger \ + && wget $MLNX_OFED -P deps \ + && tar xf deps/$(basename $MLNX_OFED) -C deps \ + && pushd deps/$(basename $MLNX_OFED | sed 's/.tgz//') \ + && ./mlnxofedinstall --user-space-only --upstream-libs \ + --dpdk --without-fw-update --force \ + && popd \ + && sed -i 's/Denable_kmods=true/Denable_kmods=false/' scripts/dpdk-build.sh \ + && ./scripts/dpdk-build.sh \ + && sed -i 's/CONFIG_DPVS_AGENT=n/CONFIG_DPVS_AGENT=y/' config.mk \ + && make -j && make install \ + && rm -rf deps && yum clean all + +RUN set -x \ + && mkdir libraries \ + && ldd bin/dpvs | grep "=> /" | awk '{print $3}' | xargs -I '{}' cp '{}' libraries \ + && ldd bin/ipvsadm | grep "=> /" | awk '{print $3}' | xargs -I '{}' cp '{}' libraries \ + && ldd bin/dpip | grep "=> /" | awk '{print $3}' | xargs -I '{}' cp '{}' libraries \ + && ldd bin/keepalived | grep "=> /" | awk '{print $3}' | xargs -I '{}' cp '{}' libraries + +ENTRYPOINT ["/bin/bash"] + + +###### `runner` stage builds the docker image for DPVS product environments ###### +# +# docker run --name dpvs \ +# -d --rm --privileged --network host \ +# -v /dev:/dev \ +# -v /sys:/sys \ +# -v /lib/modules:/lib/modules \ +# -v {dpvs-directory}:/dpvs \ +# github.com/iqiyi/dpvs:{version} \ +# -c /dpvs/dpvs.conf -p /dpvs/dpvs.pid -x /dpvs/dpvs.ipc \ +# -- -a {nic-pci-bus-id} +# +# docker run --name ipvsadm \ +# --rm --network none \ +# -v {dpvs-directory}:/dpvs \ +# -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ +# --entrypoint=/usr/bin/ipvsadm \ +# github.com/iqiyi/dpvs:{version} \ +# ... +# +# docker run --name dpip \ +# --rm --network none \ +# -v {dpvs-directory}:/dpvs \ +# -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ +# --entrypoint=/usr/bin/dpip \ +# github.com/iqiyi/dpvs:{version} \ +# ... +# +# docker run --name keepalived \ +# -d --rm --privileged --network host \ +# --cap-add=NET_ADMIN --cap-add=NET_BROADCAST --cap-add=NET_RAW \ +# -v {dpvs-directory}:/dpvs \ +# -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ +# --entrypoint=/usr/bin/keepalived github.com/iqiyi/dpvs:{version} \ +# -D -n -f /dpvs/keepalived.conf \ +# --log-console --log-facility=6 \ +# --pid=/dpvs/keepalived.pid \ +# --vrrp_pid=/dpvs/vrrp.pid \ +# --checkers_pid=/dpvs/checkers.pid +# +# docker run --name dpvs-agent \ +# -d --rm --network host \ +# -v {dpvs-directory}:/dpvs \ +# --entrypoint=/usr/bin/dpvs-agent \ +# github.com/iqiyi/dpvs:{version} \ +# --log-dir=/dpvs/logs/dpvs-agent \ +# --ipc-sockopt-path=/dpvs/dpvs.ipc\ +# --host=0.0.0.0 --port=6601 +# +# docker run --name healthcheck \ +# -d --rm --network host \ +# -v {dpvs-directory}:/dpvs \ +# --entrypoint=/usr/bin/healthcheck \ +# github.com/iqiyi/dpvs:{version} \ +# -log_dir=/dpvs/logs/healthcheck \ +# -lb_iface_addr=localhost:6601 +# +FROM $BASE_IMAGE as runner + +LABEL image_maker="docker build --target runner -t github.com/iqiyi/dpvs:{version} ." + +RUN set -x \ + && yum install -y iproute wget ncat nmap tcpdump socat \ + && yum clean all + +COPY --from=builder /dpvs/bin/ /usr/bin +COPY --from=builder /dpvs/libraries /usr/lib64 + +# Other available entrypoint are: +# * /usr/bin/keepalived +# * /usr/bin/dpvs-agent +# * /usr/bin/healthcheck +# * /usr/bin/ipvsadm +# * /usr/bin/dpip +# * /bin/bash +# use `docker run --entrypoint ...` to override the default entrypoint. + +ENTRYPOINT ["/usr/bin/dpvs"] From a568906e7b9f42ab61ba5128615accdbbd804fcd Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 29 Aug 2023 12:50:05 +0800 Subject: [PATCH 070/105] add a doc for running dpvs in container Signed-off-by: ywc689 --- Dockerfile | 21 +- doc/containerized/README.md | 353 ++++++++++++++++++++++++++++++ doc/containerized/dpvs.conf | 271 +++++++++++++++++++++++ doc/containerized/keepalived.conf | 122 +++++++++++ doc/containerized/run.sh | 116 ++++++++++ 5 files changed, 874 insertions(+), 9 deletions(-) create mode 100644 doc/containerized/README.md create mode 100644 doc/containerized/dpvs.conf create mode 100644 doc/containerized/keepalived.conf create mode 100755 doc/containerized/run.sh diff --git a/Dockerfile b/Dockerfile index 0b47109a1..be85ec8f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,13 +8,13 @@ # restriction of the website. # - RPM_PKGCONFIG: The `pkg-config` tool of v0.29.2 is required to build DPVS. # However, the default installation version on centos7 is v0.27.1. You need to -# download or build the v0.29.2 RPM for pkgconfig and put it to the the local +# download it or build the v0.29.2 RPM from source and put it to the the local # fileserver indicated by the ARG `RPM_PKGCONFIG`. Alternatively, building a # binary `pkg-config` and installing it in the local binary path is also ok. # # No kernel dependencies of dpdk/dpvs or network driver are built and installed. -# You should ensure the host the server has installed the drivers before running -# a dpvs container on it. +# You should ensure the host has installed the drivers before running a dpvs +# container on it. # ARG BASE_IMAGE=centos:centos7.9.2009 @@ -36,7 +36,7 @@ ARG MLNX_OFED=http://$FILE_SERVER/deploy/MLNX_OFED/MLNX_OFED_LINUX-5.6-2.0.9.0-r # the pkgconfig default installed version is 0.27.1 on centos7, update it to 0.29.2 # the 0.29.2 rpm is built from source based on the rpm spec file of 0.27.1. -# FIXME: remove thefile server dependency +# FIXME: remove the file server dependency ARG RPM_PKGCONFIG=http://$FILE_SERVER/deploy/rpms/centos7/pkgconfig-0.29.2-1.el7.x86_64.rpm # golang install files @@ -55,7 +55,7 @@ RUN set -x \ && yum install -y epel-release \ && yum install -y tcl tk iproute wget vim patch meson python36 emacs-filesystem \ gcc make lsof libnl3 ethtool libpcap pciutils numactl-libs numactl-devel \ - openssl-devel automake popt-devel ninja-build meson \ + openssl-devel automake popt-devel ninja-build meson libnl3-devel cgdb git \ && mkdir deps \ && rpm -Uvh $RPM_PKGCONFIG \ && wget $GO_PACKAGE -P deps \ @@ -87,7 +87,7 @@ ENTRYPOINT ["/bin/bash"] ###### `runner` stage builds the docker image for DPVS product environments ###### # # docker run --name dpvs \ -# -d --rm --privileged --network host \ +# -d --privileged --network host \ # -v /dev:/dev \ # -v /sys:/sys \ # -v /lib/modules:/lib/modules \ @@ -113,7 +113,7 @@ ENTRYPOINT ["/bin/bash"] # ... # # docker run --name keepalived \ -# -d --rm --privileged --network host \ +# -d --privileged --network host \ # --cap-add=NET_ADMIN --cap-add=NET_BROADCAST --cap-add=NET_RAW \ # -v {dpvs-directory}:/dpvs \ # -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ @@ -125,7 +125,7 @@ ENTRYPOINT ["/bin/bash"] # --checkers_pid=/dpvs/checkers.pid # # docker run --name dpvs-agent \ -# -d --rm --network host \ +# -d --network host \ # -v {dpvs-directory}:/dpvs \ # --entrypoint=/usr/bin/dpvs-agent \ # github.com/iqiyi/dpvs:{version} \ @@ -134,7 +134,7 @@ ENTRYPOINT ["/bin/bash"] # --host=0.0.0.0 --port=6601 # # docker run --name healthcheck \ -# -d --rm --network host \ +# -d --network host \ # -v {dpvs-directory}:/dpvs \ # --entrypoint=/usr/bin/healthcheck \ # github.com/iqiyi/dpvs:{version} \ @@ -143,6 +143,9 @@ ENTRYPOINT ["/bin/bash"] # FROM $BASE_IMAGE as runner +LABEL maintainer="IQiYi/QLB team" +LABEL email="iig_cloud_qlb@qiyi.com" +LABEL project="https://github.com/iqiyi/dpvs" LABEL image_maker="docker build --target runner -t github.com/iqiyi/dpvs:{version} ." RUN set -x \ diff --git a/doc/containerized/README.md b/doc/containerized/README.md new file mode 100644 index 000000000..187b37e68 --- /dev/null +++ b/doc/containerized/README.md @@ -0,0 +1,353 @@ +**Run DPVS in Container** +------ + +The document presents a solution to run DPVS and its related tools in docker containers. It's a step-by-step tutorial that breaks down the whole topic into serveral small parts shown as below. + +* Build DPVS container images with Dockerfile. +* Run DPVS in container. +* Configure services with keepalived or dpvs-agent, which also run in containers. +* Set up devel environments using DPVS container image. + +We run a container for each DPVS component with the docker tool. Container orchestrations like Kubernetes or Docker Swarm are not used. The containers use host network and loose restrictions in runtime capability and volume mapping. So the solution is pretty experimental, and extral efforts are required if you want to make it productive. + +# 1. Build DPVS Container Image + +DPVS provides a [Dockerfile](../../Dockerfile) that employs the `centos:centos7.9.2009` as base image. It resolves all dependencies except the pkgconfig RPM and Mellanox OFED tarball to compile DPDK/DPVS from source codes and build DPVS container images. Refer to the comments in the Dockerfile to resolve the two broken dependencies manually, and after that, run the command + +```sh +docker build -t github.com/iqiyi/dpvs:{version} . +``` +in the directory of Dockerfile to build DPVS docker image, where `{version}` is the DPVS version, v1.9.5 for example. + +# 2. Install Host Requirements + +### 2.1. Install kernel modules on the host and bind NIC drivers + +All DPVS required kernel modules should be installed on the host, including uio and NIC specific dpdk drivers. Notes that toa and uoa kernel modules are used on backend servers, and aren't required on the DPVS host. Bind NICs to the required kernel drivers if needed, for example, use the following commands to bind the intel ixgbe NIC at `0000:01:00.1` with `uio_pci_generic` driver. + +```sh +modprobe uio +modprobe uio_pci_generic +dpdk-devbind -b uio_pci_generic 0000:01:00.1 +``` + +### 2.2. Configure hugepage memory + +We should reserve hugepages for DPVS on the host. For example, the command below reserves 16GB hugepage memory of 2MB size on each numa node of the host. + +```sh +echo 8192 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages +echo 8192 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages +``` +Refer to [Quick Start](../../README.md) doc for more details. + +### 2.3. Prepare a work directory + +The work directory contains config files, running files, and log files for DPVS. The directory is mapped into multiple containers, such as dpvs, keepalived, and dpvs-agent, simplifying data sharing across containers. In this tutorial, we create `/var/run/dpvs/` as the work directory. + +```sh +mkdir -p /var/run/dpvs +mkdir -p /var/run/dpvs/logs/dpvs-agent +mkdir -p /var/run/dpvs/logs/healthcheck +``` + +# 3. Run DPVS in Container + +### 3.1 Start a DPVS container + +Firstly, prepare a dpvs config file and place it in the work directory `/var/run/dpvs/dpvs.conf`. Refer to [dpvs sample configs](../../conf) to customize your config file. Then start dpvs container with the docker command below. + +```sh +docker run --name dpvs \ + -d --privileged --network host \ + -v /dev:/dev \ + -v /sys:/sys \ + -v /lib/modules:/lib/modules \ + -v /var/run/dpvs:/dpvs \ + github.com/iqiyi/dpvs:v1.9.5 \ + -c /dpvs/dpvs.conf -p /dpvs/dpvs.pid -x /dpvs/dpvs.ipc \ + -- -a 0000:01:00.1 +``` +It starts a container named `dpvs` in the host network namespace on a single NIC port, and maps host directories `/dev`, `/sys`, `/lib/modules` and the work directory into the container. + +Finally, confirm that the dpvs container is running in the background. + +```sh +[dpvs]# docker ps -f name=dpvs$ +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +f71c30c6d8a1 github.com/iqiyi/dpvs:v1.9.5 "/usr/bin/dpvs -c /d…" 2 seconds ago Up 1 second dpvs +``` + +### 3.2 Use dpip/ipvsadm tools in DPVS image + +Although discouraged, we can also execute the `dpip` and `ipvsadm` command in container. + +```sh +docker run --name dpip \ + --rm --network none \ + -v /var/run/dpvs:/dpvs \ + -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ + --entrypoint=/usr/bin/dpip \ + github.com/iqiyi/dpvs:v1.9.5 \ + ... +docker run --name ipvsadm \ + --rm --network none \ + -v /var/run/dpvs:/dpvs \ + -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ + --entrypoint=/usr/bin/ipvsadm \ + github.com/iqiyi/dpvs:v1.9.5 \ + ... +``` + +For simplification, create the aliases, + +```sh +alias dpip='docker run --name dpip --rm --network none -v /var/run/dpvs:/dpvs -e DPVS_IPC_FILE=/dpvs/dpvs.ipc --entrypoint=/usr/bin/dpip github.com/iqiyi/dpvs:v1.9.5' +alias ipvsadm='docker run --name ipvsadm --rm --network none -v /var/run/dpvs:/dpvs -e DPVS_IPC_FILE=/dpvs/dpvs.ipc --entrypoint=/usr/bin/ipvsadm github.com/iqiyi/dpvs:v1.9.5' +``` +and then you can use the containerized `dpip` and `ipvsadm` commands the same way as using the binaries directly. However, the containerized commands are costy and slow, so it's advised use the binaries directly in the productive environments. + +### 3.3 Setup the DPVS container network + +Before running test services, we should configure the host network for both DPVS and KNI devices. The tests run in layer2 network of 192.168.88.0/24 of vlan 102, which can be configured with the aliased `dpip` and linux `ip` commands. + +```sh +dpip vlan add dpdk0.102 link dpdk0 id 102 +dpip addr add 192.168.88.28/24 dev dpdk0.102 +dpip addr add 2001::28/64 dev dpdk0.102 +ip addr add 192.168.88.28/24 dev dpdk0.102.kni +ip addr add 2001::28/64 dev dpdk0.102.kni +ip link set dpdk0.102.kni up +``` +Alternatively, the goal can be also accomplished by HTTP APIs if you are using dpvs-agent. API is more suitable to integrate DPVS into your own service management platform. Refer to the next sector for how to run dpvs-agent in container. The following commands use `curl` to invoke the dpvs-agent APIs, and are equivalent to the `dpip` and `ip` commands listed above. + +```sh +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/vlan" -H "Content-type:application/json" -d "{\"device\":\"dpdk0\", \"id\":\"102\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.28/24\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"2001::28/64\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.28/24\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"2001::28/64\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102.kni/netlink" +``` + +### 3.4 Deploy services in the DPVS container + +There are three ways to deloy services into DPVS: ipvsadm, keepalived, and dpvs-agent. `ipvsadm` is a command line tool, `keepalived` uses config files, and `dpvs-agent` provides a set of HTTP API. + +* **Deploy service with `ipvsadm`** +You can either use the aliased `ipvsadm` in DPVS container image, or deploy it in the host. To deploy services with `ipvsadm`, there are no differences from the corresponding case of non-containerized DPVS. So we are not going to elaborate on it. Refer to [Quick Start](../../README.md) for details. + +* **Deploy service with `keepalived`** + +In container, the keepalived must be run in foreground, privileged mode, and the same network (i.e. host network) as the dpvs container. Extra network capabilities such as NET_ADMIN, NET_BROADCAST and NET_RAW are required. + +```sh +docker run --name keepalived \ + -d --privileged --network host \ + --cap-add=NET_ADMIN --cap-add=NET_BROADCAST --cap-add=NET_RAW \ + -v /var/run/dpvs:/dpvs \ + -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ + --entrypoint=/usr/bin/keepalived github.com/iqiyi/dpvs:v1.9.5 \ + -D -n -f /dpvs/keepalived.conf \ + --log-console --log-facility=6 \ + --pid=/dpvs/keepalived.pid \ + --vrrp_pid=/dpvs/vrrp.pid \ + --checkers_pid=/dpvs/checkers.pid +``` +The keepalived config file [keepalived.conf](./keepalived.conf) should be placed in the work directory beforehand. The config file contains two fullnat test services, one is pure IPv4, the other one is NAT64. Inspect the keepalived container and ensure it's running now. + +```sh +[dpvs]# docker ps -f name=keepalived +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +f52f4b1f4625 github.com/iqiyi/dpvs:v1.9.5 "/usr/bin/keepalived…" About a minute ago Up About a minute keepalived +``` +Check the serivces deployed by keepalived. + +```sh +[dpvs]# ipvsadm -ln +IP Virtual Server version 1.9.5 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.88.1:80 rr conn-timeout 60 + -> 192.168.88.30:80 FullNat 100 0 37 + -> 192.168.88.130:80 FullNat 100 0 34 +TCP [2001::1]:80 conhash sip + -> 192.168.88.30:80 FullNat 100 0 0 + -> 192.168.88.30:8080 FullNat 100 0 0 + -> 192.168.88.130:8080 FullNat 100 0 3 +``` + +* **Deploy service with `dpvs-agent`** + +The following docker command starts dpvs-agent in container on host network port 6601. NET_ADMIN capability is required to configure IPs on KNI device. + +```sh +docker run --name dpvs-agent \ + --cap-add=NET_ADMIN \ + -d --network host \ + -v /var/run/dpvs:/dpvs \ + --entrypoint=/usr/bin/dpvs-agent \ + github.com/iqiyi/dpvs:v1.9.5 \ + --log-dir=/dpvs/logs/dpvs-agent \ + --ipc-sockopt-path=/dpvs/dpvs.ipc\ + --host=0.0.0.0 --port=6601 +``` + +Verify the dpvs-agent container is running, + +```sh +[dpvs]# docker ps -f name=dpvs-agent +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +9b752bc7250f github.com/iqiyi/dpvs:v1.9.5 "/usr/bin/dpvs-agent…" 2 seconds ago Up 1 second dpvs-agent +``` +then deploy a test service with dpvs-agent API, + +```sh +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp" -H "Content-type:application/json" -d "{\"SchedName\":\"wrr\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"2001::2\"}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.88.241\"}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.88.242\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.241\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.242\"}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"192.168.88.30\", \"port\":80, \"weight\":100}]}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"192.168.88.130\", \"port\":8080, \"weight\":100}]}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"10.1.1.1\", \"port\":80, \"weight\":100}]}" +``` + +and check the test service we deployed just now. + +```sh +[dpvs]# ipvsadm -ln -t [2001::2]:80 +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP [2001::2]:80 wrr + -> 192.168.88.30:80 FullNat 100 0 0 + -> 192.168.88.130:8080 FullNat 100 0 1 + -> 10.1.1.1:80 FullNat 100 0 7 +[dpvs]# ipvsadm -G -t [2001::2]:80 +VIP:VPORT TOTAL SNAT_IP CONFLICTS CONNS +[2001::2]:80 2 + 192.168.88.241 0 5 + 192.168.88.242 0 6 +``` + +Finally, start the healthcheck service for dpvs-agent, which also runs in container. + +```sh +docker run --name healthcheck \ + -d --network host \ + -v /var/run/dpvs:/dpvs \ + --entrypoint=/usr/bin/healthcheck \ + github.com/iqiyi/dpvs:v1.9.5 \ + -log_dir=/dpvs/logs/healthcheck \ + -lb_iface_addr=localhost:6601 +``` +Check the test service again, + +```sh +[dpvs]# ipvsadm -ln -t [2001::2]:80 +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP [2001::2]:80 wrr + -> 192.168.88.30:80 FullNat 100 0 1 + -> 192.168.88.130:8080 FullNat 100 0 1 + -> 10.1.1.1:80 FullNat 0 0 6 inhibited +``` +then we find that the invalid backend `10.1.1.1:80` is removed from the service successfully. + +**Summury** + +Now let's have a look at all the containerized process and test services we've deployed. + +```sh +[dpvs]# docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +e43d8ec1700d github.com/iqiyi/dpvs:v1.9.5 "/usr/bin/healthchec…" 9 minutes ago Up 9 minutes healthcheck +9b752bc7250f github.com/iqiyi/dpvs:v1.9.5 "/usr/bin/dpvs-agent…" 19 minutes ago Up 19 minutes dpvs-agent +f52f4b1f4625 github.com/iqiyi/dpvs:v1.9.5 "/usr/bin/keepalived…" 36 minutes ago Up 36 minutes keepalived +f71c30c6d8a1 github.com/iqiyi/dpvs:v1.9.5 "/usr/bin/dpvs -c /d…" 15 hours ago Up 15 hours dpvs + +[dpvs]# ipvsadm -ln +IP Virtual Server version 1.9.5 (size=0) +Prot LocalAddress:Port Scheduler Flags + -> RemoteAddress:Port Forward Weight ActiveConn InActConn +TCP 192.168.88.1:80 rr conn-timeout 60 + -> 192.168.88.30:80 FullNat 100 0 42 + -> 192.168.88.130:80 FullNat 100 0 40 +TCP [2001::1]:80 conhash sip + -> 192.168.88.30:80 FullNat 100 0 0 + -> 192.168.88.30:8080 FullNat 100 0 0 + -> 192.168.88.130:8080 FullNat 100 0 15 +TCP [2001::2]:80 wrr + -> 192.168.88.30:80 FullNat 100 0 7 + -> 192.168.88.130:8080 FullNat 100 0 7 + -> 10.1.1.1:80 FullNat 0 0 0 inhibited + +[dpvs]# ipvsadm -G +VIP:VPORT TOTAL SNAT_IP CONFLICTS CONNS +[2001::2]:80 2 + 192.168.88.241 0 8 + 192.168.88.242 0 7 +[2001::1]:80 2 + 192.168.88.240 0 7 + 192.168.88.241 0 8 +192.168.88.1:80 2 + 192.168.88.240 0 41 + 192.168.88.241 0 39 +[dpvs]# dpip addr show +inet6 2001::28/64 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet 192.168.88.242/32 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet6 2001::1/128 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet 192.168.88.1/32 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet6 2001::2/128 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet 192.168.88.240/32 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet 192.168.88.28/24 scope global dpdk0.102 + valid_lft forever preferred_lft forever +inet 192.168.88.241/32 scope global dpdk0.102 + valid_lft forever preferred_lft forever + +[dpvs]# dpip route show +inet 192.168.88.1/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0.102 mtu 1500 tos 0 scope host metric 0 proto auto +inet 192.168.88.28/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0.102 mtu 1500 tos 0 scope host metric 0 proto auto +inet 192.168.88.240/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0.102 mtu 1500 tos 0 scope host metric 0 proto auto +inet 192.168.88.241/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0.102 mtu 1500 tos 0 scope host metric 0 proto auto +inet 192.168.88.242/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0.102 mtu 1500 tos 0 scope host metric 0 proto auto +inet 192.168.88.0/24 via 0.0.0.0 src 192.168.88.28 dev dpdk0.102 mtu 1500 tos 0 scope link metric 0 proto auto +[dpvs]# dpip -6 route show +inet6 2001::1/128 dev dpdk0.102 mtu 1500 scope host +inet6 2001::2/128 dev dpdk0.102 mtu 1500 scope host +inet6 2001::28/128 dev dpdk0.102 mtu 1500 scope host +inet6 2001::/64 src 2001::28 dev dpdk0.102 mtu 1500 scope link + +[dpvs]# ip addr show dpdk0.102.kni +560: dpdk0.102.kni: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 + link/ether 24:6e:96:75:7c:fa brd ff:ff:ff:ff:ff:ff + inet 192.168.88.28/24 scope global dpdk0.102.kni + valid_lft forever preferred_lft forever + inet6 2001::28/64 scope global + valid_lft forever preferred_lft forever + inet6 fe80::266e:96ff:fe75:7cfa/64 scope link + valid_lft forever preferred_lft forever +``` +The whole test procedures described above are written into the [run.sh](./run.sh) script. Read the script and then run it, you may gain insights into solutions to the integration of DPVS multiple componets into a container group such as kubernete Pod. + +# 4. Develop DPVS in Container + +We also provide a container image for DPVS developers. You can build an image for devel environments by specifying the build target as `builder`. + +```sh +docker build --target builder -t github.com/iqiyi/dpvs-builder:{version} . +``` +Once the dpvs-builder container image built successfully, run + +```sh +docker run --name=dpvs-devel -it github.com/iqiyi/dpvs-builder:v1.9.5 +``` +, and you enter a DPVS devel container, which installs the source codes and all dependencies for DPVS, include DPDK library and development tool chains. It's an easy place to make changes to DPVS codes for beginners. + diff --git a/doc/containerized/dpvs.conf b/doc/containerized/dpvs.conf new file mode 100644 index 000000000..565178f28 --- /dev/null +++ b/doc/containerized/dpvs.conf @@ -0,0 +1,271 @@ +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! This is dpvs default configuration file. +! +! The attribute "" denotes the configuration item at initialization stage. Item of +! this type is configured oneshoot and not reloadable. If invalid value configured in the +! file, dpvs would use its default value. +! +! Note that dpvs configuration file supports the following comment type: +! * line comment: using '#" or '!' +! * inline range comment: using '<' and '>', put comment in between +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +! global config +global_defs { + log_level WARNING + ! log_file /var/log/dpvs.log + ! log_async_mode on + ! kni on + ! pdump off +} + +! netif config +netif_defs { + pktpool_size 1048575 + pktpool_cache 256 + fdir_mode perfect + + device dpdk0 { + rx { + queue_number 8 + descriptor_number 1024 + rss all + } + tx { + queue_number 8 + descriptor_number 1024 + } + ! mtu 1500 + ! promisc_mode + ! allmulticast + kni_name dpdk0.kni + } +} + +! worker config (lcores) +! notes: +! 1. rx(tx) queue ids MUST start from 0 and continous +! 2. cpu ids and rx(tx) queue ids MUST be unique, repeated ids is forbidden +! 3. cpu ids identify dpvs workers only, and not correspond to physical cpu cores. +! If you are to specify cpu cores on which to run dpvs, please use dpdk eal options, +! such as "-c", "-l", "--lcores". Use "dpvs -- --help" for supported eal options. +worker_defs { + worker cpu0 { + type master + cpu_id 0 + } + + worker cpu1 { + type slave + cpu_id 1 + port dpdk0 { + rx_queue_ids 0 + tx_queue_ids 0 + ! isol_rx_cpu_ids 9 + ! isol_rxq_ring_sz 1048576 + } + } + + worker cpu2 { + type slave + cpu_id 2 + port dpdk0 { + rx_queue_ids 1 + tx_queue_ids 1 + ! isol_rx_cpu_ids 10 + ! isol_rxq_ring_sz 1048576 + } + } + + worker cpu3 { + type slave + cpu_id 3 + port dpdk0 { + rx_queue_ids 2 + tx_queue_ids 2 + ! isol_rx_cpu_ids 11 + ! isol_rxq_ring_sz 1048576 + } + } + + worker cpu4 { + type slave + cpu_id 4 + port dpdk0 { + rx_queue_ids 3 + tx_queue_ids 3 + ! isol_rx_cpu_ids 12 + ! isol_rxq_ring_sz 1048576 + } + } + + worker cpu5 { + type slave + cpu_id 5 + port dpdk0 { + rx_queue_ids 4 + tx_queue_ids 4 + ! isol_rx_cpu_ids 13 + ! isol_rxq_ring_sz 1048576 + } + } + + worker cpu6 { + type slave + cpu_id 6 + port dpdk0 { + rx_queue_ids 5 + tx_queue_ids 5 + ! isol_rx_cpu_ids 14 + ! isol_rxq_ring_sz 1048576 + } + } + + worker cpu7 { + type slave + cpu_id 7 + port dpdk0 { + rx_queue_ids 6 + tx_queue_ids 6 + ! isol_rx_cpu_ids 15 + ! isol_rxq_ring_sz 1048576 + } + } + + worker cpu8 { + type slave + cpu_id 8 + ! icmp_redirect_core + port dpdk0 { + rx_queue_ids 7 + tx_queue_ids 7 + ! isol_rx_cpu_ids 16 + ! isol_rxq_ring_sz 1048576 + } + } + + ! worker cpu17 { + ! type kni + ! cpu_id 17 + ! port dpdk0 { + ! rx_queue_ids 8 + ! tx_queue_ids 8 + ! } + !} +} + +! timer config +timer_defs { + # cpu job loops to schedule dpdk timer management + schedule_interval 500 +} + +! dpvs neighbor config +neigh_defs { + unres_queue_length 128 + timeout 60 +} + +! dpvs ipset config +ipset_defs { + ipset_hash_pool_size 131072 +} + +! dpvs ipv4 config +ipv4_defs { + forwarding off + default_ttl 64 + fragment { + bucket_number 4096 + bucket_entries 16 + max_entries 4096 + ttl 1 + } +} + +! dpvs ipv6 config +ipv6_defs { + disable off + forwarding off + route6 { + method hlist + recycle_time 10 + } +} + +! control plane config +ctrl_defs { + lcore_msg { + ring_size 4096 + sync_msg_timeout_us 20000 + priority_level low + } +} + +! ipvs config +ipvs_defs { + conn { + conn_pool_size 2097152 + conn_pool_cache 256 + conn_init_timeout 3 + ! expire_quiescent_template + ! fast_xmit_close + ! redirect off + } + + udp { + ! defence_udp_drop + uoa_mode opp + uoa_max_trail 3 + timeout { + oneway 60 + normal 300 + last 3 + } + } + + tcp { + ! defence_tcp_drop + timeout { + none 2 + established 90 + syn_sent 3 + syn_recv 30 + fin_wait 7 + time_wait 7 + close 3 + close_wait 7 + last_ack 7 + listen 120 + synack 30 + last 2 + } + synproxy { + synack_options { + mss 1452 + ttl 63 + sack + ! wscale 0 + ! timestamp + } + close_client_window + ! defer_rs_syn + rs_syn_max_retry 3 + ack_storm_thresh 10 + max_ack_saved 3 + conn_reuse_state { + close + time_wait + ! fin_wait + ! close_wait + ! last_ack + } + } + } +} + +! sa_pool config +sa_pool { + pool_hash_size 16 + flow_enable on +} diff --git a/doc/containerized/keepalived.conf b/doc/containerized/keepalived.conf new file mode 100644 index 000000000..f51eb9b65 --- /dev/null +++ b/doc/containerized/keepalived.conf @@ -0,0 +1,122 @@ +global_defs { + script_user root + enable_script_security +} + +local_address_group laddr_g1 { + 192.168.88.240 dpdk0.102 + 192.168.88.241 dpdk0.102 +} + +vrrp_instance vrrp_instance_107 { + state MASTER + interface dpdk0.102.kni + dpdk_interface dpdk0.102 + + higher_prio_send_advert + garp_lower_prio_repeat 3 + garp_master_refresh 30 + garp_master_refresh_repeat 1 + + virtual_router_id 107 + priority 100 + advert_int 1 + authentication { + auth_type PASS + auth_pass 12345 + } + + virtual_ipaddress { + 192.168.88.1 + } + virtual_ipaddress_excluded { + 2001::1 + } +} + +virtual_server_group 192.168.88.1-80-TCP_QLB { + 192.168.88.1 80 +} + +virtual_server group 192.168.88.1-80-TCP_QLB { + delay_loop 3 + lb_algo rr + lb_kind FNAT + protocol TCP + + establish_timeout 60 + daddr_group_name 192.168.88.1_deny + laddr_group_name laddr_g1 + + real_server 192.168.88.30 80 { + weight 100 + inhibit_on_failure + TCP_CHECK { + retry 1 + connect_timeout 1 + connect_port 80 + } + } + + real_server 192.168.88.130 80 { + weight 100 + inhibit_on_failure + TCP_CHECK { + retry 1 + connect_timeout 1 + connect_port 80 + } + + } +} + +virtual_server_group 2001::1-80-TCP_QLB { + 2001::1 80 +} + +virtual_server group 2001::1-80-TCP_QLB { + delay_loop 3 + lb_algo conhash + lb_kind FNAT + protocol TCP + + daddr_group_name 2001::1_deny + laddr_group_name laddr_g1 + + real_server 192.168.88.30 80 { + weight 100 + inhibit_on_failure + TCP_CHECK { + retry 1 + connect_timeout 1 + connect_port 80 + } + } + + real_server 192.168.88.130 8080 { + weight 100 + inhibit_on_failure + TCP_CHECK { + retry 1 + connect_timeout 1 + connect_port 8080 + } + } + + real_server 192.168.88.30 8080 { + weight 100 + inhibit_on_failure + TCP_CHECK { + retry 1 + connect_timeout 1 + connect_port 8080 + } + } +} + +deny_address_group 192.168.88.1_deny { +} + +deny_address_group 2001::1_deny { +} + diff --git a/doc/containerized/run.sh b/doc/containerized/run.sh new file mode 100755 index 000000000..ed4d3d2ea --- /dev/null +++ b/doc/containerized/run.sh @@ -0,0 +1,116 @@ +#!/bin/sh + +## install host requirements +if [ $# -ge 1 -a _$1 = _initial ]; then + ## FIXME: use proper dpdk drivers for different nics + modprobe uio + modprobe uio_pci_generic + dpdk-devbind -b uio_pci_generic 0000:01:00.1 + + echo 8192 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages + echo 8192 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages + + mkdir /var/run/dpvs + mkdir -p /var/run/dpvs/logs/dpvs-agent + mkdir -p /var/run/dpvs/logs/healthcheck +fi + +## stop and clean the running containers +docker stop dpvs && docker rm dpvs +docker stop keepalived && docker rm keepalived +docker stop dpvs-agent && docker rm dpvs-agent +docker stop healthcheck && docker rm healthcheck +rm -f /var/run/dpvs/{*.pid,dpvs.ipc} + +## TODO: prepare config file: /var/run/dpvs/dpvs.conf + +## start dpvs +docker run --name dpvs \ + -d --privileged --network host \ + -v /dev:/dev \ + -v /sys:/sys \ + -v /lib/modules:/lib/modules \ + -v /var/run/dpvs:/dpvs \ + github.com/iqiyi/dpvs:v1.9.5 \ + -c /dpvs/dpvs.conf -p /dpvs/dpvs.pid -x /dpvs/dpvs.ipc \ + -- -a 0000:01:00.1 +sleep 10 + +## start dpvs-agent +docker run --name dpvs-agent \ + --cap-add=NET_ADMIN \ + -d --network host \ + -v /var/run/dpvs:/dpvs \ + --entrypoint=/usr/bin/dpvs-agent \ + github.com/iqiyi/dpvs:v1.9.5 \ + --log-dir=/dpvs/logs/dpvs-agent \ + --ipc-sockopt-path=/dpvs/dpvs.ipc\ + --host=0.0.0.0 --port=6601 +sleep 3 + + +## set command line tools +alias ipvsadm='docker run --name ipvsadm --rm --network none -v /var/run/dpvs:/dpvs -e DPVS_IPC_FILE=/dpvs/dpvs.ipc --entrypoint=/usr/bin/ipvsadm github.com/iqiyi/dpvs:v1.9.5' +#docker run --name ipvsadm \ +# --rm --network none \ +# -v /var/run/dpvs:/dpvs \ +# -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ +# --entrypoint=/usr/bin/ipvsadm \ +# github.com/iqiyi/dpvs:v1.9.5 \ +# ... +alias dpip='docker run --name dpip --rm --network none -v /var/run/dpvs:/dpvs -e DPVS_IPC_FILE=/dpvs/dpvs.ipc --entrypoint=/usr/bin/dpip github.com/iqiyi/dpvs:v1.9.5' +#docker run --name dpip \ +# --rm --network none \ +# -v /var/run/dpvs:/dpvs \ +# -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ +# --entrypoint=/usr/bin/dpip \ +# github.com/iqiyi/dpvs:v1.9.5 \ +# ... + +## configure host network +#dpip vlan add dpdk0.102 link dpdk0 id 102 +#dpip addr add 192.168.88.28/24 dev dpdk0.102 +#dpip addr add 2001::28/64 dev dpdk0.102 +#ip addr add 192.168.88.28/24 dev dpdk0.102.kni +#ip addr add 2001::28/64 dev dpdk0.102.kni +#ip link set dpdk0.102.kni up +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/vlan" -H "Content-type:application/json" -d "{\"device\":\"dpdk0\", \"id\":\"102\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.28/24\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"2001::28/64\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.28/24\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102.kni/netlink/addr" -H "Content-type:application/json" -d "{\"addr\":\"2001::28/64\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102.kni/netlink" + +## start keepalived and deploy test services +docker run --name keepalived \ + -d --privileged --network host \ + --cap-add=NET_ADMIN --cap-add=NET_BROADCAST --cap-add=NET_RAW \ + -v /var/run/dpvs:/dpvs \ + -e DPVS_IPC_FILE=/dpvs/dpvs.ipc \ + --entrypoint=/usr/bin/keepalived github.com/iqiyi/dpvs:v1.9.5 \ + -D -n -f /dpvs/keepalived.conf \ + --log-console --log-facility=6 \ + --pid=/dpvs/keepalived.pid \ + --vrrp_pid=/dpvs/vrrp.pid \ + --checkers_pid=/dpvs/checkers.pid + +## deploy a test service with dpvs-agent api +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp" -H "Content-type:application/json" -d "{\"SchedName\":\"wrr\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr" -H "Content-type:application/json" -d "{\"addr\":\"2001::2\"}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.88.241\"}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/laddr" -H "Content-type:application/json" -d "{\"device\":\"dpdk0.102\", \"addr\":\"192.168.88.242\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.241\"}" +curl -X PUT "http://127.0.0.1:6601/v2/device/dpdk0.102/addr?sapool=true" -H "Content-type:application/json" -d "{\"addr\":\"192.168.88.242\"}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"192.168.88.30\", \"port\":80, \"weight\":100}]}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"192.168.88.130\", \"port\":8080, \"weight\":100}]}" +curl -X PUT "http://127.0.0.1:6601/v2/vs/2001::2-80-tcp/rs" -H "Content-type:application/json" -d "{\"Items\":[{\"ip\":\"10.1.1.1\", \"port\":80, \"weight\":100}]}" + +## start healthcheck for dpvs-aegnt +docker run --name healthcheck \ + -d --network host \ + -v /var/run/dpvs:/dpvs \ + --entrypoint=/usr/bin/healthcheck \ + github.com/iqiyi/dpvs:v1.9.5 \ + -log_dir=/dpvs/logs/healthcheck \ + -lb_iface_addr=localhost:6601 + From 474b85384a5330df13d34c79237cda0535f2089c Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 6 Sep 2023 16:37:15 +0800 Subject: [PATCH 071/105] healthcheck: add healthcheck method 'udpping' and make it the default checker for UDP targets The 'udpping' checker first checks the l3 network connectivity with ping checker, and performs udp checker only ping checker responds ok. It's an enhancement for the simple udp checker when udp port probe times out. Signed-off-by: ywc689 --- .../pkg/helthcheck/ping_checker_test.go | 7 ++- tools/healthcheck/pkg/helthcheck/server.go | 4 +- .../healthcheck/pkg/helthcheck/udp_checker.go | 4 +- .../pkg/helthcheck/udp_ping_checker.go | 62 +++++++++++++++++++ .../pkg/helthcheck/udp_ping_checker_test.go | 48 ++++++++++++++ tools/healthcheck/pkg/lb/types.go | 1 + 6 files changed, 120 insertions(+), 6 deletions(-) create mode 100644 tools/healthcheck/pkg/helthcheck/udp_ping_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/udp_ping_checker_test.go diff --git a/tools/healthcheck/pkg/helthcheck/ping_checker_test.go b/tools/healthcheck/pkg/helthcheck/ping_checker_test.go index 686ff15cf..7b86e665a 100644 --- a/tools/healthcheck/pkg/helthcheck/ping_checker_test.go +++ b/tools/healthcheck/pkg/helthcheck/ping_checker_test.go @@ -18,12 +18,13 @@ package hc import ( + "fmt" "net" "testing" "time" ) -var targets = []Target{ +var ping_targets = []Target{ {net.ParseIP("127.0.0.1"), 0, 0}, {net.ParseIP("192.168.88.30"), 0, 0}, {net.ParseIP("11.22.33.44"), 0, 0}, @@ -33,13 +34,13 @@ var targets = []Target{ } func TestPingChecker(t *testing.T) { - for _, target := range targets { + for _, target := range ping_targets { checker := NewPingChecker() id := Id(target.IP.String()) config := NewCheckerConfig(&id, checker, &target, StateUnknown, 0, 3*time.Second, 1*time.Second, 3) result := checker.Check(target, config.Timeout) - t.Logf("%v", result) + fmt.Printf("[ Ping ]%s ==>%v\n", target, result) } } diff --git a/tools/healthcheck/pkg/helthcheck/server.go b/tools/healthcheck/pkg/helthcheck/server.go index bd26265cb..2c3d6c55b 100644 --- a/tools/healthcheck/pkg/helthcheck/server.go +++ b/tools/healthcheck/pkg/helthcheck/server.go @@ -78,13 +78,15 @@ func (s *Server) NewChecker(typ lb.Checker, proto utils.IPProto) CheckMethod { checker = NewUDPChecker("", "") case lb.CheckerPING: checker = NewPingChecker() + case lb.CheckerUDPPing: + checker = NewUDPPingChecker("", "") case lb.CheckerNone: if s.config.LbAutoMethod { switch proto { case utils.IPProtoTCP: checker = NewTCPChecker("", "") case utils.IPProtoUDP: - checker = NewUDPChecker("", "") + checker = NewUDPPingChecker("", "") } } } diff --git a/tools/healthcheck/pkg/helthcheck/udp_checker.go b/tools/healthcheck/pkg/helthcheck/udp_checker.go index ceb6d4467..4cf385da6 100644 --- a/tools/healthcheck/pkg/helthcheck/udp_checker.go +++ b/tools/healthcheck/pkg/helthcheck/udp_checker.go @@ -47,7 +47,7 @@ func (hc *UDPChecker) String() string { return fmt.Sprintf("UDP checker for %v", hc.Config.Id) } -// Check executes a UDP healthcheck. +// Check executes an UDP healthcheck. func (hc *UDPChecker) Check(target Target, timeout time.Duration) *Result { msg := fmt.Sprintf("UDP check to %s", target.Addr()) start := time.Now() @@ -81,7 +81,7 @@ func (hc *UDPChecker) Check(target Target, timeout time.Duration) *Result { return NewResult(start, msg, false, err) } - buf := make([]byte, len(hc.Receive)+1) + buf := make([]byte, len(hc.Receive)) n, _, err := udpConn.ReadFrom(buf) if err != nil { if hc.Send == "" && hc.Receive == "" { diff --git a/tools/healthcheck/pkg/helthcheck/udp_ping_checker.go b/tools/healthcheck/pkg/helthcheck/udp_ping_checker.go new file mode 100644 index 000000000..6fbcee13d --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/udp_ping_checker.go @@ -0,0 +1,62 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "time" +) + +var _ CheckMethod = (*UDPPingChecker)(nil) + +// UDPPingChecker contains configuration specific to a UDPPing healthcheck. +type UDPPingChecker struct { + Config *CheckerConfig + + *UDPChecker + *PingChecker +} + +// NewUDPPingChecker returns an initialised UDPPingChecker. +func NewUDPPingChecker(recv, send string) *UDPPingChecker { + return &UDPPingChecker{UDPChecker: NewUDPChecker(recv, send), + PingChecker: NewPingChecker()} +} + +func (hc *UDPPingChecker) BindConfig(conf *CheckerConfig) { + hc.Config = conf +} + +// String returns the string representation of a UDPPing healthcheck. +func (hc *UDPPingChecker) String() string { + return fmt.Sprintf("UDPPing checker for %v", hc.Config.Id) +} + +// Check executes an UDPPing healthcheck. +func (hc *UDPPingChecker) Check(target Target, timeout time.Duration) *Result { + start := time.Now() + + result := hc.PingChecker.Check(target, timeout) + if result.Success != true { + return result + } + + result = hc.UDPChecker.Check(target, time.Until(start.Add(timeout))) + result.Duration = time.Since(start) + return result +} diff --git a/tools/healthcheck/pkg/helthcheck/udp_ping_checker_test.go b/tools/healthcheck/pkg/helthcheck/udp_ping_checker_test.go new file mode 100644 index 000000000..f20e69ac7 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/udp_ping_checker_test.go @@ -0,0 +1,48 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "net" + "testing" + "time" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +var udpping_targets = []Target{ + {net.ParseIP("192.168.88.30"), 6601, utils.IPProtoUDP}, + {net.ParseIP("11.22.33.44"), 6601, utils.IPProtoUDP}, + {net.ParseIP("192.168.88.30"), 6602, utils.IPProtoUDP}, + {net.ParseIP("2001::30"), 6601, utils.IPProtoUDP}, + {net.ParseIP("1234:5678::9"), 6601, utils.IPProtoUDP}, + {net.ParseIP("2001::30"), 6602, utils.IPProtoUDP}, +} + +func TestUDPPingChecker(t *testing.T) { + for _, target := range udpping_targets { + checker := NewUDPPingChecker("", "") + id := Id(target.String()) + config := NewCheckerConfig(&id, checker, + &target, StateUnknown, 0, + 3*time.Second, 2*time.Second, 3) + result := checker.Check(target, config.Timeout) + fmt.Printf("[ UDPPing ] %s ==> %v\n", target, result) + } +} diff --git a/tools/healthcheck/pkg/lb/types.go b/tools/healthcheck/pkg/lb/types.go index bc3f8a02e..092f4fb22 100644 --- a/tools/healthcheck/pkg/lb/types.go +++ b/tools/healthcheck/pkg/lb/types.go @@ -27,6 +27,7 @@ const ( CheckerTCP CheckerUDP CheckerPING + CheckerUDPPing ) type RealServer struct { From ff4962b2727d55c3acf117031a80ee42c84dfc6c Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 11 Sep 2023 17:14:56 +0800 Subject: [PATCH 072/105] healthcheck: add HTTP(S) check method Signed-off-by: ywc689 --- .../pkg/helthcheck/http_checker.go | 182 ++++++++++++++++++ .../pkg/helthcheck/http_checker_test.go | 78 ++++++++ 2 files changed, 260 insertions(+) create mode 100644 tools/healthcheck/pkg/helthcheck/http_checker.go create mode 100644 tools/healthcheck/pkg/helthcheck/http_checker_test.go diff --git a/tools/healthcheck/pkg/helthcheck/http_checker.go b/tools/healthcheck/pkg/helthcheck/http_checker.go new file mode 100644 index 000000000..4432a9187 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/http_checker.go @@ -0,0 +1,182 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "crypto/tls" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strings" + "time" +) + +var _ CheckMethod = (*HttpChecker)(nil) + +type HttpCodeRange struct { + start int // inclusive + end int // inclusive +} + +// HttpChecker contains configuration specific to a HTTP(S) healthcheck. +type HttpChecker struct { + Config *CheckerConfig + + Method string + Host string + Uri string + ResponseCodes []HttpCodeRange + Response string + + Secure bool + TLSVerify bool + Proxy bool +} + +// NewHttpChecker returns an initialised HttpChecker. +func NewHttpChecker(method, host, uri string) *HttpChecker { + if len(method) == 0 { + method = "GET" + } + if len(uri) == 0 { + uri = "/" + } + return &HttpChecker{ + Method: method, + Uri: uri, + ResponseCodes: []HttpCodeRange{{200, 299}, {300, 399}, {400, 499}}, + Response: "", + Secure: false, + TLSVerify: true, + Proxy: false, + } +} + +func (hc *HttpChecker) BindConfig(conf *CheckerConfig) { + hc.Config = conf + if len(hc.Host) == 0 { + hc.Host = conf.Target.Addr() + } +} + +// String returns the string representation of a HTTP healthcheck. +func (hc *HttpChecker) String() string { + attr := []string{hc.Method, hc.Host, hc.Uri} + if hc.Secure { + attr = append(attr, "secure") + if hc.TLSVerify { + attr = append(attr, "tls-verify") + } + } + if hc.Proxy { + attr = append(attr, "proxy") + } + + return fmt.Sprintf("HTTP checker for %v [%s]", hc.Config.Id, strings.Join(attr, ", ")) +} + +// Check executes a HTTP healthcheck. +func (hc *HttpChecker) Check(target Target, timeout time.Duration) *Result { + var msg string + if hc.Secure { + msg = fmt.Sprintf("HTTPS %s to %s", hc.Method, hc.Host) + } else { + msg = fmt.Sprintf("HTTP %s to %s", hc.Method, hc.Host) + } + + start := time.Now() + if timeout == time.Duration(0) { + timeout = DefaultCheckConfig.Timeout + } + + u, err := url.Parse(hc.Uri) + if err != nil { + return NewResult(start, fmt.Sprintf("%s; url parse failed", msg), false, err) + } + if hc.Secure { + u.Scheme = "https" + } else { + u.Scheme = "http" + } + if len(u.Host) == 0 { + u.Host = hc.Host + } + + proxy := (func(*http.Request) (*url.URL, error))(nil) + if hc.Proxy { + proxy = http.ProxyURL(u) + } + + tlsConfig := &tls.Config{ + InsecureSkipVerify: !hc.TLSVerify, + } + client := &http.Client{ + Transport: &http.Transport{ + Proxy: proxy, + TLSClientConfig: tlsConfig, + }, + Timeout: timeout, + CheckRedirect: func(req *http.Request, via []*http.Request) error { + return errors.New("redirect not permitted") + }, + } + + req, err := http.NewRequest(hc.Method, hc.Uri, nil) + req.URL = u + + // If we received a response we want to process it, even in the + // presence of an error - a redirect 3xx will result in both the + // response and an error being returned. + resp, err := client.Do(req) + if resp == nil { + return NewResult(start, fmt.Sprintf("%s; got no response", msg), false, err) + } + if resp.Body != nil { + defer resp.Body.Close() + } + + // Check response code. + codeOk := false + for _, cr := range hc.ResponseCodes { + if resp.StatusCode >= cr.start && resp.StatusCode <= cr.end { + codeOk = true + break + } + } + + // Check response body. + bodyOk := false + msg = fmt.Sprintf("%s; got %s", msg, resp.Status) + if len(hc.Response) == 0 { + bodyOk = true + } else if resp.Body != nil { + buf := make([]byte, len(hc.Response)) + n, err := io.ReadFull(resp.Body, buf) + if err != nil && err != io.ErrUnexpectedEOF { + msg = fmt.Sprintf("%s; failed to read HTTP response", msg) + } else if string(buf) != hc.Response { + msg = fmt.Sprintf("%s; unexpected response - %q", msg, string(buf[0:n])) + } else { + bodyOk = true + } + } + + return NewResult(start, msg, codeOk && bodyOk, nil) +} diff --git a/tools/healthcheck/pkg/helthcheck/http_checker_test.go b/tools/healthcheck/pkg/helthcheck/http_checker_test.go new file mode 100644 index 000000000..809b43bd3 --- /dev/null +++ b/tools/healthcheck/pkg/helthcheck/http_checker_test.go @@ -0,0 +1,78 @@ +// Copyright 2023 IQiYi Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// The healthcheck package refers to the framework of "github.com/google/ +// seesaw/healthcheck" heavily, with only some adaption changes for DPVS. + +package hc + +import ( + "fmt" + "net" + "strings" + "testing" + "time" + + "github.com/iqiyi/dpvs/tools/healthcheck/pkg/utils" +) + +var http_targets = []Target{ + {net.ParseIP("192.168.88.30"), 80, utils.IPProtoTCP}, + {net.ParseIP("192.168.88.30"), 443, utils.IPProtoTCP}, + {net.ParseIP("2001::30"), 80, utils.IPProtoTCP}, + {net.ParseIP("2001::30"), 443, utils.IPProtoTCP}, +} + +var http_url_targets = []string{ + "http://www.baidu.com", + "https://www.baidu.com", + "http://www.iqiyi.com", + "https://www.iqiyi.com", +} + +func TestHttpChecker(t *testing.T) { + for _, target := range http_targets { + checker := NewHttpChecker("", "", "") + checker.Host = target.Addr() + /* + if target.Port == 443 { + checker.Secure = true + } + */ + id := Id(target.String()) + config := NewCheckerConfig(&id, checker, &target, StateUnknown, + 0, 3*time.Second, 2*time.Second, 3) + result := checker.Check(target, config.Timeout) + fmt.Printf("[ HTTP ] %s ==> %v\n", target, result) + } + + for _, target := range http_url_targets { + host := target[strings.Index(target, "://")+3:] + checker := NewHttpChecker("GET", target, "") + checker.Host = host + checker.ResponseCodes = []HttpCodeRange{{200, 200}} + if strings.HasPrefix(target, "https") { + checker.Secure = true + } + id := Id(host) + config := NewCheckerConfig(&id, checker, &Target{}, StateUnknown, + 0, 3*time.Second, 2*time.Second, 3) + result := checker.Check(Target{}, config.Timeout) + if result.Success == false { + t.Errorf("[ HTTP ] %s ==> %v\n", target, result) + } else { + fmt.Printf("[ HTTP ] %s ==> %v\n", target, result) + } + } +} From e11055489d5e75a5a06556ff5ca8830a7b0b81bb Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 12 Sep 2023 15:33:42 +0800 Subject: [PATCH 073/105] healthcheck: set config's health state from dpvs properly Note that realserver's weight and inhibited flag can be modified by dpvs-agent independently. So we cannot assume that the weight is zero when inhibited flag is set. Signed-off-by: ywc689 --- tools/healthcheck/pkg/helthcheck/server.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/healthcheck/pkg/helthcheck/server.go b/tools/healthcheck/pkg/helthcheck/server.go index 2c3d6c55b..9e5712570 100644 --- a/tools/healthcheck/pkg/helthcheck/server.go +++ b/tools/healthcheck/pkg/helthcheck/server.go @@ -111,9 +111,9 @@ func (s *Server) getHealthchecks() (*Checkers, error) { } weight := rs.Weight state := StateUnknown - if weight > 0 { + if weight > 0 && rs.Inhibited == false { state = StateHealthy - } else if rs.Inhibited { + } else if weight == 0 && rs.Inhibited == true { state = StateUnhealthy } // TODO: allow users to specify check interval, timeout and retry From e3a7ee0d0746f663d31d6c5ad4a37eb9640714b7 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 12 Sep 2023 15:39:28 +0800 Subject: [PATCH 074/105] dpvs-agent: fix confusions for realserver's inhibited and overloaded flags Signed-off-by: ywc689 --- tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go | 2 +- tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go index 76520bc12..a7c9378a1 100644 --- a/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/post_vs_vip_port_rs.go @@ -56,7 +56,7 @@ func (h *postVsRs) Handle(params apiVs.PostVsVipPortRsParams) middleware.Respond rss[i].SetProto(front.GetProto()) rss[i].SetAddr(rs.IP) rss[i].SetInhibited(rs.Inhibited) - rss[i].SetOverloaded(rs.Inhibited) + rss[i].SetOverloaded(rs.Overloaded) rss[i].SetFwdMode(fwdmode) } diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go index a472be1e7..acfeb572f 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port_rs.go @@ -58,7 +58,7 @@ func (h *putVsRs) Handle(params apiVs.PutVsVipPortRsParams) middleware.Responder rss[i].SetWeight(uint32(rs.Weight)) rss[i].SetFwdMode(fwdmode) rss[i].SetInhibited(rs.Inhibited) - rss[i].SetOverloaded(rs.Inhibited) + rss[i].SetOverloaded(rs.Overloaded) } } From 1ca55d8c5db4ca701822b38e4d5ca58e0ae276ef Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 12 Sep 2023 15:40:50 +0800 Subject: [PATCH 075/105] ipvs: lower 'no dest found' log message level when scheduling a service without available backends Signed-off-by: ywc689 --- src/ipvs/ip_vs_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ipvs/ip_vs_core.c b/src/ipvs/ip_vs_core.c index 2e7851c40..85fa206eb 100644 --- a/src/ipvs/ip_vs_core.c +++ b/src/ipvs/ip_vs_core.c @@ -299,7 +299,7 @@ struct dp_vs_conn *dp_vs_schedule(struct dp_vs_service *svc, dest = svc->scheduler->schedule(svc, mbuf, iph); if (!dest) { - RTE_LOG(WARNING, IPVS, "%s: no dest found.\n", __func__); + RTE_LOG(INFO, IPVS, "%s: no dest found.\n", __func__); #ifdef CONFIG_DPVS_MBUF_DEBUG dp_vs_mbuf_dump("found dest failed.", iph->af, mbuf); #endif From af47c02d1ed0f67d1e5201703c866247c9709ee8 Mon Sep 17 00:00:00 2001 From: ytwang0320 Date: Fri, 15 Sep 2023 10:58:44 +0800 Subject: [PATCH 076/105] patch: support dcdn toa (#913) Decode aliyun's toa and encode it to the format of DPVS. It's a workaround when the traffic of DPVS is from aliyun l4lb. --- patch/dcdn-toa.patch | 139 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 patch/dcdn-toa.patch diff --git a/patch/dcdn-toa.patch b/patch/dcdn-toa.patch new file mode 100644 index 000000000..5107fcd42 --- /dev/null +++ b/patch/dcdn-toa.patch @@ -0,0 +1,139 @@ +From 55e8e5da2b4b0893d36cb3f621bedf9833c4ea50 Mon Sep 17 00:00:00 2001 +From: wangyetong +Date: Thu, 14 Sep 2023 15:33:42 +0800 +Subject: [PATCH] added dcdn toa + +--- + include/ipvs/conn.h | 5 +++++ + include/ipvs/proto_tcp.h | 2 ++ + src/ipvs/ip_vs_proto_tcp.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 60 insertions(+), 1 deletion(-) + +diff --git a/include/ipvs/conn.h b/include/ipvs/conn.h +index fa0bdeb..88dcb44 100644 +--- a/include/ipvs/conn.h ++++ b/include/ipvs/conn.h +@@ -166,6 +166,11 @@ struct dp_vs_conn { + /* flag for gfwip */ + bool outwall; + ++ /* dcdn toa found or not */ ++ bool dcdn_found; ++ /* dcdn toa address */ ++ struct in_addr dcdn_addr; ++ + } __rte_cache_aligned; + + /* for syn-proxy to save all ack packet in conn before rs's syn-ack arrives */ +diff --git a/include/ipvs/proto_tcp.h b/include/ipvs/proto_tcp.h +index 9f5162a..41d5646 100644 +--- a/include/ipvs/proto_tcp.h ++++ b/include/ipvs/proto_tcp.h +@@ -28,6 +28,7 @@ enum { + TCP_OPT_SACK_PERM = 4, + TCP_OPT_SACK = 5, + TCP_OPT_TIMESTAMP = 8, ++ TCP_OPT_DCDN_ADDR = 28, + TCP_OPT_ADDR = 254, /* non-standard */ + }; + +@@ -35,6 +36,7 @@ enum { + #define TCP_OLEN_TIMESTAMP 10 + #define TCP_OLEN_IP4_ADDR 8 + #define TCP_OLEN_IP6_ADDR 20 ++#define TOA_DCDN_IPV4 1 + + #define TCP_OLEN_TSTAMP_ALIGNED 12 + #define TCP_OLEN_SACK_BASE 2 +diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c +index cbb7cb2..2cd889a 100644 +--- a/src/ipvs/ip_vs_proto_tcp.c ++++ b/src/ipvs/ip_vs_proto_tcp.c +@@ -305,6 +305,43 @@ static void tcp_in_remove_ts(struct tcphdr *tcph) + } + } + ++/* check dcdn toa option */ ++static inline int tcp_in_check_toa(struct dp_vs_conn *conn, struct tcphdr *tcph, struct in_addr *addr) ++{ ++ unsigned char *ptr; ++ int len; ++ ++ ptr = (unsigned char *)(tcph + 1); ++ len = (tcph->doff << 2) - sizeof(struct tcphdr); ++ ++ while (len > 0) { ++ int opcode = *ptr++; ++ int opsize; ++ ++ switch (opcode) { ++ case TCP_OPT_EOL: ++ return EDPVS_NOTEXIST; ++ case TCP_OPT_NOP: ++ len--; ++ continue; ++ default: ++ opsize = *ptr++; ++ if (opsize < 2) /* silly options */ ++ return EDPVS_NOTEXIST; ++ if (opsize > len) ++ return EDPVS_NOTEXIST; /* partial options */ ++ if ((opcode == TCP_OPT_DCDN_ADDR) ++ && (*ptr == TOA_DCDN_IPV4) && (opsize == TCP_OLEN_IP4_ADDR - 1) && addr) { ++ memcpy(addr, ptr + 1, sizeof(struct in_addr)); ++ return EDPVS_OK; ++ } ++ ptr += opsize - 2; ++ len -= opsize; ++ } ++ } ++ return EDPVS_NOTEXIST; ++} ++ + static inline int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + struct tcphdr *tcph) + { +@@ -382,7 +419,10 @@ static inline int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + + if (conn->af == AF_INET) { + struct tcpopt_ip4_addr *toa_ip4 = (struct tcpopt_ip4_addr *)(tcph + 1); +- toa_ip4->addr = conn->caddr.in; ++ if (conn->dcdn_found) ++ toa_ip4->addr = conn->dcdn_addr; ++ else ++ toa_ip4->addr = conn->caddr.in; + } + else { + struct tcpopt_ip6_addr *toa_ip6 = (struct tcpopt_ip6_addr *)(tcph + 1); +@@ -694,9 +734,13 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, + struct dp_vs_conn *conn, struct rte_mbuf *mbuf) + { + struct tcphdr *th; ++ struct in_addr dcdn_addr; + /* af/mbuf may be changed for nat64 which in af is ipv6 and out is ipv4 */ + int af = tuplehash_out(conn).af; + int iphdrlen = ((AF_INET6 == af) ? ip6_hdrlen(mbuf): ip4_hdrlen(mbuf)); ++#ifdef CONFIG_DPVS_IPVS_DEBUG ++ char dcdn_buf[64]; ++#endif + + if (mbuf_may_pull(mbuf, iphdrlen + sizeof(*th)) != 0) + return EDPVS_INVPKT; +@@ -720,6 +764,14 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, + if (th->syn && !th->ack) { + tcp_in_remove_ts(th); + tcp_in_init_seq(conn, mbuf, th); ++ if (tcp_in_check_toa(conn, th, &dcdn_addr) == EDPVS_OK) { ++ conn->dcdn_found = true; ++ conn->dcdn_addr = dcdn_addr; ++#ifdef CONFIG_DPVS_IPVS_DEBUG ++ inet_ntop(AF_INET, &dcdn_addr, dcdn_buf, sizeof(dcdn_buf)); ++ RTE_LOG(DEBUG, IPVS, "get dcdn toa addr %s\n", dcdn_buf); ++#endif ++ } + tcp_in_add_toa(conn, mbuf, th); + } + +-- +1.8.3.1 + From e250eb936501e4102db21322f3256e5da0236b7b Mon Sep 17 00:00:00 2001 From: you-looks-not-tasty <42596733+you-looks-not-tasty@users.noreply.github.com> Date: Fri, 15 Sep 2023 11:50:39 +0800 Subject: [PATCH 077/105] dpvs-agent: fix spelling mistake TUNNEL (#914) --- tools/dpvs-agent/pkg/ipc/types/const.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/dpvs-agent/pkg/ipc/types/const.go b/tools/dpvs-agent/pkg/ipc/types/const.go index 30be74fdb..6cbf89f02 100644 --- a/tools/dpvs-agent/pkg/ipc/types/const.go +++ b/tools/dpvs-agent/pkg/ipc/types/const.go @@ -96,7 +96,7 @@ func (e *DpvsFwdMode) String() string { case DPVS_FWD_MODE_DR: return "DR" case DPVS_FWD_MODE_TUNNEL: - return "TUNNLE" + return "TUNNEL" case DPVS_FWD_MODE_BYPASS: return "BYPASS" case DPVS_FWD_MODE_SNAT: @@ -115,7 +115,7 @@ func (e *DpvsFwdMode) FromString(name string) { *e = DPVS_FWD_LOCALNODE case "DR": *e = DPVS_FWD_MODE_DR - case "TUNNLE": + case "TUNNEL": *e = DPVS_FWD_MODE_TUNNEL case "BYPASS": *e = DPVS_FWD_MODE_BYPASS From 1a7ac1b2af3c99fcd0c6db2c62ac0b182996e727 Mon Sep 17 00:00:00 2001 From: donghaobo <122531097@qq.com> Date: Wed, 25 Oct 2023 10:22:18 +0800 Subject: [PATCH 078/105] ip4_select_id use rte_atomic32_add_return --- src/ipv4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ipv4.c b/src/ipv4.c index 652a351c3..21884c7a5 100644 --- a/src/ipv4.c +++ b/src/ipv4.c @@ -518,8 +518,8 @@ uint32_t ip4_select_id(struct rte_ipv4_hdr *iph) iph->next_proto_id, ip4_id_hashrnd); p_id = ip4_idents + hash % IP4_IDENTS_SZ; - id = htons(rte_atomic32_read(p_id)); - rte_atomic32_add(p_id, 1); + id = rte_atomic32_add_return(p_id, 1) - 1; + id = htons(id); return id; } From f9e7422e64164c9f5706f0ddbd5b952ebc623d36 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 19 Sep 2023 11:13:00 +0800 Subject: [PATCH 079/105] timer: fix timeout over about 524s do not work as expected The problem is revealed by yangxingwu in pr #901 and the fix is fetched from pr #29 authored by yangxingwu. --- include/timer.h | 1 + src/timer.c | 39 +++++++++++++++++++++------------------ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/include/timer.h b/include/timer.h index e77eae161..ba1bb6563 100644 --- a/include/timer.h +++ b/include/timer.h @@ -51,6 +51,7 @@ struct dpvs_timer { * 'interval' for periodic timer. */ dpvs_tick_t delay; + dpvs_tick_t left; }; dpvs_tick_t timeval_to_ticks(const struct timeval *tv); diff --git a/src/timer.c b/src/timer.c index 067c7d129..dd3485375 100644 --- a/src/timer.c +++ b/src/timer.c @@ -187,6 +187,7 @@ static int __dpvs_timer_sched(struct timer_scheduler *sched, timer->delay = 1; } + timer->left = timer->delay; /* add to corresponding wheel, from higher level to lower. */ for (level = LEVEL_DEPTH - 1; level >= 0; level--) { off = timer->delay / get_level_ticks(level); @@ -196,6 +197,10 @@ static int __dpvs_timer_sched(struct timer_scheduler *sched, #ifdef CONFIG_TIMER_DEBUG assert(timer->handler == handler); #endif + /* store the remainder */ + timer->left = timer->left % get_level_ticks(level); + for (level = level - 1; level >= 0; level--) + timer->left += sched->cursors[level] * get_level_ticks(level); return EDPVS_OK; } } @@ -285,7 +290,7 @@ static void rte_timer_tick_cb(struct rte_timer *tim, void *arg) struct timer_scheduler *sched = arg; struct dpvs_timer *timer; struct list_head *head; - uint64_t left, hash, off, remainder; + uint64_t hash, off; int level, lower; uint32_t *cursor; bool carry; @@ -314,36 +319,34 @@ static void rte_timer_tick_cb(struct rte_timer *tim, void *arg) while (!list_empty(head)) { timer = list_first_entry(head, struct dpvs_timer, list); /* is all lower levels ticks empty ? */ - left = timer->delay % get_level_ticks(level); - if (!left) { + if (!timer->left) { timer_expire(sched, timer); } else { /* drop to lower level wheel, note it may not drop to * "next" lower level wheel. */ list_del(&timer->list); - lower = level; - remainder = timer->delay % get_level_ticks(level); - while (--lower >= 0) { - off = remainder / get_level_ticks(lower); - if (!off) - continue; /* next lower level */ - - hash = (sched->cursors[lower] + off) % LEVEL_SIZE; - list_add_tail(&timer->list, &sched->hashs[lower][hash]); - break; + for (lower = level; lower >= 0; lower--) { + off = timer->left / get_level_ticks(lower); + if (off > 0) { + hash = (sched->cursors[lower] + off) % LEVEL_SIZE; + list_add_tail(&timer->list, &sched->hashs[lower][hash]); + /* + * store the remainder + * all lower cursor must be 0 + * so it's not necessary to calculate the offset + * see __dpvs_timer_sched for details + */ + timer->left = timer->left % get_level_ticks(lower); + break; + } } - - assert(lower >= 0); } } - if (!carry) break; } timer_sched_unlock(sched); - - return; } static int timer_init_schedler(struct timer_scheduler *sched, lcoreid_t cid) From 12ef8a917d034e215197501e6f46c6ae77cf5e7e Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 19 Sep 2023 10:37:31 +0800 Subject: [PATCH 080/105] test: update timer accuracy test program Signed-off-by: ywc689 --- src/global_data.c | 4 +++ src/main.c | 4 --- test/timer/timer_accuracy_test.c | 52 +++++++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/global_data.c b/src/global_data.c index 81f6cf30a..991599a46 100644 --- a/src/global_data.c +++ b/src/global_data.c @@ -20,6 +20,10 @@ #include #include "global_data.h" +char *dpvs_pid_file; +char *dpvs_ipc_file; +char *dpvs_conf_file; + RTE_DEFINE_PER_LCORE(uint32_t, g_dpvs_poll_tick); unsigned int g_version; diff --git a/src/main.c b/src/main.c index 05c0d92ec..00ca89655 100644 --- a/src/main.c +++ b/src/main.c @@ -55,10 +55,6 @@ #define LCORE_CONF_BUFFER_LEN 4096 -char *dpvs_pid_file; -char *dpvs_ipc_file; -char *dpvs_conf_file; - static void inline dpdk_version_check(void) { #if RTE_VERSION < RTE_VERSION_NUM(20, 11, 1, 0) diff --git a/test/timer/timer_accuracy_test.c b/test/timer/timer_accuracy_test.c index 2e1c27dfb..6458cd204 100644 --- a/test/timer/timer_accuracy_test.c +++ b/test/timer/timer_accuracy_test.c @@ -1,12 +1,15 @@ +#include #include #include "dpdk.h" +#include "scheduler.h" #include "cfgfile.h" #include "timer.h" -#define RTE_TIMER_INT 500 /* us */ -#define MAX_DELAY 16000 /* s, should be less than TIMER_MAX_TICKS/DPVS_TIMER_HZ */ +#define RTE_TIMER_INT 500 /* us */ +#define MAX_DELAY 16000 /* s, should be less than TIMER_MAX_TICKS/DPVS_TIMER_HZ */ static struct timeval g_start_time; +static int init_delay_sec; static int lcore_loop(void *arg) { @@ -20,15 +23,22 @@ static int lcore_loop(void *arg) static int timeup(void *arg) { struct timeval tv; - struct timeval now, elapsed; + struct timeval now, elapsed, delta; struct dpvs_timer *tm = arg; gettimeofday(&now, NULL); timersub(&now, &g_start_time, &elapsed); ticks_to_timeval(tm->delay, &tv); - fprintf(stdout, "timer timeout: %lu.%06lu, elapsed time: %lu.%06lu\n", - tv.tv_sec, tv.tv_usec, elapsed.tv_sec, elapsed.tv_usec); + if (timercmp(&tv, &elapsed, <)) { + timersub(&elapsed, &tv, &delta); + } else { + timersub(&tv, &elapsed, &delta); + } + + fprintf(stderr, "[%02d] timer timeout: %lu.%06lu, elapsed time: %lu.%06lu, " + "diff: %lu.%06lu\n", rte_lcore_id(), tv.tv_sec, tv.tv_usec, + elapsed.tv_sec, elapsed.tv_usec, delta.tv_sec, delta.tv_usec); rte_free(tm); @@ -38,9 +48,13 @@ static int timeup(void *arg) int main(int argc, char *argv[]) { int i, err; - struct timeval delay; + struct timeval delay, elapsed; struct dpvs_timer *timer; + gettimeofday(&delay, NULL); + srandom(delay.tv_usec ^ getpid()); + init_delay_sec = random() % 53 + 7; + /* init */ err = rte_eal_init(argc, argv); if (err < 0) { @@ -49,6 +63,18 @@ int main(int argc, char *argv[]) } rte_timer_subsystem_init(); + err = dpvs_scheduler_init(); + if (err) { + fprintf(stderr, "dpvs_scheduler_init failed\n"); + return 1; + } + + err = global_data_init(); + if (err) { + fprintf(stderr, "global_data_init failed\n"); + return 1; + } + err = cfgfile_init(); if (err) { fprintf(stderr, "cfgfile_init failed\n"); @@ -61,10 +87,20 @@ int main(int argc, char *argv[]) return 1; } - rte_eal_mp_remote_launch(lcore_loop, NULL, SKIP_MASTER); + rte_eal_mp_remote_launch(lcore_loop, NULL, SKIP_MAIN); + + /* delay for some time before scheduling timers */ + fprintf(stderr, "delay %d seconds ..\n", init_delay_sec); + while (1) { + rte_timer_manage(); + gettimeofday(&g_start_time, NULL); + timersub(&g_start_time, &delay, &elapsed); + if (elapsed.tv_sec > init_delay_sec) + break; + usleep(RTE_TIMER_INT); + } /* start timer */ - gettimeofday(&g_start_time, NULL); for (i = 1; i < MAX_DELAY; i++) { timer = rte_zmalloc("timer", sizeof(struct dpvs_timer), 0); if (!timer) { From ab6dd163554485e05bf9f50ad559499e95cc3eee Mon Sep 17 00:00:00 2001 From: cfc4n Date: Thu, 7 Dec 2023 21:29:40 +0800 Subject: [PATCH 081/105] clear TOA field, fix security vulnerability. See #925 for more detail. --- src/ipvs/ip_vs_proto_tcp.c | 70 ++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 7578bae4d..244722a5d 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -305,6 +305,48 @@ static void tcp_in_remove_ts(struct tcphdr *tcph) } } +/* use NOP option to replace TCP_OLEN_IP4_ADDR and TCP_OLEN_IP6_ADDR opt */ +static void tcp_in_remove_toa(struct tcphdr *tcph, int af) +{ + unsigned char *ptr; + int len, i; + uint32_t tcp_opt_len = af == AF_INET ? TCP_OLEN_IP4_ADDR : TCP_OLEN_IP6_ADDR; + + ptr = (unsigned char *)(tcph + 1); + len = (tcph->doff << 2) - sizeof(struct tcphdr); + + while (len > 0) { + int opcode = *ptr++; + int opsize; + + switch (opcode) { + case TCP_OPT_EOL: + return; + case TCP_OPT_NOP: + len--; + continue; + default: + opsize = *ptr++; + if (opsize < 2) /* silly options */ + return; + if (opsize > len) + return; /* partial options */ + if ((opcode == TCP_OPT_ADDR) && (opsize == tcp_opt_len)) { + for (i = 0; i < tcp_opt_len; i++) { + *(ptr - 2 + i) = TCP_OPT_NOP; + } + /* DON'T RETURN + * keep search other TCP_OPT_ADDR ,and clear them. + * See https://github.com/iqiyi/dpvs/pull/925 for more detail. */ + } + + ptr += opsize - 2; + len -= opsize; + break; + } + } +} + static inline int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, struct tcphdr *tcph) { @@ -705,8 +747,13 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, { struct tcphdr *th; /* af/mbuf may be changed for nat64 which in af is ipv6 and out is ipv4 */ - int af = tuplehash_out(conn).af; - int iphdrlen = ((AF_INET6 == af) ? ip6_hdrlen(mbuf): ip4_hdrlen(mbuf)); + int iaf, oaf; + int iphdrlen; + + iaf = tuplehash_in(conn).af; + oaf = tuplehash_out(conn).af; + + iphdrlen = ((AF_INET6 == oaf) ? ip6_hdrlen(mbuf): ip4_hdrlen(mbuf)); if (mbuf_may_pull(mbuf, iphdrlen + sizeof(*th)) != 0) return EDPVS_INVPKT; @@ -729,14 +776,25 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, */ if (th->syn && !th->ack) { tcp_in_remove_ts(th); + tcp_in_init_seq(conn, mbuf, th); - tcp_in_add_toa(conn, mbuf, th); + + /* Only clear when adding TOA fails to reduce invocation frequency and improve performance. + * See https://github.com/iqiyi/dpvs/pull/925 for more detail. */ + if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { + tcp_in_remove_toa(th, iaf); + } } /* add toa to first data packet */ if (ntohl(th->ack_seq) == conn->fnat_seq.fdata_seq - && !th->syn && !th->rst /*&& !th->fin*/) - tcp_in_add_toa(conn, mbuf, th); + && !th->syn && !th->rst /*&& !th->fin*/) { + /* Only clear when adding TOA fails to reduce invocation frequency and improve performance. + * See https://github.com/iqiyi/dpvs/pull/925 for more detail. */ + if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { + tcp_in_remove_toa(th, iaf); + } + } tcp_in_adjust_seq(conn, th); @@ -745,7 +803,7 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, th->dest = conn->dport; - return tcp_send_csum(af, iphdrlen, th, conn, mbuf, conn->in_dev); + return tcp_send_csum(oaf, iphdrlen, th, conn, mbuf, conn->in_dev); } static int tcp_fnat_out_handler(struct dp_vs_proto *proto, From d5a39f2d4890d0425dc52c866c322e05f90b2617 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 12 Jul 2023 16:13:39 +0800 Subject: [PATCH 082/105] route: remove fragile implementation of strategy routing codes for snat Signed-off-by: ywc689 --- include/conf/flow.h | 1 - include/conf/route.h | 1 - include/ipvs/conn.h | 4 --- include/ipvs/ipvs.h | 3 +-- include/ipvs/service.h | 2 +- include/route.h | 1 - src/ipvs/ip_vs_conn.c | 1 - src/ipvs/ip_vs_core.c | 9 +++---- src/ipvs/ip_vs_dest.c | 8 +++--- src/ipvs/ip_vs_laddr.c | 18 ++++++------- src/ipvs/ip_vs_proto_icmp.c | 5 ++-- src/ipvs/ip_vs_proto_tcp.c | 5 ++-- src/ipvs/ip_vs_proto_udp.c | 5 ++-- src/ipvs/ip_vs_service.c | 14 ++++------ src/ipvs/ip_vs_synproxy.c | 7 +++-- src/ipvs/ip_vs_xmit.c | 17 +++---------- src/route.c | 51 +++---------------------------------- 17 files changed, 38 insertions(+), 114 deletions(-) diff --git a/include/conf/flow.h b/include/conf/flow.h index 95baf407c..1c403b938 100644 --- a/include/conf/flow.h +++ b/include/conf/flow.h @@ -46,7 +46,6 @@ #define RTF_LOCALIN 0x0800 #define RTF_DEFAULT 0x1000 #define RTF_KNI 0X2000 -#define RTF_OUTWALL 0x4000 typedef struct rt_addr { union inet_addr addr; diff --git a/include/conf/route.h b/include/conf/route.h index 20839b20c..85e4cf5f6 100644 --- a/include/conf/route.h +++ b/include/conf/route.h @@ -60,7 +60,6 @@ struct dp_vs_route_conf { uint8_t metric; uint8_t proto; /* routing protocol */ uint32_t flags; - int32_t outwalltb; } __attribute__((__packed__)); typedef struct dp_vs_route_detail { diff --git a/include/ipvs/conn.h b/include/ipvs/conn.h index 4624185cd..0075da6cc 100644 --- a/include/ipvs/conn.h +++ b/include/ipvs/conn.h @@ -58,7 +58,6 @@ struct dp_vs_conn_param { uint16_t cport; uint16_t vport; uint16_t ct_dport; /* RS port for template connection */ - bool outwall; }; struct conn_tuple_hash { @@ -165,9 +164,6 @@ struct dp_vs_conn { /* connection redirect in fnat/snat/nat modes */ struct dp_vs_redirect *redirect; - /* flag for gfwip */ - bool outwall; - } __rte_cache_aligned; /* for syn-proxy to save all ack packet in conn before rs's syn-ack arrives */ diff --git a/include/ipvs/ipvs.h b/include/ipvs/ipvs.h index 04f823686..becabe6ac 100644 --- a/include/ipvs/ipvs.h +++ b/include/ipvs/ipvs.h @@ -53,7 +53,6 @@ struct dp_vs_service; struct dp_vs_conn *dp_vs_schedule(struct dp_vs_service *svc, const struct dp_vs_iphdr *iph, struct rte_mbuf *mbuf, - bool is_synproxy_on, - bool outwall); + bool is_synproxy_on); #endif /* __DPVS_IPVS_H__ */ diff --git a/include/ipvs/service.h b/include/ipvs/service.h index 8ef66b902..2b12e05bb 100644 --- a/include/ipvs/service.h +++ b/include/ipvs/service.h @@ -102,7 +102,7 @@ dp_vs_service_lookup(int af, uint16_t protocol, uint16_t vport, uint32_t fwmark, const struct rte_mbuf *mbuf, const struct dp_vs_match *match, - bool *outwall, lcoreid_t cid); + lcoreid_t cid); void dp_vs_service_bind(struct dp_vs_dest *dest, struct dp_vs_service *svc); diff --git a/include/route.h b/include/route.h index 55c61a2c0..66de7af9f 100644 --- a/include/route.h +++ b/include/route.h @@ -105,5 +105,4 @@ int route_del(struct in_addr* dest,uint8_t netmask, uint32_t flag, struct in_addr* gw, struct netif_port *port, struct in_addr* src, unsigned long mtu,short metric); -struct route_entry *route_gfw_net_lookup(const struct in_addr *dest); #endif diff --git a/src/ipvs/ip_vs_conn.c b/src/ipvs/ip_vs_conn.c index f88ae0e29..ef1c5d3c0 100644 --- a/src/ipvs/ip_vs_conn.c +++ b/src/ipvs/ip_vs_conn.c @@ -879,7 +879,6 @@ struct dp_vs_conn *dp_vs_conn_new(struct rte_mbuf *mbuf, else new->daddr = dest->addr; new->dport = rport; - new->outwall = param->outwall; /* neighbour confirm cache */ if (AF_INET == tuplehash_in(new).af) { diff --git a/src/ipvs/ip_vs_core.c b/src/ipvs/ip_vs_core.c index 85fa206eb..b92e98496 100644 --- a/src/ipvs/ip_vs_core.c +++ b/src/ipvs/ip_vs_core.c @@ -182,8 +182,7 @@ static struct dp_vs_conn *dp_vs_sched_persist(struct dp_vs_service *svc, static struct dp_vs_conn *dp_vs_snat_schedule(struct dp_vs_dest *dest, const struct dp_vs_iphdr *iph, uint16_t *ports, - struct rte_mbuf *mbuf, - bool outwall) + struct rte_mbuf *mbuf) { int err; struct dp_vs_conn *conn; @@ -263,7 +262,6 @@ static struct dp_vs_conn *dp_vs_snat_schedule(struct dp_vs_dest *dest, ports[1], saddr6->sin6_port, 0, ¶m); } } - param.outwall = outwall; conn = dp_vs_conn_new(mbuf, iph, ¶m, dest, 0); if (!conn) { sa_release(NULL, &daddr, &saddr); @@ -278,8 +276,7 @@ static struct dp_vs_conn *dp_vs_snat_schedule(struct dp_vs_dest *dest, struct dp_vs_conn *dp_vs_schedule(struct dp_vs_service *svc, const struct dp_vs_iphdr *iph, struct rte_mbuf *mbuf, - bool is_synproxy_on, - bool outwall) + bool is_synproxy_on) { uint16_t _ports[2], *ports; /* sport, dport */ struct dp_vs_dest *dest; @@ -307,7 +304,7 @@ struct dp_vs_conn *dp_vs_schedule(struct dp_vs_service *svc, } if (dest->fwdmode == DPVS_FWD_MODE_SNAT) - return dp_vs_snat_schedule(dest, iph, ports, mbuf, outwall); + return dp_vs_snat_schedule(dest, iph, ports, mbuf); if (unlikely(iph->proto == IPPROTO_ICMP)) { struct icmphdr *ich, _icmph; diff --git a/src/ipvs/ip_vs_dest.c b/src/ipvs/ip_vs_dest.c index 0a337f9a9..8564c6ebe 100644 --- a/src/ipvs/ip_vs_dest.c +++ b/src/ipvs/ip_vs_dest.c @@ -439,7 +439,7 @@ static struct dp_vs_dest *get_dest_from_notification(const struct dest_notificat struct dp_vs_service *svc; svc = dp_vs_service_lookup(notice->svc_af, notice->proto, ¬ice->vaddr, notice->vport, - 0, NULL, NULL, NULL, rte_lcore_id()); + 0, NULL, NULL, rte_lcore_id()); if (!svc) return NULL; return dp_vs_dest_lookup(notice->af, svc, ¬ice->daddr, notice->dport); @@ -770,7 +770,7 @@ static int dp_vs_dest_set(sockoptid_t opt, const void *user, size_t len) msg_destroy(&msg); } - getsvc = dp_vs_service_lookup(insvc->af, insvc->proto, &insvc->addr, insvc->port, insvc->fwmark, NULL, &insvc->match, NULL, cid); + getsvc = dp_vs_service_lookup(insvc->af, insvc->proto, &insvc->addr, insvc->port, insvc->fwmark, NULL, &insvc->match, cid); if (!getsvc || getsvc->proto != insvc->proto) { return EDPVS_INVAL; } @@ -839,7 +839,7 @@ static int dp_vs_dest_get(sockoptid_t opt, const void *user, size_t len, void ** } if (cid == rte_get_main_lcore()) { - getsvc = dp_vs_service_lookup(insvc->af, insvc->proto, &insvc->addr, insvc->port, insvc->fwmark, NULL, &insvc->match, NULL, cid); + getsvc = dp_vs_service_lookup(insvc->af, insvc->proto, &insvc->addr, insvc->port, insvc->fwmark, NULL, &insvc->match, cid); if (!getsvc) { msg_destroy(&msg); return EDPVS_NOTEXIST; @@ -950,7 +950,7 @@ static int dp_vs_dests_get_uc_cb(struct dpvs_msg *msg) struct dp_vs_service *svc; get = (struct dp_vs_dest_front*)msg->data; - svc = dp_vs_service_lookup(get->af, get->proto, &get->addr, get->port, get->fwmark, NULL, &get->match, NULL, cid); + svc = dp_vs_service_lookup(get->af, get->proto, &get->addr, get->port, get->fwmark, NULL, &get->match, cid); if (!svc) return EDPVS_NOTEXIST; diff --git a/src/ipvs/ip_vs_laddr.c b/src/ipvs/ip_vs_laddr.c index b6fca2810..4f15005a9 100644 --- a/src/ipvs/ip_vs_laddr.c +++ b/src/ipvs/ip_vs_laddr.c @@ -542,10 +542,8 @@ static int laddr_sockopt_set(sockoptid_t opt, const void *conf, size_t size) } #endif - svc = dp_vs_service_lookup(af, proto, - addr, port, - fwmark, NULL, match, - NULL, rte_lcore_id()); + svc = dp_vs_service_lookup(af, proto, addr, port, + fwmark, NULL, match, rte_lcore_id()); if (!svc) return EDPVS_NOSERV; @@ -609,8 +607,7 @@ static int agent_get_msg_cb(struct dpvs_msg *msg) svc = dp_vs_service_lookup(laddr_conf->af, laddr_conf->proto, &laddr_conf->addr, laddr_conf->port, - laddr_conf->fwmark, NULL, &laddr_conf->match, - NULL, cid); + laddr_conf->fwmark, NULL, &laddr_conf->match, cid); if (!svc) { return EDPVS_NOSERV; } @@ -662,8 +659,7 @@ static int get_msg_cb(struct dpvs_msg *msg) svc = dp_vs_service_lookup(laddr_conf->af_s, laddr_conf->proto, &laddr_conf->vaddr, laddr_conf->vport, - laddr_conf->fwmark, NULL, &laddr_conf->match, - NULL, cid); + laddr_conf->fwmark, NULL, &laddr_conf->match, cid); if (!svc) { return EDPVS_NOSERV; } @@ -755,7 +751,7 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, if (cid == rte_get_main_lcore()) { svc = dp_vs_service_lookup(laddr_conf->af_s, laddr_conf->proto, &laddr_conf->vaddr, laddr_conf->vport, - laddr_conf->fwmark, NULL, &laddr_conf->match, NULL, cid); + laddr_conf->fwmark, NULL, &laddr_conf->match, cid); if (!svc) { msg_destroy(&msg); return EDPVS_NOSERV; @@ -845,7 +841,9 @@ static int laddr_sockopt_get(sockoptid_t opt, const void *conf, size_t size, return EDPVS_MSG_FAIL; } - svc = dp_vs_service_lookup(laddr_front->af, laddr_front->proto, &laddr_front->addr, laddr_front->port, laddr_front->fwmark, NULL, &laddr_front->match, NULL, rte_get_main_lcore()); + svc = dp_vs_service_lookup(laddr_front->af, laddr_front->proto, + &laddr_front->addr, laddr_front->port, laddr_front->fwmark, + NULL, &laddr_front->match, rte_get_main_lcore()); if (!svc) { msg_destroy(&msg); return EDPVS_NOSERV; diff --git a/src/ipvs/ip_vs_proto_icmp.c b/src/ipvs/ip_vs_proto_icmp.c index 8aebff195..37d9f2ad3 100644 --- a/src/ipvs/ip_vs_proto_icmp.c +++ b/src/ipvs/ip_vs_proto_icmp.c @@ -81,7 +81,6 @@ static int icmp_conn_sched(struct dp_vs_proto *proto, void *ich = NULL; struct dp_vs_service *svc; int af = iph->af; - bool outwall = false; assert(proto && iph && mbuf && conn && verdict); if (AF_INET6 == af) { @@ -100,14 +99,14 @@ static int icmp_conn_sched(struct dp_vs_proto *proto, } svc = dp_vs_service_lookup(iph->af, iph->proto, &iph->daddr, 0, 0, - mbuf, NULL, &outwall, rte_lcore_id()); + mbuf, NULL, rte_lcore_id()); if (!svc) { *verdict = INET_ACCEPT; return EDPVS_NOSERV; } /* schedule RS and create new connection */ - *conn = dp_vs_schedule(svc, iph, mbuf, false, outwall); + *conn = dp_vs_schedule(svc, iph, mbuf, false); if (!*conn) { *verdict = INET_DROP; return EDPVS_RESOURCE; diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 244722a5d..713e0aaa3 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -612,7 +612,6 @@ static int tcp_conn_sched(struct dp_vs_proto *proto, { struct tcphdr *th, _tcph; struct dp_vs_service *svc; - bool outwall = false; assert(proto && iph && mbuf && conn && verdict); @@ -661,7 +660,7 @@ static int tcp_conn_sched(struct dp_vs_proto *proto, } svc = dp_vs_service_lookup(iph->af, iph->proto, &iph->daddr, th->dest, - 0, mbuf, NULL, &outwall, rte_lcore_id()); + 0, mbuf, NULL, rte_lcore_id()); if (!svc) { /* Drop tcp packet which is send to vip and !vport */ if (g_defence_tcp_drop && @@ -675,7 +674,7 @@ static int tcp_conn_sched(struct dp_vs_proto *proto, return EDPVS_NOSERV; } - *conn = dp_vs_schedule(svc, iph, mbuf, false, outwall); + *conn = dp_vs_schedule(svc, iph, mbuf, false); if (!*conn) { *verdict = INET_DROP; return EDPVS_RESOURCE; diff --git a/src/ipvs/ip_vs_proto_udp.c b/src/ipvs/ip_vs_proto_udp.c index 0a3a51b85..b71d9d7d8 100644 --- a/src/ipvs/ip_vs_proto_udp.c +++ b/src/ipvs/ip_vs_proto_udp.c @@ -156,7 +156,6 @@ static int udp_conn_sched(struct dp_vs_proto *proto, { struct rte_udp_hdr *uh, _udph; struct dp_vs_service *svc; - bool outwall = false; assert(proto && iph && mbuf && conn && verdict); uh = mbuf_header_pointer(mbuf, iph->len, sizeof(_udph), &_udph); @@ -167,14 +166,14 @@ static int udp_conn_sched(struct dp_vs_proto *proto, /* lookup service */ svc = dp_vs_service_lookup(iph->af, iph->proto, &iph->daddr, - uh->dst_port, 0, mbuf, NULL, &outwall, rte_lcore_id()); + uh->dst_port, 0, mbuf, NULL, rte_lcore_id()); if (!svc) { *verdict = INET_ACCEPT; return EDPVS_NOSERV; } /* schedule RS and create new connection */ - *conn = dp_vs_schedule(svc, iph, mbuf, false, outwall); + *conn = dp_vs_schedule(svc, iph, mbuf, false); if (!*conn) { *verdict = INET_DROP; return EDPVS_RESOURCE; diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index 839b4828e..27ca3a7e7 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -196,7 +196,7 @@ static inline bool __service_in_range(int af, } static struct dp_vs_service * -__dp_vs_service_match_get4(const struct rte_mbuf *mbuf, bool *outwall, lcoreid_t cid) +__dp_vs_service_match_get4(const struct rte_mbuf *mbuf, lcoreid_t cid) { struct route_entry *rt = MBUF_USERDATA_CONST(mbuf, struct route_entry *, MBUF_FIELD_ROUTE); struct rte_ipv4_hdr *iph = ip4_hdr(mbuf); /* ipv4 only */ @@ -217,10 +217,6 @@ __dp_vs_service_match_get4(const struct rte_mbuf *mbuf, bool *outwall, lcoreid_t if ((rt->flag & RTF_KNI) || (rt->flag & RTF_LOCALIN)) return NULL; oif = rt->port->id; - } else if (outwall != NULL && (rt = route_gfw_net_lookup(&daddr.in))) { - oif = rt->port->id; - route4_put(rt); - *outwall = true; } else { rt = route4_input(mbuf, &daddr.in, &saddr.in, iph->type_of_service, @@ -331,10 +327,10 @@ __dp_vs_service_match_get6(const struct rte_mbuf *mbuf, lcoreid_t cid) } static struct dp_vs_service * -__dp_vs_service_match_get(int af, const struct rte_mbuf *mbuf, bool *outwall, lcoreid_t cid) +__dp_vs_service_match_get(int af, const struct rte_mbuf *mbuf, lcoreid_t cid) { if (af == AF_INET) - return __dp_vs_service_match_get4(mbuf, outwall, cid); + return __dp_vs_service_match_get4(mbuf, cid); else if (af == AF_INET6) return __dp_vs_service_match_get6(mbuf, cid); else @@ -367,7 +363,7 @@ struct dp_vs_service *dp_vs_service_lookup(int af, uint16_t protocol, uint16_t vport, uint32_t fwmark, const struct rte_mbuf *mbuf, const struct dp_vs_match *match, - bool *outwall, lcoreid_t cid) + lcoreid_t cid) { struct dp_vs_service *svc = NULL; @@ -382,7 +378,7 @@ struct dp_vs_service *dp_vs_service_lookup(int af, uint16_t protocol, goto out; if (mbuf) /* lowest priority */ - svc = __dp_vs_service_match_get(af, mbuf, outwall, cid); + svc = __dp_vs_service_match_get(af, mbuf, cid); out: #ifdef CONFIG_DPVS_MBUF_DEBUG diff --git a/src/ipvs/ip_vs_synproxy.c b/src/ipvs/ip_vs_synproxy.c index 6dbdcb0c2..902c4d55c 100644 --- a/src/ipvs/ip_vs_synproxy.c +++ b/src/ipvs/ip_vs_synproxy.c @@ -726,8 +726,7 @@ int dp_vs_synproxy_syn_rcv(int af, struct rte_mbuf *mbuf, if (th->syn && !th->ack && !th->rst && !th->fin && (svc = dp_vs_service_lookup(af, iph->proto, &iph->daddr, th->dest, 0, - NULL, NULL, NULL, rte_lcore_id())) && - (svc->flags & DP_VS_SVC_F_SYNPROXY)) { + NULL, NULL, rte_lcore_id())) && (svc->flags & DP_VS_SVC_F_SYNPROXY)) { /* if service's weight is zero (non-active realserver), * do noting and drop the packet */ if (svc->weight == 0) { @@ -1178,7 +1177,7 @@ int dp_vs_synproxy_ack_rcv(int af, struct rte_mbuf *mbuf, /* Do not check svc syn-proxy flag, as it may be changed after syn-proxy step 1. */ if (!th->syn && th->ack && !th->rst && !th->fin && (svc = dp_vs_service_lookup(af, iph->proto, &iph->daddr, - th->dest, 0, NULL, NULL, NULL, rte_lcore_id()))) { + th->dest, 0, NULL, NULL, rte_lcore_id()))) { if (dp_vs_synproxy_ctrl_defer && !syn_proxy_ack_has_data(mbuf, iph, th)) { /* Update statistics */ @@ -1214,7 +1213,7 @@ int dp_vs_synproxy_ack_rcv(int af, struct rte_mbuf *mbuf, /* Let the virtual server select a real server for the incoming connetion, * and create a connection entry */ - *cpp = dp_vs_schedule(svc, iph, mbuf, 1, 0); + *cpp = dp_vs_schedule(svc, iph, mbuf, 1); if (unlikely(!*cpp)) { RTE_LOG(WARNING, IPVS, "%s: ip_vs_schedule failed\n", __func__); /* FIXME: What to do when virtual service is available but no destination diff --git a/src/ipvs/ip_vs_xmit.c b/src/ipvs/ip_vs_xmit.c index 2fb7270c1..d9a359ce8 100644 --- a/src/ipvs/ip_vs_xmit.c +++ b/src/ipvs/ip_vs_xmit.c @@ -1520,20 +1520,11 @@ static int __dp_vs_out_xmit_snat4(struct dp_vs_proto *proto, fl4.fl4_daddr = conn->caddr.in; fl4.fl4_saddr = conn->vaddr.in; fl4.fl4_tos = iph->type_of_service; - - if (conn->outwall) { - rt = route_gfw_net_lookup(&conn->caddr.in); - if (!rt) { - err = EDPVS_NOROUTE; - goto errout; - } - } else { - rt = route4_output(&fl4); - if (!rt) { - err = EDPVS_NOROUTE; - goto errout; - } + rt = route4_output(&fl4); + if (!rt) { + err = EDPVS_NOROUTE; + goto errout; } MBUF_USERDATA(mbuf, struct route_entry *, MBUF_FIELD_ROUTE) = rt; diff --git a/src/route.c b/src/route.c index 7a8115df3..00354f7c8 100644 --- a/src/route.c +++ b/src/route.c @@ -28,14 +28,11 @@ #define NET_ROUTE_TAB_SIZE 8 #define NET_ROUTE_TAB_MASK (NET_ROUTE_TAB_SIZE - 1) +#define this_num_routes (RTE_PER_LCORE(num_routes)) #define this_route_lcore (RTE_PER_LCORE(route_lcore)) #define this_local_route_table (this_route_lcore.local_route_table) #define this_net_route_table (this_route_lcore.net_route_table) -#define this_gfw_route_table (this_route_lcore.gfw_route_table) - -#define this_num_routes (RTE_PER_LCORE(num_routes)) -#define this_num_out_routes (RTE_PER_LCORE(num_out_routes)) /** * use per-lcore structure for lockless @@ -44,12 +41,10 @@ struct route_lcore { struct list_head local_route_table[LOCAL_ROUTE_TAB_SIZE]; struct list_head net_route_table; - struct list_head gfw_route_table; }; static RTE_DEFINE_PER_LCORE(struct route_lcore, route_lcore); static RTE_DEFINE_PER_LCORE(rte_atomic32_t, num_routes); -static RTE_DEFINE_PER_LCORE(rte_atomic32_t, num_out_routes); static int route_msg_seq(void) { @@ -124,10 +119,6 @@ static int route_net_add(struct in_addr *dest, uint8_t netmask, uint32_t flag, struct route_entry *route_node, *route; struct list_head *route_table = &this_net_route_table; - if (flag & RTF_OUTWALL) { - route_table = &this_gfw_route_table; - } - list_for_each_entry(route_node, route_table, list){ if (net_cmp(port, dest->s_addr, netmask, route_node) && (netmask == route_node->netmask)){ @@ -141,10 +132,7 @@ static int route_net_add(struct in_addr *dest, uint8_t netmask, uint32_t flag, } __list_add(&route->list, (&route_node->list)->prev, &route_node->list); - if (flag & RTF_OUTWALL) - rte_atomic32_inc(&this_num_out_routes); - else - rte_atomic32_inc(&this_num_routes); + rte_atomic32_inc(&this_num_routes); rte_atomic32_inc(&route->refcnt); return EDPVS_OK; } @@ -155,10 +143,7 @@ static int route_net_add(struct in_addr *dest, uint8_t netmask, uint32_t flag, return EDPVS_NOMEM; } list_add_tail(&route->list, route_table); - if (flag & RTF_OUTWALL) - rte_atomic32_inc(&this_num_out_routes); - else - rte_atomic32_inc(&this_num_routes); + rte_atomic32_inc(&this_num_routes); rte_atomic32_inc(&route->refcnt); return EDPVS_OK; } @@ -230,18 +215,6 @@ static struct route_entry *route_out_net_lookup(const struct in_addr *dest) return NULL; } -struct route_entry *route_gfw_net_lookup(const struct in_addr *dest) -{ - struct route_entry *route_node; - list_for_each_entry(route_node, &this_gfw_route_table, list){ - if (net_cmp(route_node->port, dest->s_addr, route_node->netmask, route_node)){ - rte_atomic32_inc(&route_node->refcnt); - return route_node; - } - } - return NULL; -} - static int route_local_add(struct in_addr* dest, uint8_t netmask, uint32_t flag, struct in_addr* gw, struct netif_port *port, struct in_addr* src, unsigned long mtu,short metric) @@ -309,17 +282,6 @@ static int route_del_lcore(struct in_addr* dest,uint8_t netmask, uint32_t flag, return EDPVS_OK; } - if (flag & RTF_OUTWALL) { - route = route_gfw_net_lookup(dest); - if (!route) - return EDPVS_NOTEXIST; - list_del(&route->list); - rte_atomic32_dec(&route->refcnt); - rte_atomic32_dec(&this_num_out_routes); - route4_put(route); - return EDPVS_OK; - } - if(flag & RTF_FORWARD || (flag & RTF_DEFAULT)){ route = route_net_lookup(port, dest, netmask); if (!route) @@ -488,11 +450,6 @@ static int route_lcore_flush(void) route4_put(route_node); } - list_for_each_entry(route_node, &this_gfw_route_table, list){ - list_del(&route_node->list); - rte_atomic32_dec(&this_num_out_routes); - route4_put(route_node); - } return EDPVS_OK; } @@ -721,7 +678,6 @@ static int route_lcore_init(void *arg) for (i = 0; i < LOCAL_ROUTE_TAB_SIZE; i++) INIT_LIST_HEAD(&this_local_route_table[i]); INIT_LIST_HEAD(&this_net_route_table); - INIT_LIST_HEAD(&this_gfw_route_table); return EDPVS_OK; } @@ -741,7 +697,6 @@ int route_init(void) struct dpvs_msg_type msg_type; rte_atomic32_set(&this_num_routes, 0); - rte_atomic32_set(&this_num_out_routes, 0); /* master core also need routes */ rte_eal_mp_remote_launch(route_lcore_init, NULL, CALL_MAIN); RTE_LCORE_FOREACH_WORKER(cid) { From 4ff1c75fce497a7c4994d32d517dbfe06f854565 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 21 Sep 2023 11:10:16 +0800 Subject: [PATCH 083/105] keepalived: fix dpvs crash problem in issue #911 Signed-off-by: ywc689 --- include/conf/dest.h | 7 ------- tools/keepalived/keepalived/check/ipvswrapper.c | 7 ------- 2 files changed, 14 deletions(-) diff --git a/include/conf/dest.h b/include/conf/dest.h index ba0cf56a1..db81bc40c 100644 --- a/include/conf/dest.h +++ b/include/conf/dest.h @@ -65,13 +65,6 @@ typedef struct dp_vs_dest_compat { /* statistics */ struct dp_vs_stats stats; -#ifdef _HAVE_IPVS_TUN_TYPE_ - int tun_type; - int tun_port; -#ifdef _HAVE_IPVS_TUN_CSUM_ - int tun_flags; -#endif -#endif } dpvs_dest_compat_t; typedef struct dp_vs_dest_table { diff --git a/tools/keepalived/keepalived/check/ipvswrapper.c b/tools/keepalived/keepalived/check/ipvswrapper.c index 8bb1262be..061204db7 100755 --- a/tools/keepalived/keepalived/check/ipvswrapper.c +++ b/tools/keepalived/keepalived/check/ipvswrapper.c @@ -840,13 +840,6 @@ ipvs_set_drule(int cmd, dpvs_dest_compat_t *drule, real_server_t * rs) drule->fwdmode = rs->forwarding_method; drule->max_conn = rs->u_threshold; drule->min_conn = rs->l_threshold; -#ifdef _HAVE_IPVS_TUN_TYPE_ - drule->tun_type = rs->tun_type; - drule->tun_port = rs->tun_port; -#ifdef _HAVE_IPVS_TUN_CSUM_ - drule->tun_flags = rs->tun_flags; -#endif -#endif } /*check whitelist addr*/ From 121e9903f7196342436b59dd06b53199d01b0217 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 17 Oct 2023 17:30:25 +0800 Subject: [PATCH 084/105] test: add demo servers for proxy protocol Signed-off-by: ywc689 --- test/proxy_protocol/.gitignore | 2 + test/proxy_protocol/Makefile | 26 +++ test/proxy_protocol/example.c | 79 +++++++++ test/proxy_protocol/nginx/nginx.conf | 87 ++++++++++ test/proxy_protocol/proxy_protocol.c | 153 +++++++++++++++++ test/proxy_protocol/proxy_protocol.h | 35 ++++ test/proxy_protocol/tcp_server.c | 248 +++++++++++++++++++++++++++ test/proxy_protocol/udp_server.c | 155 +++++++++++++++++ 8 files changed, 785 insertions(+) create mode 100644 test/proxy_protocol/.gitignore create mode 100644 test/proxy_protocol/Makefile create mode 100644 test/proxy_protocol/example.c create mode 100644 test/proxy_protocol/nginx/nginx.conf create mode 100644 test/proxy_protocol/proxy_protocol.c create mode 100644 test/proxy_protocol/proxy_protocol.h create mode 100644 test/proxy_protocol/tcp_server.c create mode 100644 test/proxy_protocol/udp_server.c diff --git a/test/proxy_protocol/.gitignore b/test/proxy_protocol/.gitignore new file mode 100644 index 000000000..48e6b6af8 --- /dev/null +++ b/test/proxy_protocol/.gitignore @@ -0,0 +1,2 @@ +tcp_server +udp_server diff --git a/test/proxy_protocol/Makefile b/test/proxy_protocol/Makefile new file mode 100644 index 000000000..dfe8eed23 --- /dev/null +++ b/test/proxy_protocol/Makefile @@ -0,0 +1,26 @@ +CC = gcc +MAKE = make +RM = rm + +OPTIONS = -DWITH_IPV6_ENABLE +OPTIONS += -DLOG_VERBOSE + +ALL = tcp_server udp_server +OBJS = $(patsubst %.c, %.o, $(shell find $(SRCDIR) -name '*.c' | sort)) +CFLAGS = -g -O0 $(OPTIONS) + +.PHONY: all clean + +all: $(ALL) + +tcp_server: proxy_protocol.o tcp_server.o + $(CC) $(CFLAGS) $^ -o $@ + +udp_server: proxy_protocol.o udp_server.o + $(CC) $(CFLAGS) $^ -o $@ + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm *.o $(ALL) diff --git a/test/proxy_protocol/example.c b/test/proxy_protocol/example.c new file mode 100644 index 000000000..58803fe21 --- /dev/null +++ b/test/proxy_protocol/example.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include "proxy_protocol.h" + +struct sockaddr_storage from; /* already filled by accept() */ +struct sockaddr_storage to; /* already filled by getsockname() */ +const char ppv2sig[] = PPV2SIG; + +/* returns 0 if needs to poll, <0 upon error or >0 if it did the job */ +int read_evt(int fd) +{ + int size, ret; + pphdr_t hdr; + + do { + ret = recv(fd, &hdr, sizeof(hdr), MSG_PEEK); + } while (ret == -1 && errno == EINTR); + + if (ret == -1) + return (errno == EAGAIN) ? 0 : -1; + + if (ret >= 16 && memcmp(&hdr.v2, ppv2sig, 12) == 0 && + (hdr.v2.ver_cmd & 0xF0) == 0x20) { + size = 16 + ntohs(hdr.v2.len); + if (ret < size) + return -1; /* truncated or too large header */ + + switch (hdr.v2.ver_cmd & 0xF) { + case 0x01: /* PROXY command */ + switch (hdr.v2.fam) { + case 0x11: /* TCPv4 */ + ((struct sockaddr_in *)&from)->sin_family = AF_INET; + ((struct sockaddr_in *)&from)->sin_addr.s_addr = hdr.v2.addr.ip4.src_addr; + ((struct sockaddr_in *)&from)->sin_port = hdr.v2.addr.ip4.src_port; + ((struct sockaddr_in *)&to)->sin_family = AF_INET; + ((struct sockaddr_in *)&to)->sin_addr.s_addr = hdr.v2.addr.ip4.dst_addr; + ((struct sockaddr_in *)&to)->sin_port = hdr.v2.addr.ip4.dst_port; + goto done; + case 0x21: /* TCPv6 */ + ((struct sockaddr_in6 *)&from)->sin6_family = AF_INET6; + memcpy(&((struct sockaddr_in6 *)&from)->sin6_addr, hdr.v2.addr.ip6.src_addr, 16); + ((struct sockaddr_in6 *)&from)->sin6_port = hdr.v2.addr.ip6.src_port; + ((struct sockaddr_in6 *)&to)->sin6_family = AF_INET6; + memcpy(&((struct sockaddr_in6 *)&to)->sin6_addr, hdr.v2.addr.ip6.dst_addr, 16); + ((struct sockaddr_in6 *)&to)->sin6_port = hdr.v2.addr.ip6.dst_port; + goto done; + } + /* unsupported protocol, keep local connection address */ + break; + case 0x00: /* LOCAL command */ + /* keep local connection address for LOCAL */ + break; + default: + return -1; /* not a supported command */ + } + } else if (ret >= 8 && memcmp(hdr.v1.line, "PROXY", 5) == 0) { + char *end = memchr(hdr.v1.line, '\r', ret - 1); + if (!end || end[1] != '\n') + return -1; /* partial or invalid header */ + *end = '\0'; /* terminate the string to ease parsing */ + size = end + 2 - hdr.v1.line; /* skip header + CRLF */ + /* parse the V1 header using favorite address parsers like inet_pton. + * return -1 upon error, or simply fall through to accept. + */ + } else { + /* Wrong protocol */ + return -1; + } + +done: + /* we need to consume the appropriate amount of data from the socket */ + do { + ret = recv(fd, &hdr, size, 0); + } while (ret == -1 && errno == EINTR); + return (ret >= 0) ? 1 : -1; +} diff --git a/test/proxy_protocol/nginx/nginx.conf b/test/proxy_protocol/nginx/nginx.conf new file mode 100644 index 000000000..b052fcb60 --- /dev/null +++ b/test/proxy_protocol/nginx/nginx.conf @@ -0,0 +1,87 @@ +## official tutorial doc: +## https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/ +## + +user root root; +worker_processes auto; +worker_cpu_affinity auto; +worker_rlimit_nofile 307200; +error_log /data/nginx/logs/error.log notice; + +pid /var/run/nginx.pid; + + +events { + worker_connections 102400; # max connections will be worker_processes * worker_connections + multi_accept on; # accept as many connections as it can + use epoll; # generally recommended for best throughput + accept_mutex off; +} + +## setup a stream server as the test client +stream { + log_format main '$remote_addr - [$time_local] ' + '$protocol $status $bytes_sent $bytes_received ' + '$session_time'; + + server { + listen 8000; + + error_log /data/nginx/logs/proxy-error.log; + access_log /data/nginx/logs/proxy-access.log main buffer=32k flush=5s; + + proxy_pass 127.0.0.1:8002; + proxy_protocol on; + #proxy_protocol_version 2; # Client supports proxy protocol v1 only for open sourced nginx. + } +} + +http { + include mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + '"$host" "$http_x_original_uri" "$http_proxy_token"'; + + log_format backend '$remote_addr($proxy_protocol_addr:$proxy_protocol_port) ' + '- $remote_user [$time_local] "$request" ' + '$status $upstream_status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + '"$host" "$http_x_original_uri" "$http_proxy_token"'; + + access_log /data/nginx/logs/access.log main; + + sendfile on; + keepalive_timeout 65; + + ## backend server + server { + listen 8002 proxy_protocol; # Server supoorts both proxy protocol v1 and v2. + # V2 requires nginx version >= 1.13.11, refer to + # "http://nginx.org/en/CHANGES" for more details. + + error_log /data/nginx/logs/backend-error.log; + access_log /data/nginx/logs/backend-access.log backend buffer=32k flush=5s; + + charset utf-8; + resolver 127.0.0.1 ipv6=off; + + set_real_ip_from 127.0.0.0/8; + real_ip_header proxy_protocol; + + root /usr/share/nginx/html; + + location / { + index host.html; + } + + location /test { + proxy_pass http://qlb-test.qiyi.domain:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $proxy_protocol_addr; + proxy_set_header X-Forwarded-For $proxy_protocol_addr; + } + } +} diff --git a/test/proxy_protocol/proxy_protocol.c b/test/proxy_protocol/proxy_protocol.c new file mode 100644 index 000000000..3695e3fcb --- /dev/null +++ b/test/proxy_protocol/proxy_protocol.c @@ -0,0 +1,153 @@ +// +// The proxy protocol implementation (server reception side) +// https://www.haproxy.org/download/2.9/doc/proxy-protocol.txt +// +#include +#include +#include +#include "proxy_protocol.h" + +const char ppv2sig[] = PPV2SIG; + +int parse_proxy_protocol(char *buf, int len) { + struct sockaddr_storage from = { 0 }, to = { 0 }; + size_t pplen; + pphdr_t *phdr; + char ppv1data[108], *token, *tmp, *end; + char frombuf[64], tobuf[64]; + + phdr = (pphdr_t *)buf; + if (len >= 16 && memcmp(&phdr->v2, ppv2sig, 12) == 0 && + (phdr->v2.ver_cmd & 0xF0) == 0x20) { // PPv2 + pplen = 16 + ntohs(phdr->v2.len); + if (pplen > len) // invalid PPv2 + return len; + switch (phdr->v2.ver_cmd & 0xF) { + case 0x01: // PROXY command + switch (phdr->v2.fam) { + case 0x11: // TCPv4 + case 0x12: // UDPv4 + ((struct sockaddr_in *)&from)->sin_family = AF_INET; + ((struct sockaddr_in *)&from)->sin_addr.s_addr = phdr->v2.addr.ip4.src_addr; + ((struct sockaddr_in *)&from)->sin_port = phdr->v2.addr.ip4.src_addr; + ((struct sockaddr_in *)&to)->sin_family = AF_INET; + ((struct sockaddr_in *)&to)->sin_addr.s_addr = phdr->v2.addr.ip4.dst_addr; + ((struct sockaddr_in *)&to)->sin_port = phdr->v2.addr.ip4.dst_addr; + goto done; + case 0x21: // TCPv6 + case 0x22: // UDPv6 + ((struct sockaddr_in6 *)&from)->sin6_family = AF_INET6; + memcpy(&((struct sockaddr_in6 *)&from)->sin6_addr, &phdr->v2.addr.ip6.src_addr, 16); + ((struct sockaddr_in6 *)&from)->sin6_port = phdr->v2.addr.ip6.src_port; + ((struct sockaddr_in6 *)&to)->sin6_family = AF_INET6; + memcpy(&((struct sockaddr_in6 *)&to)->sin6_addr, &phdr->v2.addr.ip6.dst_addr, 16); + ((struct sockaddr_in6 *)&to)->sin6_port = phdr->v2.addr.ip6.dst_port; + goto done; + default: // unsupported protocol + break; + break; + } + case 0x00: // LOCAL command + goto done; + default: // unsupported command + break; + } + } else if (len >= 8 && memcmp(phdr->v1.line, "PROXY", 5) == 0) { // PPv1 + end = index((char *)phdr, '\n'); + if (NULL == end || end + 1 - (char *)phdr > 107) // invalid PPv1 + return len; + pplen = end + 1 - (char *)phdr; + + memcpy(ppv1data, phdr, pplen); + if (ppv1data[pplen-1] != '\n') + return len; + ppv1data[pplen-1] = '\0'; + if (pplen > 1 && ppv1data[pplen-2] == '\r') + ppv1data[pplen-2] = '\0'; + + if (NULL == (token = strtok_r((char *)ppv1data, " ", &tmp))) // "PROXY" + return len; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // "TCP4|TCP6" + return len; + if (memcmp(token, "TCP4", 4) == 0) { + ((struct sockaddr_in *)&from)->sin_family = AF_INET; + ((struct sockaddr_in *)&to)->sin_family = AF_INET; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // source IP + return len; + if (1 != inet_pton(AF_INET, token, &(((struct sockaddr_in *)&from)->sin_addr))) + return len; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // dest IP + return len; + if (1 != inet_pton(AF_INET, token, &(((struct sockaddr_in *)&to)->sin_addr))) + return len; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // source port + return len; + ((struct sockaddr_in *)&from)->sin_port = htons(strtol(token, &end, 10)); + if (*end != '\0') + return len; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // dest port + return len; + ((struct sockaddr_in *)&to)->sin_port = htons(strtol(token, &end, 10)); + if (*end != '\0') + return len; + if (NULL != strtok_r(NULL, " ", &tmp)) + return len; + goto done; + } else if (memcmp(token, "TCP6", 4) == 0) { + ((struct sockaddr_in6 *)&from)->sin6_family = AF_INET6; + ((struct sockaddr_in6 *)&to)->sin6_family = AF_INET6; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // source IP + return len; + if (1 != inet_pton(AF_INET6, token, &(((struct sockaddr_in6 *)&from)->sin6_addr))) + return len; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // dest IP + return len; + if (1 != inet_pton(AF_INET6, token, &(((struct sockaddr_in6 *)&to)->sin6_addr))) + return len; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // source port + return len; + ((struct sockaddr_in6 *)&from)->sin6_port = ntohs(strtol(token, &end, 10)); + if (*end != '\0') + return len; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // dest port + return len; + ((struct sockaddr_in6 *)&to)->sin6_port = ntohs(strtol(token, &end, 10)); + if (*end != '\0') + return len; + if (NULL != strtok_r(NULL, " ", &tmp)) + return len; + goto done; + } else if (memcmp(token, "UNKNOWN", 7) == 0) { // LOCAL command + if (NULL != strtok_r(NULL, " ", &tmp)) + goto done; + return len; + } else { // unsupported protocol + // UDP4, UDP6 are not supported in v1 + return len; + } + } else { // no or invalid proxy protocol + } + return len; +done: + if (from.ss_family == AF_INET) { + inet_ntop(from.ss_family, &((struct sockaddr_in *)&from)->sin_addr, frombuf, sizeof(frombuf)); + inet_ntop(from.ss_family, &((struct sockaddr_in *)&to)->sin_addr, tobuf, sizeof(tobuf)); + printf("original connection from proxy protocol: %s:%d -> %s:%d\n", + frombuf, ntohs(((struct sockaddr_in *)&from)->sin_port), + tobuf, ntohs(((struct sockaddr_in *)&to)->sin_port)); + } else if (from.ss_family == AF_INET6) { + inet_ntop(from.ss_family, &((struct sockaddr_in6 *)&from)->sin6_addr, frombuf, sizeof(frombuf)); + inet_ntop(from.ss_family, &((struct sockaddr_in6 *)&to)->sin6_addr, tobuf, sizeof(tobuf)); + printf("original connection from proxy protocol: [%s]:%d -> [%s]:%d\n", + frombuf, ntohs(((struct sockaddr_in6 *)&from)->sin6_port), + tobuf, ntohs(((struct sockaddr_in6 *)&to)->sin6_port)); + } + // strip the proxy protocol data + if (pplen < len) { + memmove(buf, buf + pplen, len - pplen); + } else { + memset(buf, 0, len); + } + // return the left data length + return len - pplen; +} diff --git a/test/proxy_protocol/proxy_protocol.h b/test/proxy_protocol/proxy_protocol.h new file mode 100644 index 000000000..87a370485 --- /dev/null +++ b/test/proxy_protocol/proxy_protocol.h @@ -0,0 +1,35 @@ +#include + +#define PPV2SIG "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A"; + +typedef union { + struct { + char line[108]; + } v1; + struct { + uint8_t sig[12]; + uint8_t ver_cmd; + uint8_t fam; + uint16_t len; + union { + struct { /* for TCP/UDP over IPv4, len = 12 */ + uint32_t src_addr; + uint32_t dst_addr; + uint16_t src_port; + uint16_t dst_port; + } ip4; + struct { /* for TCP/UDP over IPv6, len = 36 */ + uint8_t src_addr[16]; + uint8_t dst_addr[16]; + uint16_t src_port; + uint16_t dst_port; + } ip6; + struct { /* for AF_UNIX sockets, len = 216 */ + uint8_t src_addr[108]; + uint8_t dst_addr[108]; + } unx; + } addr; + } v2; +} pphdr_t; + +int parse_proxy_protocol(char *buf, int len); diff --git a/test/proxy_protocol/tcp_server.c b/test/proxy_protocol/tcp_server.c new file mode 100644 index 000000000..e245a3be5 --- /dev/null +++ b/test/proxy_protocol/tcp_server.c @@ -0,0 +1,248 @@ +// +// This is a simple TCP echo server supports Proxy Protocol. +// Client address encoded in Proxy Protocol is parsed and output to stdout. +// + +#include +#include +#include +#include +#include +#include "proxy_protocol.h" +#include + +#define DEFAULT_SERV_PORT 8082 +#define AFS 2 +#define LISTEN_BACKLOG 16 +#define EPOLL_EVENTS 32 + +static int listen_fds[AFS] = { 0 }; + +struct evdata { + int fd; + int af; + uint16_t firstseg; + uint16_t port; + union { + struct in_addr in; + struct in6_addr in6; + } addr; +}; + +static int handle_accept(int af, int epfd, int listen_fd) { + int fd; + socklen_t caddrlen; + struct sockaddr_storage caddr; + char addrbuf[64] = { 0 }; + struct sockaddr_in *caddr4; +#ifdef WITH_IPV6_ENABLE + struct sockaddr_in6 *caddr6; +#endif + struct epoll_event ev; + struct evdata *pdata; + + caddrlen = sizeof(caddr); + fd = accept(listen_fd, (struct sockaddr *)&caddr, &caddrlen); + if (fd == -1) { + fprintf(stderr, "accept connection failed: %d, %s\n", af, strerror(errno)); + return -1; + } + + pdata = calloc(1, sizeof(struct evdata)); + if (!pdata) + return -1; + pdata->af = af; + pdata->fd = fd; + pdata->firstseg = 1; + + if (af == AF_INET) { + caddr4 = (struct sockaddr_in *)&caddr; + pdata->addr.in.s_addr = caddr4->sin_addr.s_addr; + pdata->port = htons(caddr4->sin_port); + inet_ntop(AF_INET, &caddr4->sin_addr, addrbuf, sizeof(addrbuf)); + printf("accept connection %d from %s:%d\n", fd, addrbuf, htons(caddr4->sin_port)); + } +#ifdef WITH_IPV6_ENABLE + else { + caddr6 = (struct sockaddr_in6 *)&caddr; + memcpy(&pdata->addr.in6, &caddr6->sin6_addr, sizeof(struct in6_addr)); + pdata->port = htons(caddr6->sin6_port); + inet_ntop(AF_INET6, &caddr6->sin6_addr, addrbuf, sizeof(addrbuf)); + printf("accept connection %d from [%s]:%d\n", fd, addrbuf, htons(caddr6->sin6_port)); + } +#endif + + memset(&ev, 0, sizeof(ev)); + ev.data.ptr = pdata; + ev.events = EPOLLIN | EPOLLERR; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) != 0) { + fprintf(stderr, "add accepted connection to epoll failed"); + free(pdata); + return -1; + } + + return 0; +} + +static int handle_reply(int epfd, struct evdata *pdata) { + char *buf, addrbuf[64]; + int len; + + buf = (char *)calloc(1, 2048); + if (!buf) + return -1; + len = read(pdata->fd, buf, 2047); + if (len == 0) { // received EOF + inet_ntop(pdata->af, &pdata->addr, addrbuf, sizeof(addrbuf)); + printf("close connection %s:%d\n", addrbuf, pdata->port); + epoll_ctl(epfd, EPOLL_CTL_DEL, pdata->fd, NULL); + close(pdata->fd); + free(pdata); + return 0; + } + buf[len] = '\0'; + +#ifdef LOG_VERBOSE + printf("%d bytes received: %s\n", len, buf); +#endif + + if (pdata->firstseg) { + len = parse_proxy_protocol(buf, len); + if (len > 0) + write(pdata->fd, buf, len); + pdata->firstseg = 0; + buf[len] = '\0'; + } +#ifdef LOG_VERBOSE + printf("%d bytes written back: %s\n", len, buf); +#endif + + free(buf); + return 0; +} + +int main(int argc, char *argv[]) { + int epfd; + int i, nfds; + int enable = 1; + int serv_port; + struct evdata *pdata, evdata[2] = { 0 }; + struct epoll_event ev; + struct epoll_event events[EPOLL_EVENTS]; + struct sockaddr_in serv_addr; +#ifdef WITH_IPV6_ENABLE + struct sockaddr_in6 serv_addr6; +#endif + char addrbuf[64]; + + if (argc > 1) + serv_port = atoi(argv[1]); + if (serv_port <= 0 || serv_port > 65535) + serv_port = DEFAULT_SERV_PORT; + + if ((epfd = epoll_create1(0)) < 0) { + perror("Fail to create epoll fd!\n"); + exit(1); + } + + if ((listen_fds[0] = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Fail to create INET socket!\n"); + exit(1); + } + setsockopt(listen_fds[0], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + setsockopt(listen_fds[0], SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); + + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(serv_port); + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(listen_fds[0], (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) { + perror("Fail to bind INET socket!\n"); + exit(1); + } + + if (listen(listen_fds[0], LISTEN_BACKLOG) < 0) { + perror("Fail to listen INET socket!\n"); + exit(1); + } + + evdata[0].af = AF_INET; + evdata[0].fd = listen_fds[0]; + evdata[0].port = serv_port; + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN | EPOLLERR; + ev.data.ptr = &evdata[0]; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fds[0], &ev) != 0) { + perror("EPOLL_CTL_ADD failed for INET fd!\n"); + exit(1); + } + +#ifdef WITH_IPV6_ENABLE + if ((listen_fds[1] = socket(AF_INET6, SOCK_STREAM, 0)) < 0) { + perror("Fail to create INET6 socket!\n"); + exit(1); + } + setsockopt(listen_fds[1], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + setsockopt(listen_fds[1], SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); + + memset(&serv_addr6, 0, sizeof(serv_addr6)); + serv_addr6.sin6_family = AF_INET6; + serv_addr6.sin6_port = htons(serv_port); + serv_addr6.sin6_addr = in6addr_any; + if (bind(listen_fds[1], (struct sockaddr *)&serv_addr6, sizeof(serv_addr6)) != 0) { + perror("Fail to bind INET6 socket!\n"); + exit(1); + } + + if (listen(listen_fds[1], LISTEN_BACKLOG) < 0) { + perror("Fail to listen INET6 socket!\n"); + exit(1); + } + + evdata[1].af = AF_INET6; + evdata[1].fd = listen_fds[1]; + evdata[1].port = serv_port; + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN | EPOLLERR; + ev.data.ptr = &evdata[1]; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, listen_fds[1], &ev) != 0) { + perror("EPOLL_CTL_ADD failed for INET6 fd!\n"); + exit(1); + } +#endif + + while (1) { + nfds = epoll_wait(epfd, events, EPOLL_EVENTS, -1); + if (nfds == -1) { + perror("epoll_wait failed!\n"); + exit(1); + } + + for (i = 0; i < nfds; i++) { + pdata = (struct evdata *)events[i].data.ptr; + if (pdata->fd == listen_fds[0]) { + handle_accept(AF_INET, epfd, pdata->fd); + } +#ifdef WITH_IPV6_ENABLE + else if (((struct evdata *)events[i].data.ptr)->fd == listen_fds[1]) { + handle_accept(AF_INET6, epfd, pdata->fd); + } +#endif + else { + if (events[i].events & EPOLLERR) { + inet_ntop(pdata->af, &pdata->addr, addrbuf, sizeof(addrbuf)); + fprintf(stderr, "error occurred, close connection %s:%d\n", addrbuf, pdata->port); + epoll_ctl(epfd, EPOLL_CTL_DEL, pdata->fd, NULL); + close(pdata->fd); + free(pdata); + continue; + } + handle_reply(epfd, pdata); + } + } + } + + return 0; +} diff --git a/test/proxy_protocol/udp_server.c b/test/proxy_protocol/udp_server.c new file mode 100644 index 000000000..48a8cbacb --- /dev/null +++ b/test/proxy_protocol/udp_server.c @@ -0,0 +1,155 @@ +// +// This is a simple UDP echo server supports Proxy Protocol. +// Client address encoded in Proxy Protocol is parsed and output to stdout. +// Note that only proxy protocol v2 supports UDP. +// + +#include +#include +#include +#include +#include +#include "proxy_protocol.h" +#include + +#define DEFAULT_SERV_PORT 8082 +#define AFS 2 +#define EPOLL_EVENTS 2 + +static int sockfd[AFS] = { 0 }; + +static int handle_reply(int epfd, int fd) { + struct sockaddr_storage peer; + char *buf, addrbuf[64]; + int len, addrlen; + uint16_t port; + + buf = (char *)calloc(1, 2048); + if (!buf) + return -1; + + while (1) { + addrlen = sizeof(peer); + len = recvfrom(fd, buf, 2047, 0, (struct sockaddr *)&peer, &addrlen); + if (len < 0) { + if (EAGAIN == errno || EWOULDBLOCK == errno) + break; + perror("recvfrom failed\n"); + exit(1); + } + if (0 == len) + break; + buf[len] = '\0'; + + if (AF_INET == peer.ss_family) { + inet_ntop(AF_INET, &((struct sockaddr_in *)&peer)->sin_addr, addrbuf, sizeof(addrbuf)); + port = ntohs(((struct sockaddr_in *)&peer)->sin_port); + } else { + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&peer)->sin6_addr, addrbuf, sizeof(addrbuf)); + port = ntohs(((struct sockaddr_in6 *)&peer)->sin6_port); + } +#ifdef LOG_VERBOSE + printf("%d bytes received from %s:%d: %s\n", len, addrbuf, port, buf); +#endif + len = parse_proxy_protocol(buf, len); + if (len > 0 && sendto(fd, buf, len, 0, + (const struct sockaddr*)&peer, addrlen) < 0) { + perror("sendto failed\n"); + exit(1); + } +#ifdef LOG_VERBOSE + printf("%d bytes written back to %s:%d: %s\n", len, addrbuf, port, buf); +#endif + } + + free(buf); + return 0; +} + +int main(int argc, char *argv[]) { + int epfd; + int i, nfds; + int enable = 1; + int serv_port; + struct epoll_event ev; + struct epoll_event events[EPOLL_EVENTS]; + struct sockaddr_in serv_addr; +#ifdef WITH_IPV6_ENABLE + struct sockaddr_in6 serv_addr6; +#endif + char addrbuf[64]; + + if (argc > 1) + serv_port = atoi(argv[1]); + if (serv_port <= 0 || serv_port > 65535) + serv_port = DEFAULT_SERV_PORT; + + if ((epfd = epoll_create1(0)) < 0) { + perror("Fail to create epoll fd!\n"); + exit(1); + } + + if ((sockfd[0] = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)) < 0) { + perror("Fail to create INET socket!\n"); + exit(1); + } + setsockopt(sockfd[0], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + setsockopt(sockfd[0], SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); + + memset(&serv_addr, 0, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(serv_port); + serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(sockfd[0], (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) { + perror("Fail to bind INET socket!\n"); + exit(1); + } + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN | EPOLLERR; + ev.data.fd = sockfd[0]; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd[0], &ev) != 0) { + perror("EPOLL_CTL_ADD failed for INET fd!\n"); + exit(1); + } + +#ifdef WITH_IPV6_ENABLE + if ((sockfd[1] = socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, 0)) < 0) { + perror("Fail to create INET6 socket!\n"); + exit(1); + } + setsockopt(sockfd[1], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); + setsockopt(sockfd[1], SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable)); + + memset(&serv_addr6, 0, sizeof(serv_addr6)); + serv_addr6.sin6_family = AF_INET6; + serv_addr6.sin6_port = htons(serv_port); + serv_addr6.sin6_addr = in6addr_any; + if (bind(sockfd[1], (struct sockaddr *)&serv_addr6, sizeof(serv_addr6)) != 0) { + perror("Fail to bind INET6 socket!\n"); + exit(1); + } + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN | EPOLLERR; + ev.data.fd = sockfd[1]; + if (epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd[1], &ev) != 0) { + perror("EPOLL_CTL_ADD failed for INET6 fd!\n"); + exit(1); + } +#endif + + while (1) { + nfds = epoll_wait(epfd, events, EPOLL_EVENTS, -1); + if (nfds == -1) { + perror("epoll_wait failed!\n"); + exit(1); + } + + for (i = 0; i < nfds; i++) { + handle_reply(epfd, events[i].data.fd); + } + } + + return 0; +} From 28397f4d22793f61082e141945aadd788b1f382c Mon Sep 17 00:00:00 2001 From: ywc689 Date: Thu, 19 Oct 2023 10:13:56 +0800 Subject: [PATCH 085/105] ipvs: support proxy protocol config Signed-off-by: ywc689 --- include/conf/service.h | 38 ++++++++++++++++--- include/ipvs/conn.h | 3 ++ include/ipvs/service.h | 3 +- src/ipvs/ip_vs_service.c | 7 +++- tools/ipvsadm/ipvsadm.c | 10 +++++ .../keepalived/keepalived/check/check_data.c | 1 + .../keepalived/check/check_parser.c | 12 +++++- .../keepalived/keepalived/check/ipvswrapper.c | 1 + tools/keepalived/keepalived/check/ipwrapper.c | 1 + tools/keepalived/keepalived/check/libipvs.c | 1 + .../keepalived/include/check_data.h | 4 +- 11 files changed, 69 insertions(+), 12 deletions(-) diff --git a/include/conf/service.h b/include/conf/service.h index d408b9d50..5310e187b 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -62,6 +62,12 @@ #define DEST_INHIBIT_DURATION_MIN 5 // 5s #define DEST_INHIBIT_DURATION_MAX 3600 // 1h +enum { + PROXY_PROTOCOL_DISABLE = 0, + PROXY_PROTOCOL_V1, + PROXY_PROTOCOL_V2, +}; + struct dest_check_configs { uint8_t types; // DEST_HC_* @@ -76,16 +82,17 @@ struct dest_check_configs { typedef struct dp_vs_service_compat { /*base*/ int af; - uint16_t proto; + uint8_t proto; + uint8_t proxy_protocol; /* proxy protocol version: DISABLE | V1 | V2 */ uint16_t port; - uint32_t fwmark; /* firwall mark of service */ - unsigned flags; /* virtual service flags */ - unsigned timeout; /* persistent timeout in sec */ + uint32_t fwmark; /* firwall mark of service */ + unsigned flags; /* virtual service flags */ + unsigned timeout; /* persistent timeout in sec */ unsigned conn_timeout; - uint32_t netmask; /* persistent netmask */ + uint32_t netmask; /* persistent netmask */ unsigned bps; unsigned limit_proportion; - union inet_addr addr; /* virtual ip address */ + union inet_addr addr; /* virtual ip address */ char sched_name[DP_VS_SCHEDNAME_MAXLEN]; /*dp_vs_service_user & dp_vs_service_entry*/ @@ -170,5 +177,24 @@ dest_check_configs_sanity(struct dest_check_configs *conf) { return res; }; +static inline uint8_t proxy_protocol_type(const char *str) { + if (!strcasecmp(str, "v1")) + return PROXY_PROTOCOL_V1; + if (!strcasecmp(str, "v2")) + return PROXY_PROTOCOL_V2; + return PROXY_PROTOCOL_DISABLE; +} + +static inline const char *proxy_protocol_str(uint8_t type) { + switch (type) { + case PROXY_PROTOCOL_DISABLE: + return "disable"; + case PROXY_PROTOCOL_V1: + return "v1"; + case PROXY_PROTOCOL_V2: + return "v2"; + } + return "unknown"; +} #endif /* __DPVS_SVC_CONF_H__ */ diff --git a/include/ipvs/conn.h b/include/ipvs/conn.h index 0075da6cc..c14ba74a9 100644 --- a/include/ipvs/conn.h +++ b/include/ipvs/conn.h @@ -149,6 +149,9 @@ struct dp_vs_conn { uint32_t last_ack_seq; /* ack seq of the last ack packet */ rte_atomic32_t dup_ack_cnt; /* count of repeated ack packets */ + uint8_t pp_version; /* proxy protocol version */ + uint8_t pp_sent; /* proxy protocol data has sent, for udp only */ + /* flags and state transition */ volatile uint16_t flags; volatile uint16_t state; diff --git a/include/ipvs/service.h b/include/ipvs/service.h index 2b12e05bb..a4cbff8e8 100644 --- a/include/ipvs/service.h +++ b/include/ipvs/service.h @@ -62,9 +62,10 @@ struct dp_vs_service { */ int af; uint8_t proto; /* TCP/UDP/... */ - union inet_addr addr; /* virtual IP address */ + uint8_t proxy_protocol; uint16_t port; uint32_t fwmark; + union inet_addr addr; /* virtual IP address */ struct dp_vs_match *match; unsigned flags; diff --git a/src/ipvs/ip_vs_service.c b/src/ipvs/ip_vs_service.c index 27ca3a7e7..44907dcd0 100644 --- a/src/ipvs/ip_vs_service.c +++ b/src/ipvs/ip_vs_service.c @@ -468,9 +468,10 @@ static int dp_vs_service_add(struct dp_vs_service_conf *u, svc->af = u->af; svc->proto = u->proto; - svc->addr = u->addr; + svc->proxy_protocol = u->proxy_protocol; svc->port = u->port; svc->fwmark = u->fwmark; + svc->addr = u->addr; svc->flags = u->flags; svc->timeout = u->timeout; svc->conn_timeout = u->conn_timeout; @@ -549,6 +550,7 @@ static int dp_vs_service_edit(struct dp_vs_service *svc, struct dp_vs_service_co svc->flags = u->flags | DP_VS_SVC_F_HASHED; svc->timeout = u->timeout; svc->conn_timeout = u->conn_timeout; + svc->proxy_protocol = u->proxy_protocol; svc->netmask = u->netmask; svc->bps = u->bps; svc->limit_proportion = u->limit_proportion; @@ -645,9 +647,10 @@ dp_vs_service_copy(struct dp_vs_service_entry *dst, struct dp_vs_service *src) memset(dst, 0, sizeof(*dst)); dst->af = src->af; dst->proto = src->proto; - dst->addr = src->addr; + dst->proxy_protocol = src->proxy_protocol; dst->port = src->port; dst->fwmark = src->fwmark; + dst->addr = src->addr; snprintf(dst->sched_name, sizeof(dst->sched_name), "%s", src->scheduler->name); dst->flags = src->flags; diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index 89ebc3d8e..549ecd71f 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -335,6 +335,7 @@ enum { TAG_CONN_EXPIRE_QUIESCENT, TAG_DEST_CHECK, TAG_CONN_TIMEOUT, + TAG_PROXY_PROTOCOL, }; /* various parsing helpers & parsing functions */ @@ -560,6 +561,7 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, { "expire-quiescent", '\0', POPT_ARG_NONE, NULL, TAG_CONN_EXPIRE_QUIESCENT, NULL, NULL }, { "dest-check", '\0', POPT_ARG_STRING, &optarg, TAG_DEST_CHECK, NULL, NULL}, { "conn-timeout", '\0', POPT_ARG_INT, &intarg, TAG_CONN_TIMEOUT, NULL, NULL}, + { "proxy-protocol", '\0', POPT_ARG_STRING, &optarg, TAG_PROXY_PROTOCOL, NULL, NULL}, { NULL, 0, 0, NULL, 0, NULL, NULL } }; @@ -978,6 +980,11 @@ parse_options(int argc, char **argv, struct ipvs_command_entry *ce, ce->dpvs_svc.conn_timeout = intarg; break; } + case TAG_PROXY_PROTOCOL: + { + ce->dpvs_svc.proxy_protocol = proxy_protocol_type(optarg); + break; + } default: fail(2, "invalid option `%s'", poptBadOption(context, POPT_BADOPTION_NOALIAS)); @@ -1702,6 +1709,7 @@ static void usage_exit(const char *program, const int exit_status) " --connection -c output of current IPVS connections\n" " --timeout output of timeout (tcp tcpfin udp)\n" " --conn-timeout set connection established timeout\n" + " --proxy-protocol proxy protocol config (disable|v1|v2)\n" " --daemon output of daemon information\n" " --stats output of statistics information\n" " --rate output of rate information\n" @@ -2163,6 +2171,8 @@ print_service_entry(dpvs_service_compat_t *se, unsigned int format) printf(" synproxy"); if (se->conn_timeout != 0) printf(" conn-timeout %u", se->conn_timeout); + if (se->proxy_protocol != PROXY_PROTOCOL_DISABLE) + printf(" pp%s", proxy_protocol_str(se->proxy_protocol)); if (se->flags & IP_VS_SVC_F_EXPIRE_QUIESCENT) printf(" expire-quiescent"); if (se->check_conf.types) { diff --git a/tools/keepalived/keepalived/check/check_data.c b/tools/keepalived/keepalived/check/check_data.c index 315f6face..ba3ece87e 100644 --- a/tools/keepalived/keepalived/check/check_data.c +++ b/tools/keepalived/keepalived/check/check_data.c @@ -584,6 +584,7 @@ alloc_vs(const char *param1, const char *param2) #endif } + new->proxy_protocol = PROXY_PROTOCOL_DISABLE; new->virtualhost = NULL; new->alpha = false; new->omega = false; diff --git a/tools/keepalived/keepalived/check/check_parser.c b/tools/keepalived/keepalived/check/check_parser.c index a59e22d09..8c4f26dcf 100644 --- a/tools/keepalived/keepalived/check/check_parser.c +++ b/tools/keepalived/keepalived/check/check_parser.c @@ -1056,8 +1056,8 @@ static void limit_proportion_handler(const vector_t *strvec) { virtual_server_t *vs = LIST_TAIL_DATA(check_data->vs); - char *str = vector_slot(strvec, 1); - vs->limit_proportion = atoi(str); + char *str = vector_slot(strvec, 1); + vs->limit_proportion = atoi(str); } static void @@ -1073,6 +1073,13 @@ establish_timeout_handler(const vector_t *strvec) vs->conn_timeout = conn_timeout; } +static void +proxy_protocol_handler(const vector_t *strvec) +{ + virtual_server_t *vs = LIST_TAIL_DATA(check_data->vs); + vs->proxy_protocol = proxy_protocol_type((const char *)vector_slot(strvec, 1)); +} + static void src_range_handler(const vector_t *strvec) { @@ -1173,6 +1180,7 @@ init_check_keywords(bool active) #endif install_keyword("lb_kind", &forwarding_handler); install_keyword("establish_timeout", &establish_timeout_handler); + install_keyword("proxy_protocol", &proxy_protocol_handler); install_keyword("lvs_method", &forwarding_handler); #ifdef _HAVE_PE_NAME_ install_keyword("persistence_engine", &pengine_handler); diff --git a/tools/keepalived/keepalived/check/ipvswrapper.c b/tools/keepalived/keepalived/check/ipvswrapper.c index 061204db7..61f590be9 100755 --- a/tools/keepalived/keepalived/check/ipvswrapper.c +++ b/tools/keepalived/keepalived/check/ipvswrapper.c @@ -762,6 +762,7 @@ static void ipvs_set_srule(int cmd, dpvs_service_compat_t *srule, virtual_server srule->flags = vs->flags; srule->netmask = (vs->af == AF_INET6) ? 128 : ((uint32_t) 0xffffffff); srule->proto = vs->service_type; + srule->proxy_protocol = vs->proxy_protocol; srule->bps = vs->bps; srule->limit_proportion = vs->limit_proportion; srule->conn_timeout = vs->conn_timeout; diff --git a/tools/keepalived/keepalived/check/ipwrapper.c b/tools/keepalived/keepalived/check/ipwrapper.c index ea6c80b17..5d4d7b20d 100755 --- a/tools/keepalived/keepalived/check/ipwrapper.c +++ b/tools/keepalived/keepalived/check/ipwrapper.c @@ -1378,6 +1378,7 @@ clear_diff_services(list old_checkers_queue) because the VS still exists in new configuration */ if (strcmp(vs->sched, new_vs->sched) || vs->flags != new_vs->flags || + vs->proxy_protocol != new_vs->proxy_protocol || vs->persistence_granularity != new_vs->persistence_granularity || vs->persistence_timeout != new_vs->persistence_timeout || vs->conn_timeout != new_vs->conn_timeout || diff --git a/tools/keepalived/keepalived/check/libipvs.c b/tools/keepalived/keepalived/check/libipvs.c index 4067a4d98..f81efce7a 100644 --- a/tools/keepalived/keepalived/check/libipvs.c +++ b/tools/keepalived/keepalived/check/libipvs.c @@ -132,6 +132,7 @@ int dpvs_update_service_by_options(dpvs_service_compat_t *svc, unsigned int opti entry.timeout = svc->timeout; } entry.conn_timeout = svc->conn_timeout; + entry.proxy_protocol = svc->proxy_protocol; if (options & OPT_NETMASK) { entry.netmask = svc->netmask; diff --git a/tools/keepalived/keepalived/include/check_data.h b/tools/keepalived/keepalived/include/check_data.h index 1d90dc320..832a9e8bb 100644 --- a/tools/keepalived/keepalived/include/check_data.h +++ b/tools/keepalived/keepalived/include/check_data.h @@ -191,7 +191,8 @@ typedef struct _virtual_server { uint32_t vfwmark; real_server_t *s_svr; uint16_t af; - uint16_t service_type; + uint8_t service_type; + uint8_t proxy_protocol; bool ha_suspend; int ha_suspend_addr_count; #ifdef _WITH_LVS_ @@ -298,6 +299,7 @@ static inline bool quorum_equal(const notify_script_t *quorum1, #define VS_ISEQ(X,Y) (sockstorage_equal(&(X)->addr,&(Y)->addr) &&\ (X)->vfwmark == (Y)->vfwmark &&\ (X)->service_type == (Y)->service_type &&\ + (X)->proxy_protocol == (Y)->proxy_protocol &&\ (X)->forwarding_method == (Y)->forwarding_method &&\ (X)->hash_target == (Y)->hash_target &&\ (X)->syn_proxy == (Y)->syn_proxy &&\ From e8793358687af488f60ad959ea7d554d1f0a11ab Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 23 Oct 2023 15:11:31 +0800 Subject: [PATCH 086/105] ipvs: proxy protocol implementation --- include/ipvs/conn.h | 4 +- include/ipvs/proto_tcp.h | 3 + include/ipvs/proto_udp.h | 4 + include/ipvs/proxy_proto.h | 155 +++++++++++ src/ipvs/ip_vs_conn.c | 5 + src/ipvs/ip_vs_proto_tcp.c | 70 ++++- src/ipvs/ip_vs_proto_udp.c | 69 ++++- src/ipvs/ip_vs_proxy_proto.c | 504 +++++++++++++++++++++++++++++++++++ 8 files changed, 791 insertions(+), 23 deletions(-) create mode 100644 include/ipvs/proxy_proto.h create mode 100644 src/ipvs/ip_vs_proxy_proto.c diff --git a/include/ipvs/conn.h b/include/ipvs/conn.h index c14ba74a9..9e3ebf428 100644 --- a/include/ipvs/conn.h +++ b/include/ipvs/conn.h @@ -52,7 +52,7 @@ enum { struct dp_vs_conn_param { int af; - uint16_t proto; + uint8_t proto; const union inet_addr *caddr; const union inet_addr *vaddr; uint16_t cport; @@ -66,7 +66,7 @@ struct conn_tuple_hash { /* tuple info */ int af; - uint16_t proto; + uint8_t proto; union inet_addr saddr; /* pkt's source addr */ union inet_addr daddr; /* pkt's dest addr */ uint16_t sport; diff --git a/include/ipvs/proto_tcp.h b/include/ipvs/proto_tcp.h index 9f5162a85..e166ad364 100644 --- a/include/ipvs/proto_tcp.h +++ b/include/ipvs/proto_tcp.h @@ -102,6 +102,9 @@ struct tcp_state { struct tcphdr *tcp_hdr(const struct rte_mbuf *mbuf); void tcp4_send_csum(struct rte_ipv4_hdr *iph, struct tcphdr *th); void tcp6_send_csum(struct rte_ipv6_hdr *iph, struct tcphdr *th); +int tcp_send_csum(int af, int iphdrlen, struct tcphdr *th, + const struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + struct netif_port *dev); struct rte_mempool *get_mbuf_pool(const struct dp_vs_conn *conn, int dir); void install_proto_tcp_keywords(void); void tcp_keyword_value_init(void); diff --git a/include/ipvs/proto_udp.h b/include/ipvs/proto_udp.h index 3bd98a3af..26abf59f7 100644 --- a/include/ipvs/proto_udp.h +++ b/include/ipvs/proto_udp.h @@ -19,6 +19,7 @@ #define __DP_VS_PROTO_UDP_H__ #include +#include "uoa.h" enum { DPVS_UDP_S_NONE = 0, @@ -34,5 +35,8 @@ void udp_keyword_value_init(void); void udp4_send_csum(struct rte_ipv4_hdr *iph, struct rte_udp_hdr *uh); void udp6_send_csum(struct rte_ipv6_hdr *iph, struct rte_udp_hdr *uh); +int udp_send_csum(int af, int iphdrlen, struct rte_udp_hdr *uh, + const struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + const struct opphdr *opp, struct netif_port *dev); #endif diff --git a/include/ipvs/proxy_proto.h b/include/ipvs/proxy_proto.h new file mode 100644 index 000000000..2cef07da2 --- /dev/null +++ b/include/ipvs/proxy_proto.h @@ -0,0 +1,155 @@ +/* + * DPVS is a software load balancer (Virtual Server) based on DPDK. + * + * Copyright (C) 2023 iQIYI (www.iqiyi.com). + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifndef __DPVS_PPHDR_H__ +#define __DPVS_PPHDR_H__ + +#include +#include +#include "dpdk.h" +#include "ipvs/proxy_proto.h" +#include "ipvs/conn.h" + +/* + * DPVS Implementation of Proxy Protocol: + * https://www.haproxy.org/download/2.9/doc/proxy-protocol.txt + */ + +#define PROXY_PROTO_V1_MAX_DATALEN 107 +#define PROXY_PROTO_HDR_LEN_V4 28 +#define PROXY_PROTO_HDR_LEN_V6 52 + +#define PROXY_PROTO_V2_SIGNATURE "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A" +#define PROXY_PROTO_V2_AF_MAX 4 +#define PROXY_PROTO_V2_PROTO_MAX 3 + + +struct proxy_hdr_v2 { + uint8_t sig[12]; // \x0D \x0A \x0D \x0A \x00 \x0D \x0A \x51 \x55 \x49 \x54 \x0A +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t cmd:4, // 0:LOCAL, 1:PROXY + ver:4; // 2:v2 + uint8_t proto:4, // 0:UNSPEC, 1:STREAM, 2:DGRAM + af:4; // 0:AF_UNIX, 1:AF_INET, 2:AF_INET6, 3:AF_UNIX +#elif __BYTE_ORDER == __BIG_ENDIAN + uint8_t ver:4, + cmd:4; + uint8_t af:4, + proto:4; +#else +#error "Please fix " +#endif + uint16_t addrlen; +} __attribute__((__packed__)); + +struct proxy_addr_ipv4 { + uint32_t src_addr; + uint32_t dst_addr; + uint16_t src_port; + uint16_t dst_port; +}; + +struct proxy_addr_ipv6 { + uint8_t src_addr[16]; + uint8_t dst_addr[16]; + uint16_t src_port; + uint16_t dst_port; +}; + +struct proxy_addr_unix { + uint8_t src_addr[108]; + uint8_t dst_addr[108]; +}; + +typedef union { + struct { + char line[108]; + } v1; + struct { + struct proxy_hdr_v2 hdr; + union { + struct proxy_addr_ipv4 ip4; + struct proxy_addr_ipv6 ip6; + struct proxy_addr_unix unx; + } addr; + } v2; +} __attribute__((__packed__)) proxy_proto_t; + +struct proxy_info { + uint8_t af; /* AF_INET, AF_INET6, AF_UNIX */ + uint8_t proto; /* IPPROTO_TCP, IPPROTO_UDP */ + uint8_t version; /* proxy protocol version */ + uint8_t cmd; /* proxy protocol command, 0:LOCAL, 1:PROXY */ + uint16_t datalen; /* length of the encoded proxy protocol data in packet, + MUST be ZERO when the proxy_info isn't parsed from mbuf */ + union { + struct proxy_addr_ipv4 ip4; + struct proxy_addr_ipv6 ip6; + struct proxy_addr_unix unx; + } addr; +}; + +static inline uint8_t ppv2_af_pp2host(uint8_t ppv2af) +{ + static uint8_t aftable[PROXY_PROTO_V2_AF_MAX] = { + AF_UNSPEC, AF_INET, AF_INET6, AF_UNIX}; + if (unlikely(ppv2af >= PROXY_PROTO_V2_AF_MAX)) + return AF_UNSPEC; + return aftable[ppv2af]; +} + +static inline uint8_t ppv2_af_host2pp(uint8_t hostaf) +{ + static uint8_t aftable[AF_MAX] = { + [ AF_UNSPEC ] = 0, + [ AF_INET ] = 1, + [ AF_INET6 ] = 2, + [ AF_UNIX ] = 3, + }; + if (unlikely(hostaf >= AF_MAX)) + return 0; + return aftable[hostaf]; +} + +static inline uint8_t ppv2_proto_pp2host(uint8_t ppv2proto) +{ + switch (ppv2proto) { + case 1: + return IPPROTO_TCP; + case 2: + return IPPROTO_UDP; + } + return 0; /* IPPROTO_IP */ +} + +static inline uint8_t ppv2_proto_host2pp(uint8_t hostproto) +{ + switch (hostproto) { + case IPPROTO_TCP: + return 1; + case IPPROTO_UDP: + return 2; + } + return 0; +} + +int proxy_proto_parse(struct rte_mbuf *mbuf, int ppdoff, struct proxy_info *ppinfo); +int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, + struct rte_mbuf *mbuf, void *l4hdr, int *hdr_shift); + +#endif /* __DPVS_PPHDR_H__ */ + diff --git a/src/ipvs/ip_vs_conn.c b/src/ipvs/ip_vs_conn.c index ef1c5d3c0..e8deb0576 100644 --- a/src/ipvs/ip_vs_conn.c +++ b/src/ipvs/ip_vs_conn.c @@ -880,6 +880,11 @@ struct dp_vs_conn *dp_vs_conn_new(struct rte_mbuf *mbuf, new->daddr = dest->addr; new->dport = rport; + if (dest->fwdmode == DPVS_FWD_MODE_FNAT) { + new->pp_version = dest->svc->proxy_protocol; + new->pp_sent = 0; + } + /* neighbour confirm cache */ if (AF_INET == tuplehash_in(new).af) { new->in_nexthop.in.s_addr = htonl(INADDR_ANY); diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 713e0aaa3..7b910791a 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -38,6 +38,7 @@ #include #include #include "ipvs/redirect.h" +#include "ipvs/proxy_proto.h" static int g_defence_tcp_drop = 0; @@ -157,7 +158,7 @@ inline void tcp6_send_csum(struct rte_ipv6_hdr *iph, struct tcphdr *th) { (void *)th - (void *)iph, IPPROTO_TCP); } -static inline int tcp_send_csum(int af, int iphdrlen, struct tcphdr *th, +int tcp_send_csum(int af, int iphdrlen, struct tcphdr *th, const struct dp_vs_conn *conn, struct rte_mbuf *mbuf, struct netif_port *dev) { /* leverage HW TX TCP csum offload if possible */ @@ -347,7 +348,43 @@ static void tcp_in_remove_toa(struct tcphdr *tcph, int af) } } -static inline int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, +static int tcp_in_add_proxy_proto(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + struct tcphdr *tcph, int iphdrlen, int *hdr_shift) +{ + int offset; + struct proxy_info ppinfo = { 0 }; + + offset = iphdrlen + (tcph->doff << 2); + if (unlikely(EDPVS_OK != proxy_proto_parse(mbuf, offset, &ppinfo))) + return EDPVS_INVPKT; + + if (ppinfo.datalen > 0 && ppinfo.version == conn->pp_version) + return EDPVS_OK; // keep intact the orginal proxy protocol data + + if (!ppinfo.datalen) { + ppinfo.af = tuplehash_in(conn).af; + ppinfo.proto = IPPROTO_TCP; + ppinfo.version = conn->pp_version; + ppinfo.cmd = 1; + if (AF_INET == ppinfo.af) { + ppinfo.addr.ip4.src_addr = conn->caddr.in.s_addr; + ppinfo.addr.ip4.dst_addr = conn->vaddr.in.s_addr; + ppinfo.addr.ip4.src_port = conn->cport; + ppinfo.addr.ip4.dst_port = conn->vport; + } else if (AF_INET6 == ppinfo.af) { + rte_memcpy(ppinfo.addr.ip6.src_addr, conn->caddr.in6.s6_addr, 16); + rte_memcpy(ppinfo.addr.ip6.dst_addr, conn->vaddr.in6.s6_addr, 16); + ppinfo.addr.ip6.src_port = conn->cport; + ppinfo.addr.ip6.dst_port = conn->vport; + } else { + return EDPVS_NOTSUPP; + } + } + + return proxy_proto_insert(&ppinfo, conn, mbuf, tcph, hdr_shift); +} + +static int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, struct tcphdr *tcph) { uint32_t mtu; @@ -748,6 +785,7 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, /* af/mbuf may be changed for nat64 which in af is ipv6 and out is ipv4 */ int iaf, oaf; int iphdrlen; + int err, pp_hdr_shift = 0; iaf = tuplehash_in(conn).af; oaf = tuplehash_out(conn).af; @@ -777,21 +815,28 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, tcp_in_remove_ts(th); tcp_in_init_seq(conn, mbuf, th); - - /* Only clear when adding TOA fails to reduce invocation frequency and improve performance. - * See https://github.com/iqiyi/dpvs/pull/925 for more detail. */ - if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { - tcp_in_remove_toa(th, iaf); + if (PROXY_PROTOCOL_V1 != conn->pp_version && + PROXY_PROTOCOL_V2 != conn->pp_version) { + if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { + tcp_in_remove_toa(th, iaf); + } } } - /* add toa to first data packet */ + /* add toa/proxy_proto to first data packet */ if (ntohl(th->ack_seq) == conn->fnat_seq.fdata_seq && !th->syn && !th->rst /*&& !th->fin*/) { - /* Only clear when adding TOA fails to reduce invocation frequency and improve performance. - * See https://github.com/iqiyi/dpvs/pull/925 for more detail. */ - if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { - tcp_in_remove_toa(th, iaf); + if (PROXY_PROTOCOL_V2 == conn->pp_version || + PROXY_PROTOCOL_V1 == conn->pp_version) { + err = tcp_in_add_proxy_proto(conn, mbuf, th, iphdrlen, &pp_hdr_shift); + if (unlikely(EDPVS_OK != err)) + RTE_LOG(INFO, IPVS, "%s: insert proxy protocol fail -- %s\n", + __func__, dpvs_strerror(err)); + th = ((void *)th) + pp_hdr_shift; + } else { + if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { + tcp_in_remove_toa(th, iaf); + } } } @@ -801,7 +846,6 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, th->source = conn->lport; th->dest = conn->dport; - return tcp_send_csum(oaf, iphdrlen, th, conn, mbuf, conn->in_dev); } diff --git a/src/ipvs/ip_vs_proto_udp.c b/src/ipvs/ip_vs_proto_udp.c index b71d9d7d8..a8706346f 100644 --- a/src/ipvs/ip_vs_proto_udp.c +++ b/src/ipvs/ip_vs_proto_udp.c @@ -31,6 +31,7 @@ #include "ipvs/blklst.h" #include "ipvs/whtlst.h" #include "ipvs/redirect.h" +#include "ipvs/proxy_proto.h" #include "parser/parser.h" #include "uoa.h" #include "neigh.h" @@ -78,9 +79,9 @@ inline void udp6_send_csum(struct rte_ipv6_hdr *iph, struct rte_udp_hdr *uh) (void *)uh - (void *)iph, IPPROTO_UDP); } -static inline int udp_send_csum(int af, int iphdrlen, struct rte_udp_hdr *uh, - const struct dp_vs_conn *conn, - struct rte_mbuf *mbuf, const struct opphdr *opp, struct netif_port *dev) +int udp_send_csum(int af, int iphdrlen, struct rte_udp_hdr *uh, + const struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + const struct opphdr *opp, struct netif_port *dev) { /* leverage HW TX UDP csum offload if possible */ struct netif_port *select_dev = NULL; @@ -165,7 +166,7 @@ static int udp_conn_sched(struct dp_vs_proto *proto, } /* lookup service */ - svc = dp_vs_service_lookup(iph->af, iph->proto, &iph->daddr, + svc = dp_vs_service_lookup(iph->af, iph->proto, &iph->daddr, uh->dst_port, 0, mbuf, NULL, rte_lcore_id()); if (!svc) { *verdict = INET_ACCEPT; @@ -217,7 +218,7 @@ udp_conn_lookup(struct dp_vs_proto *proto, return NULL; } - if (!dp_vs_whtlst_allow(iph->af, iph->proto, &iph->daddr, + if (!dp_vs_whtlst_allow(iph->af, iph->proto, &iph->daddr, uh->dst_port, &iph->saddr)) { *drop = true; return NULL; @@ -708,6 +709,42 @@ static int udp_insert_uoa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, return err; } +static int udp_in_add_proxy_proto(struct dp_vs_conn *conn, + struct rte_mbuf *mbuf, struct rte_udp_hdr *udph, int iphdrlen) +{ + int offset; + struct proxy_info ppinfo = { 0 }; + + offset = iphdrlen + sizeof(struct rte_udp_hdr); + if (unlikely(EDPVS_OK != proxy_proto_parse(mbuf, offset, &ppinfo))) + return EDPVS_INVPKT; + + if (ppinfo.datalen > 0 && ppinfo.version == conn->pp_version) + return EDPVS_OK; // keep intact the original proxy protocol data + + if (!ppinfo.datalen) { + ppinfo.af = tuplehash_in(conn).af; + ppinfo.proto = IPPROTO_UDP; + ppinfo.version = conn->pp_version; + ppinfo.cmd = 1; + if (AF_INET == ppinfo.af) { + ppinfo.addr.ip4.src_addr = conn->caddr.in.s_addr; + ppinfo.addr.ip4.dst_addr = conn->vaddr.in.s_addr; + ppinfo.addr.ip4.src_port = conn->cport; + ppinfo.addr.ip4.dst_port = conn->vport; + } else if (AF_INET6 == ppinfo.af) { + rte_memcpy(ppinfo.addr.ip6.src_addr, conn->caddr.in6.s6_addr, 16); + rte_memcpy(ppinfo.addr.ip6.dst_addr, conn->vaddr.in6.s6_addr, 16); + ppinfo.addr.ip6.src_port = conn->cport; + ppinfo.addr.ip6.dst_port = conn->vport; + } else { + return EDPVS_NOTSUPP; + } + } + + return proxy_proto_insert(&ppinfo, conn, mbuf, udph, NULL); +} + static int udp_fnat_in_handler(struct dp_vs_proto *proto, struct dp_vs_conn *conn, struct rte_mbuf *mbuf) @@ -717,7 +754,7 @@ static int udp_fnat_in_handler(struct dp_vs_proto *proto, void *iph = NULL; /* af/mbuf may be changed for nat64 which in af is ipv6 and out is ipv4 */ int af = tuplehash_out(conn).af; - int iphdrlen = 0; + int err, iphdrlen = 0; uint8_t nxt_proto; if (AF_INET6 == af) { @@ -747,6 +784,18 @@ static int udp_fnat_in_handler(struct dp_vs_proto *proto, if (unlikely(!uh)) return EDPVS_INVPKT; + if (!conn->pp_sent && (PROXY_PROTOCOL_V2 == conn->pp_version || + PROXY_PROTOCOL_V2 == conn->pp_version)) { + err = udp_in_add_proxy_proto(conn, mbuf, uh, iphdrlen); + if (unlikely(EDPVS_OK != err)) + RTE_LOG(INFO, IPVS, "%s: insert proxy protocol fail -- %s\n", + __func__, dpvs_strerror(err)); + // Notes: Is there any approach to deal with the exceptional cases where + // - proxy protocol insertion failed + // - the first udp packet with proxy protocol data got lost in network + conn->pp_sent = 1; + } + uh->src_port = conn->lport; uh->dst_port = conn->dport; @@ -781,10 +830,14 @@ static int udp_fnat_in_pre_handler(struct dp_vs_proto *proto, { struct conn_uoa *uoa = (struct conn_uoa *)conn->prot_data; + if (PROXY_PROTOCOL_V2 == conn->pp_version || + PROXY_PROTOCOL_V1 == conn->pp_version) + return EDPVS_OK; + if (uoa && g_uoa_max_trail > 0) return udp_insert_uoa(conn, mbuf, uoa); - else - return EDPVS_OK; + + return EDPVS_OK; } static int udp_snat_in_handler(struct dp_vs_proto *proto, diff --git a/src/ipvs/ip_vs_proxy_proto.c b/src/ipvs/ip_vs_proxy_proto.c new file mode 100644 index 000000000..8804c1844 --- /dev/null +++ b/src/ipvs/ip_vs_proxy_proto.c @@ -0,0 +1,504 @@ +/* + * DPVS is a software load balancer (Virtual Server) based on DPDK. + * + * Copyright (C) 2023 iQIYI (www.iqiyi.com). + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include "ipvs/proxy_proto.h" +#include "ipvs/proto_tcp.h" +#include "ipvs/proto_udp.h" +#include "ipv4.h" +#include "ipv6.h" +#include "route.h" +#include "route6.h" +#include "conf/common.h" +#include "conf/service.h" + +int proxy_proto_parse(struct rte_mbuf *mbuf, int ppdoff, struct proxy_info *ppinfo) +{ + void *pphdr; + char *token, *tmp, *end; + int offset, ppdlen; + char buf[PROXY_PROTO_V1_MAX_DATALEN+1]; + struct proxy_hdr_v2 *pphdrv2; + struct proxy_addr_ipv4 *addr4; + struct proxy_addr_ipv6 *addr6; + struct proxy_addr_unix *addrunx; + + offset = ppdoff + 12; + pphdr = rte_pktmbuf_mtod(mbuf, void *); + memset(ppinfo, 0, sizeof(struct proxy_info)); + + if (mbuf_may_pull(mbuf, offset)) + return EDPVS_OK; /* too small to reside pp data */ + + if (!memcmp(pphdr, PROXY_PROTO_V2_SIGNATURE, 12)) { + offset += 4; + if (mbuf_may_pull(mbuf, offset)) + return EDPVS_INVPKT; + pphdrv2 = (struct proxy_hdr_v2 *)pphdr; + offset += ntohs(pphdrv2->addrlen); + if (mbuf_may_pull(mbuf, offset)) + return EDPVS_INVPKT; + ppinfo->version = pphdrv2->ver; + if (unlikely(ppinfo->version != PROXY_PROTOCOL_V2 || ppinfo->cmd > 1)) + return EDPVS_INVAL; + ppinfo->datalen = offset; + ppinfo->cmd = pphdrv2->cmd; + if (!ppinfo->cmd) + return EDPVS_OK; /* LOCAL command */ + ppinfo->af = ppv2_proto_pp2host(pphdrv2->af); + if (unlikely(AF_UNSPEC == ppinfo->af)) + return EDPVS_NOTSUPP; + ppinfo->proto = ppv2_proto_pp2host(pphdrv2->proto); + if (unlikely(0 != ppinfo->proto)) + return EDPVS_NOTSUPP; + switch (ppinfo->af) { + case AF_INET: + addr4 = (struct proxy_addr_ipv4 *)(pphdrv2 + 1); + ppinfo->addr.ip4.src_addr = ntohl(addr4->src_addr); + ppinfo->addr.ip4.dst_addr = ntohl(addr4->dst_addr); + ppinfo->addr.ip4.src_port = ntohs(addr4->src_port); + ppinfo->addr.ip4.dst_port = ntohs(addr4->dst_port); + break; + case AF_INET6: + addr6 = (struct proxy_addr_ipv6 *)(pphdrv2 + 1); + memcpy(ppinfo->addr.ip6.src_addr, addr6->src_addr, 16); + memcpy(ppinfo->addr.ip6.dst_addr, addr6->dst_addr, 16); + ppinfo->addr.ip6.src_port = ntohs(addr6->src_port); + ppinfo->addr.ip6.dst_port = ntohs(addr6->dst_port); + break; + case AF_UNIX: + addrunx = (struct proxy_addr_unix *)(pphdrv2 + 1); + memcpy(ppinfo->addr.unx.src_addr, addrunx->src_addr, 108); + memcpy(ppinfo->addr.unx.dst_addr, addrunx->dst_addr, 108); + break; + default: + return EDPVS_NOTSUPP; + } + /* ignore all TLVs */ + return EDPVS_OK; + } else if (!memcmp(pphdr, "PROXY ", 6)) { + ppdlen = strcspn((const char *)pphdr, "\n"); + if (unlikely(ppdlen > PROXY_PROTO_V1_MAX_DATALEN)) + return EDPVS_INVPKT; + offset = ppdoff + ppdlen; + if (mbuf_may_pull(mbuf, offset)) + return EDPVS_INVPKT; + memcpy(buf, pphdr, ppdlen); + buf[ppdlen] = '\0'; + if (ppdlen > 1 && buf[ppdlen-1] == '\r') + buf[ppdlen-1] = '\0'; + if (NULL == (token = strtok_r(buf, " ", &tmp))) /* "PROXY" */ + return EDPVS_INVAL; + ppinfo->version = PROXY_PROTOCOL_V1; + if (NULL == (token = strtok_r(buf, " ", &tmp))) /* TCP4 | TCP6 */ + return EDPVS_INVAL; + if (!memcmp(token, "TCP4", 4)) { + ppinfo->af = AF_INET; + ppinfo->proto = IPPROTO_TCP; + ppinfo->cmd = 1; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* source IP */ + return EDPVS_INVAL; + if (1 != inet_pton(AF_INET, token, &ppinfo->addr.ip4.src_addr)) + return EDPVS_INVAL; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* dest IP */ + return EDPVS_INVAL; + if (1 != inet_pton(AF_INET, token, &ppinfo->addr.ip4.dst_addr)) + return EDPVS_INVAL; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* source port */ + return EDPVS_INVAL; + ppinfo->addr.ip4.src_port = ntohs(strtol(token, &end, 10)); + if (*end != '\0') + return EDPVS_INVAL; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* dest port */ + return EDPVS_INVAL; + ppinfo->addr.ip4.dst_port = ntohs(strtol(token, &end, 10)); + if (*end != '\0') + return EDPVS_INVAL; + if (NULL != strtok_r(NULL, " ", &tmp)) + return EDPVS_INVAL; + ppinfo->datalen = ppdlen; + return EDPVS_OK; + } else if (!memcmp(token, "TCP6", 4)) { + ppinfo->af = AF_INET6; + ppinfo->proto = IPPROTO_TCP; + ppinfo->cmd = 1; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* source IP */ + return EDPVS_INVAL; + if (1 != inet_pton(AF_INET6, token, ppinfo->addr.ip6.src_addr)) + return EDPVS_INVAL; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* dest IP */ + return EDPVS_INVAL; + if (1 != inet_pton(AF_INET6, token, ppinfo->addr.ip6.dst_addr)) + return EDPVS_INVAL; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* source port */ + return EDPVS_INVAL; + ppinfo->addr.ip6.src_port = ntohs(strtol(token, &end, 10)); + if (*end != '\0') + return EDPVS_INVAL; + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* dest port */ + return EDPVS_INVAL; + ppinfo->addr.ip6.dst_port = ntohs(strtol(token, &end, 10)); + if (*end != '\0') + return EDPVS_INVAL; + if (NULL != strtok_r(NULL, " ", &tmp)) + return EDPVS_INVAL; + ppinfo->datalen = ppdlen; + return EDPVS_OK; + } else if (!memcpy(token, "UNKNOWN", 7)) { + ppinfo->datalen = ppdlen; + ppinfo->cmd = 0; + if (NULL != strtok_r(NULL, " ", &tmp)) + return EDPVS_INVAL; + return EDPVS_OK; + } else { + return EDPVS_NOTSUPP; + } + } + + return EDPVS_OK; +} + +static int proxy_proto_send_standalone(struct proxy_info *ppinfo, + struct dp_vs_conn *conn, struct rte_mbuf *ombuf, void *ol4hdr, + int *hdr_shift, int ppdlen, char *ppv1data) +{ + int err; + int ppdoff; + int iaf, oaf; + void *rt; + void *iph, *oiph, *pph, *l4hdr; + struct tcphdr *th; + struct rte_udp_hdr *uh; + struct rte_mbuf *mbuf = NULL; + struct proxy_hdr_v2 *pphv2; + + rt = MBUF_USERDATA_CONST(ombuf, void *, MBUF_FIELD_ROUTE); + if (unlikely(!rt)) + return EDPVS_NOROUTE; + + iaf = tuplehash_in(conn).af; + oaf = tuplehash_out(conn).af; + oiph = rte_pktmbuf_mtod(ombuf, void *); + if (IPPROTO_TCP == conn->proto) + ppdoff = ol4hdr + (((struct tcphdr *)ol4hdr)->doff << 2) - oiph; + else + ppdoff = ol4hdr + sizeof(struct rte_udp_hdr) - oiph; + assert(ppdoff > 0); + + mbuf = rte_pktmbuf_alloc(ombuf->pool); + if (unlikely(!mbuf)) + return EDPVS_NOMEM; + mbuf_userdata_reset(mbuf); + + // L3 header + if (AF_INET6 == iaf) { + iph = rte_pktmbuf_append(mbuf, sizeof(struct rte_ipv6_hdr)); + if (unlikely(!iph)) { + err = EDPVS_NOMEM; + goto errout; + } + ((struct ip6_hdr *)iph)->ip6_ctlun = ((struct ip6_hdr *)oiph)->ip6_ctlun; + ((struct ip6_hdr *)iph)->ip6_plen = 0; // calc later + rte_memcpy(&((struct ip6_hdr *)iph)->ip6_src, &conn->laddr.in6, 16); + rte_memcpy(&((struct ip6_hdr *)iph)->ip6_dst, &conn->daddr.in6, 16); + } else { + iph = rte_pktmbuf_append(mbuf, sizeof(struct rte_ipv4_hdr)); + if (unlikely(!iph)) { + err = EDPVS_NOMEM; + goto errout; + } + ((struct iphdr *)iph)->version = 4; + ((struct iphdr *)iph)->ihl = 5; + ((struct iphdr *)iph)->tos = ((struct iphdr *)oiph)->tos; + ((struct iphdr *)iph)->tot_len = 0; // calc later + ((struct iphdr *)iph)->id = ((struct iphdr *)oiph)->id; + ((struct iphdr *)iph)->frag_off = 0; + ((struct iphdr *)iph)->ttl = ((struct iphdr *)oiph)->ttl; + ((struct iphdr *)iph)->protocol = ((struct iphdr *)oiph)->protocol; + ((struct iphdr *)iph)->check = 0; // calc later + ((struct iphdr *)iph)->saddr = conn->laddr.in.s_addr; + ((struct iphdr *)iph)->daddr = conn->daddr.in.s_addr; + } + + // L4 header + if (IPPROTO_TCP == conn->proto) { + th = (struct tcphdr *)rte_pktmbuf_append(mbuf, sizeof(struct rte_tcp_hdr)); + if (unlikely(!th)) { + err = EDPVS_NOMEM; + goto errout; + } + memset(th, 0, sizeof(struct rte_tcp_hdr)); + th->source = conn->lport; + th->dest = conn->dport; + th->seq = ((struct tcphdr *)ol4hdr)->seq; + th->ack_seq = ((struct tcphdr *)ol4hdr)->ack_seq; + th->doff = 5; + th->psh = ((struct tcphdr *)ol4hdr)->psh; + th->ack = 1; + th->window = ((struct tcphdr *)ol4hdr)->window; + th->check = 0; + l4hdr = th; + } else { // IPPROTO_UDP + uh = (struct rte_udp_hdr *)rte_pktmbuf_append(mbuf, sizeof(struct rte_udp_hdr)); + if (unlikely(!uh)) { + err = EDPVS_NOMEM; + goto errout; + } + uh->src_port = conn->lport; + uh->dst_port = conn->dport; + uh->dgram_len = htons(sizeof(struct rte_udp_hdr)); + uh->dgram_cksum = 0; + l4hdr = uh; + } + + // Proxy Protocol data + pph = rte_pktmbuf_append(mbuf, ppdlen); + if (unlikely(!pph)) { + err = EDPVS_NOMEM; + goto errout; + } + if (PROXY_PROTOCOL_V2 == conn->pp_version) { + pphv2 = (struct proxy_hdr_v2 *)pph; + rte_memcpy(pphv2->sig, PROXY_PROTO_V2_SIGNATURE, sizeof(pphv2->sig)); + pphv2->cmd = ppinfo->cmd & 0xF; + pphv2->ver = ppinfo->version & 0xF; + pphv2->proto = ppinfo->proto & 0xF; + pphv2->af = ppinfo->af & 0xF; + pphv2->addrlen = ntohs(ppdlen - sizeof(struct proxy_hdr_v2)); + rte_memcpy(pphv2 + 1, &ppinfo->addr, ppdlen - sizeof(struct proxy_hdr_v2)); + } else if (PROXY_PROTOCOL_V1 == conn->pp_version) { + rte_memcpy(pph, ppv1data, ppdlen); + } else { + err = EDPVS_NOTSUPP; + goto errout; + } + + if (AF_INET6 == oaf) { + MBUF_USERDATA(mbuf, void *, MBUF_FIELD_ROUTE) = rt; + route6_get(rt); + if (IPPROTO_TCP == conn->proto) { + ((struct ip6_hdr *)iph)->ip6_plen = htons(sizeof(struct rte_tcp_hdr) + ppdlen); + err = tcp_send_csum(AF_INET6, sizeof(struct rte_ipv6_hdr), l4hdr, + conn, mbuf, ((struct route6 *)rt)->rt6_dev); + if (unlikely(EDPVS_OK != err)) { + route6_put(rt); + goto errout; + } + } else { + ((struct ip6_hdr *)iph)->ip6_plen = htons(sizeof(struct rte_udp_hdr) + ppdlen); + err = udp_send_csum(AF_INET6, sizeof(struct rte_ipv6_hdr), l4hdr, + conn, mbuf, NULL, ((struct route6 *)rt)->rt6_dev); + if (unlikely(EDPVS_OK != err)) + goto errout; + } + err = ip6_local_out(mbuf); + if (err != EDPVS_OK) + goto errout; + goto finish; + } else { // AF_INET + MBUF_USERDATA(mbuf, void *, MBUF_FIELD_ROUTE) = rt; + route4_get(rt); + if (IPPROTO_TCP == conn->proto) { + ((struct iphdr *)iph)->tot_len = htons(mbuf->pkt_len); + err = tcp_send_csum(AF_INET, sizeof(struct rte_ipv4_hdr), l4hdr, + conn, mbuf, ((struct route_entry *)rt)->port); + if (unlikely(EDPVS_OK != err)) { + route4_put(rt); + goto errout; + } + } else { + ((struct iphdr *)iph)->tot_len = htons(mbuf->pkt_len); + // notes: ipv4 udp checksum is not a mandatory + err = udp_send_csum(AF_INET, sizeof(struct rte_ipv4_hdr), l4hdr, + conn, mbuf, NULL, ((struct route_entry *)rt)->port); + if (unlikely(EDPVS_OK != err)) { + route4_put(rt); + goto errout; + } + } + err = ipv4_local_out(mbuf); + if (err != EDPVS_OK) + goto errout; + goto finish; + } + +errout: + if (likely(NULL != mbuf)) + rte_pktmbuf_free(mbuf); + return err; + +finish: + // remove the existing proxy protocol data from original mbuf + if (ppinfo->datalen > 0) { + memmove(oiph + ppdoff, oiph, ppdoff); + if (hdr_shift) + *hdr_shift = ppdoff; + rte_pktmbuf_adj(ombuf, ppdoff); + ppinfo->datalen = 0; + } + + if (IPPROTO_TCP == conn->proto) { + conn->fnat_seq.delta += ppdlen; + } + + return EDPVS_OK; +} + +int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, + struct rte_mbuf *mbuf, void *l4hdr, int *hdr_shift) +{ + void *iph, *pph, *niph; + void *rt; + int ppdoff, ppdatalen, room, mtu; + char ppv1buf[108], tbuf1[64], tbuf2[64]; + struct proxy_hdr_v2 *pphv2; + + assert(ppinfo && conn && mbuf && l4hdr); + + rt = MBUF_USERDATA_CONST(mbuf, void *, MBUF_FIELD_ROUTE); + if (unlikely(!rt)) + return EDPVS_NOROUTE; + + if (unlikely(conn->dest->fwdmode != DPVS_FWD_MODE_FNAT)) + return EDPVS_NOTSUPP; + + if (ppinfo->datalen > 0 && ppinfo->version == conn->pp_version) + return EDPVS_OK; // proxy the existing proxy protocol data directly to rs + + // calculate required space size in mbuf + ppdatalen = 0; + if (PROXY_PROTOCOL_V2 == conn->pp_version) { + ppdatalen = sizeof(struct proxy_hdr_v2); + if (ppinfo->cmd == 1) { + switch (ppinfo->af) { + case AF_INET: + ppdatalen = PROXY_PROTO_HDR_LEN_V4; + break; + case AF_INET6: + ppdatalen = PROXY_PROTO_HDR_LEN_V6; + break; + case AF_UNIX: + ppdatalen += (strlen((const char *)ppinfo->addr.unx.src_addr) + + strlen((const char *)ppinfo->addr.unx.dst_addr)); + break; + default: + return EDPVS_NOTSUPP; + } + } + } else if (PROXY_PROTOCOL_V1 == conn->pp_version) { + if (ppinfo->cmd == 1) { + if (IPPROTO_TCP != ppinfo->proto) + return EDPVS_NOTSUPP; // v1 only supports tcp + switch (ppinfo->af) { + case AF_INET: + if (unlikely(NULL == inet_ntop(AF_INET, &ppinfo->addr.ip4.src_addr, + tbuf1, sizeof(tbuf1)))) + return EDPVS_INVAL; + if (unlikely(NULL == inet_ntop(AF_INET, &ppinfo->addr.ip4.dst_addr, + tbuf2, sizeof(tbuf2)))) + return EDPVS_INVAL; + sprintf(ppv1buf, "PROXY TCP4 %s %s %d %d\r\n", tbuf1, tbuf2, + ppinfo->addr.ip4.src_port, ppinfo->addr.ip4.dst_port); + break; + case AF_INET6: + if (unlikely(NULL == inet_ntop(AF_INET6, ppinfo->addr.ip6.src_addr, + tbuf1, sizeof(tbuf1)))) + return EDPVS_INVAL; + if (unlikely(NULL == inet_ntop(AF_INET6, ppinfo->addr.ip6.dst_addr, + tbuf2, sizeof(tbuf2)))) + return EDPVS_INVAL; + sprintf(ppv1buf, "PROXY TCP6 %s %s %d %d\r\n", tbuf1, tbuf2, + ppinfo->addr.ip4.src_port, ppinfo->addr.ip4.dst_port); + break; + default: + return EDPVS_NOTSUPP; + } + } else { + rte_memcpy(ppv1buf, "PROXY UNKNOWN\r\n\0", 16); + } + ppdatalen = strlen(ppv1buf); + } else { + return EDPVS_NOTSUPP; + } + + assert(ppdatalen > 0); + iph = rte_pktmbuf_mtod(mbuf, void *); + switch (conn->proto) { + case IPPROTO_TCP: + pph = l4hdr + (((struct tcphdr *)l4hdr)->doff << 2); + ppdoff = pph - iph; + break; + case IPPROTO_UDP: + pph = l4hdr + sizeof(struct rte_udp_hdr); + ppdoff = pph - iph; + break; + default: + return EDPVS_NOTSUPP; + } + assert(ppdoff > 0); + room = ppdatalen - ppinfo->datalen; + if (room > 0) { + // allocate space from mbuf headroom + if (AF_INET6 == tuplehash_out(conn).af) + mtu = ((struct route6 *)rt)->rt6_mtu; + else + mtu = ((struct route_entry *)rt)->mtu; + if (mbuf->pkt_len + room > mtu) + return proxy_proto_send_standalone(ppinfo, conn, mbuf, l4hdr, hdr_shift, ppdatalen, ppv1buf); + niph = rte_pktmbuf_prepend(mbuf, room); + if (unlikely(!niph)) + return proxy_proto_send_standalone(ppinfo, conn, mbuf, l4hdr, hdr_shift, ppdatalen, ppv1buf); + memmove(niph, iph, ppdoff); + if (hdr_shift) + *hdr_shift = niph - iph; + iph = niph; + pph = iph + ppdoff; + } else if (room < 0) { + // strip extra space in mbuf + room = -room; + niph = iph + room; + memmove(niph, iph, ppdoff); + if (hdr_shift) + *hdr_shift = niph - iph; + niph = rte_pktmbuf_adj(mbuf, room); + if (unlikely(!niph)) + return EDPVS_INVPKT; + iph = niph; + pph = iph + ppdoff; + } + + // fill in proxy protocol data + if (PROXY_PROTOCOL_V2 == conn->pp_version) { + pphv2 = (struct proxy_hdr_v2 *)pph; + rte_memcpy(pphv2->sig, PROXY_PROTO_V2_SIGNATURE, sizeof(pphv2->sig)); + pphv2->cmd = ppinfo->cmd & 0xF; + pphv2->ver = ppinfo->version & 0xF; + pphv2->proto = ppinfo->proto & 0xF; + pphv2->af = ppinfo->af & 0xF; + pphv2->addrlen = ntohs(ppdatalen - sizeof(struct proxy_hdr_v2)); + rte_memcpy(pphv2 + 1, &ppinfo->addr, ppdatalen - sizeof(struct proxy_hdr_v2)); + } else { // PROXY_PROTOCOL_V1 + rte_memcpy(pph, ppv1buf, ppdatalen); + } + + ppinfo->datalen = ppdatalen; + if (IPPROTO_TCP == conn->proto) { + // ajust inbound tcp sequence number except for the first segment + ((struct tcphdr *)l4hdr)->seq = htonl(((struct tcphdr *)l4hdr)->seq - ppdatalen); + conn->fnat_seq.delta += ppdatalen; + } + return EDPVS_OK; +} From 45ad38bea914da6860618f3851d08ba036f39c67 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 7 Nov 2023 16:06:46 +0800 Subject: [PATCH 087/105] tools: add supports for proxy protocol Signed-off-by: ywc689 --- include/conf/service.h | 1 + .../pkg/helthcheck/http_checker.go | 56 +++++- .../pkg/helthcheck/http_checker_test.go | 26 ++- .../keepalived/keepalived/check/check_http.c | 186 ++++++++++++------ 4 files changed, 193 insertions(+), 76 deletions(-) diff --git a/include/conf/service.h b/include/conf/service.h index 5310e187b..401bf5f0a 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -66,6 +66,7 @@ enum { PROXY_PROTOCOL_DISABLE = 0, PROXY_PROTOCOL_V1, PROXY_PROTOCOL_V2, + PROXY_PROTOCOL_MAX, }; struct dest_check_configs { diff --git a/tools/healthcheck/pkg/helthcheck/http_checker.go b/tools/healthcheck/pkg/helthcheck/http_checker.go index 4432a9187..8343fdea0 100644 --- a/tools/healthcheck/pkg/helthcheck/http_checker.go +++ b/tools/healthcheck/pkg/helthcheck/http_checker.go @@ -18,10 +18,13 @@ package hc import ( + "bytes" + "context" "crypto/tls" "errors" "fmt" "io" + "net" "net/http" "net/url" "strings" @@ -30,6 +33,14 @@ import ( var _ CheckMethod = (*HttpChecker)(nil) +var ( + proxyProtoV1LocalCmd = "PROXY UNKNOWN\r\n" + proxyProtoV2LocalCmd []byte = []byte{ + 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, + 0x55, 0x49, 0x54, 0x0A, 0x20, 0x00, 0x00, 0x00, + } +) + type HttpCodeRange struct { start int // inclusive end int // inclusive @@ -45,13 +56,14 @@ type HttpChecker struct { ResponseCodes []HttpCodeRange Response string - Secure bool - TLSVerify bool - Proxy bool + Secure bool + TLSVerify bool + Proxy bool + ProxyProto int // proxy protocol: 0 - close, 1 - version 1, 2 - version 2 } // NewHttpChecker returns an initialised HttpChecker. -func NewHttpChecker(method, host, uri string) *HttpChecker { +func NewHttpChecker(method, host, uri string, proxyProto int) *HttpChecker { if len(method) == 0 { method = "GET" } @@ -66,6 +78,7 @@ func NewHttpChecker(method, host, uri string) *HttpChecker { Secure: false, TLSVerify: true, Proxy: false, + ProxyProto: proxyProto, } } @@ -127,12 +140,37 @@ func (hc *HttpChecker) Check(target Target, timeout time.Duration) *Result { tlsConfig := &tls.Config{ InsecureSkipVerify: !hc.TLSVerify, } + + tr := &http.Transport{ + Proxy: proxy, + TLSClientConfig: tlsConfig, + } + if hc.ProxyProto != 0 { + tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { + conn, err := (&net.Dialer{}).DialContext(ctx, network, addr) + if err != nil { + return nil, err + } + // Alternatively, use the go-proxyproto package: + // https://pkg.go.dev/github.com/pires/go-proxyproto + if hc.ProxyProto == 2 { + n, err := bytes.NewReader(proxyProtoV2LocalCmd).WriteTo(conn) + if err != nil || n < 16 { + return nil, err + } + } else if hc.ProxyProto == 1 { + n, err := strings.NewReader(proxyProtoV1LocalCmd).WriteTo(conn) + if err != nil || n < int64(len(proxyProtoV1LocalCmd)) { + return nil, err + } + } + return conn, nil + } + } + client := &http.Client{ - Transport: &http.Transport{ - Proxy: proxy, - TLSClientConfig: tlsConfig, - }, - Timeout: timeout, + Transport: tr, + Timeout: timeout, CheckRedirect: func(req *http.Request, via []*http.Request) error { return errors.New("redirect not permitted") }, diff --git a/tools/healthcheck/pkg/helthcheck/http_checker_test.go b/tools/healthcheck/pkg/helthcheck/http_checker_test.go index 809b43bd3..dcf9412ad 100644 --- a/tools/healthcheck/pkg/helthcheck/http_checker_test.go +++ b/tools/healthcheck/pkg/helthcheck/http_checker_test.go @@ -32,6 +32,11 @@ var http_targets = []Target{ {net.ParseIP("192.168.88.30"), 443, utils.IPProtoTCP}, {net.ParseIP("2001::30"), 80, utils.IPProtoTCP}, {net.ParseIP("2001::30"), 443, utils.IPProtoTCP}, + {net.ParseIP("192.168.88.30"), 8002, utils.IPProtoTCP}, // control group for proxy protocol +} + +var http_proxy_proto_targets = []Target{ + {net.ParseIP("192.168.88.30"), 8002, utils.IPProtoTCP}, } var http_url_targets = []string{ @@ -43,7 +48,7 @@ var http_url_targets = []string{ func TestHttpChecker(t *testing.T) { for _, target := range http_targets { - checker := NewHttpChecker("", "", "") + checker := NewHttpChecker("", "", "", 0) checker.Host = target.Addr() /* if target.Port == 443 { @@ -57,9 +62,26 @@ func TestHttpChecker(t *testing.T) { fmt.Printf("[ HTTP ] %s ==> %v\n", target, result) } + for _, target := range http_proxy_proto_targets { + checker := NewHttpChecker("", "", "", 1) + checker.Host = target.Addr() + id := Id(target.String()) + config := NewCheckerConfig(&id, checker, &target, StateUnknown, + 0, 3*time.Second, 2*time.Second, 3) + result := checker.Check(target, config.Timeout) + fmt.Printf("[ HTTP(PPv1) ] %s ==> %v\n", target, result) + checker2 := NewHttpChecker("", "", "", 2) + checker2.Host = target.Addr() + id2 := Id(target.String()) + config2 := NewCheckerConfig(&id2, checker2, &target, StateUnknown, + 0, 3*time.Second, 2*time.Second, 3) + result2 := checker2.Check(target, config2.Timeout) + fmt.Printf("[ HTTP(PPv2) ] %s ==> %v\n", target, result2) + } + for _, target := range http_url_targets { host := target[strings.Index(target, "://")+3:] - checker := NewHttpChecker("GET", target, "") + checker := NewHttpChecker("GET", target, "", 0) checker.Host = host checker.ResponseCodes = []HttpCodeRange{{200, 200}} if strings.HasPrefix(target, "https") { diff --git a/tools/keepalived/keepalived/check/check_http.c b/tools/keepalived/keepalived/check/check_http.c index 15b76e55c..670d0fad1 100644 --- a/tools/keepalived/keepalived/check/check_http.c +++ b/tools/keepalived/keepalived/check/check_http.c @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef _WITH_REGEX_CHECK_ #define PCRE2_CODE_UNIT_WIDTH 8 @@ -923,6 +924,8 @@ install_ssl_check_keyword(void) * * http_connect_thread (handle layer4 connect) * v + * http_send_proxy_protocol (handle proxy protocol) + * v * http_check_thread (handle SSL connect) * v * http_request_thread (send SSL GET request) @@ -1541,6 +1544,45 @@ http_request_thread(thread_ref_t thread) return 1; } +static int http_send_proxy_protocol(thread_ref_t thread) +{ + checker_t *checker = THREAD_ARG(thread); + virtual_server_t *vs = checker->vs; + + unsigned int len; + char *ppbuf; + const char ppv2_local_cmd[] = { + 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, + 0x55, 0x49, 0x54, 0x0A, 0x20, 0x00, 0x00, 0x00, + }; + + assert(vs->proxy_protocol >= PROXY_PROTOCOL_DISABLE + && vs->proxy_protocol < PROXY_PROTOCOL_MAX); + + ppbuf = (char *) MALLOC(16); + if (!ppbuf) { + return -1; + } + memset(ppbuf, 0, 16); + + if (PROXY_PROTOCOL_V1 == vs->proxy_protocol) { + len = 15; + sprintf(ppbuf, "%s", "PROXY UNKNOWN\r\n"); + } else if (PROXY_PROTOCOL_V2 == vs->proxy_protocol) { + len = 16; + memcpy(ppbuf, ppv2_local_cmd, 16); + } + + if (send(thread->u.f.fd, ppbuf, len, 0) != len) { + log_message(LOG_WARNING, "Send proxy protocol data failed!"); + FREE(ppbuf); + return -1; + } + + FREE(ppbuf); + return 0; +} + /* WEB checkers threads */ static int http_check_thread(thread_ref_t thread) @@ -1551,12 +1593,84 @@ http_check_thread(thread_ref_t thread) request_t *req = http_get_check->req; #endif int ret = 1; - int status; unsigned long timeout = 0; int ssl_err = 0; bool new_req = false; - status = tcp_socket_state(thread, http_check_thread); + if (!http_get_check->req) { + http_get_check->req = (request_t *) MALLOC(sizeof (request_t)); + new_req = true; + } else + new_req = false; + + if (http_get_check->proto == PROTO_SSL) { + timeout = timer_long(thread->sands) - timer_long(time_now); + if (thread->type != THREAD_WRITE_TIMEOUT && + thread->type != THREAD_READ_TIMEOUT) + ret = ssl_connect(thread, new_req); + else + return timeout_epilog(thread, "Timeout connecting"); + + if (ret == -1) { + switch ((ssl_err = SSL_get_error(http_get_check->req->ssl, + ret))) { + case SSL_ERROR_WANT_READ: + thread_add_read(thread->master, + http_check_thread, + THREAD_ARG(thread), + thread->u.f.fd, timeout, true); + thread_del_write(thread); + break; + case SSL_ERROR_WANT_WRITE: + thread_add_write(thread->master, + http_check_thread, + THREAD_ARG(thread), + thread->u.f.fd, timeout, true); + thread_del_read(thread); + break; + default: + ret = 0; + break; + } + if (ret == -1) + return 0; + } else if (ret != 1) + ret = 0; + } + + if (ret) { + /* Remote WEB server is connected. + * Register the next step thread ssl_request_thread. + */ + DBG("Remote Web server %s connected.", FMT_CHK(checker)); + thread_add_write(thread->master, + http_request_thread, checker, + thread->u.f.fd, + checker->co->connection_to, true); + thread_del_read(thread); + } else { + DBG("Connection trouble to: %s." + , FMT_CHK(checker)); +#ifdef _DEBUG_ + if (http_get_check->proto == PROTO_SSL) + ssl_printerr(SSL_get_error + (req->ssl, ret)); +#endif + return timeout_epilog(thread, "SSL handshake/communication error" + " connecting to"); + } + + return 0; +} + +static int +http_proxy_protocol_thread(thread_ref_t thread) +{ + int status; + unsigned long timeout; + checker_t *checker = THREAD_ARG(thread); + + status = tcp_socket_state(thread, http_proxy_protocol_thread); switch (status) { case connect_error: return timeout_epilog(thread, "Error connecting"); @@ -1571,68 +1685,9 @@ http_check_thread(thread_ref_t thread) break; case connect_success: - if (!http_get_check->req) { - http_get_check->req = (request_t *) MALLOC(sizeof (request_t)); - new_req = true; - } else - new_req = false; - - if (http_get_check->proto == PROTO_SSL) { - timeout = timer_long(thread->sands) - timer_long(time_now); - if (thread->type != THREAD_WRITE_TIMEOUT && - thread->type != THREAD_READ_TIMEOUT) - ret = ssl_connect(thread, new_req); - else - return timeout_epilog(thread, "Timeout connecting"); - - if (ret == -1) { - switch ((ssl_err = SSL_get_error(http_get_check->req->ssl, - ret))) { - case SSL_ERROR_WANT_READ: - thread_add_read(thread->master, - http_check_thread, - THREAD_ARG(thread), - thread->u.f.fd, timeout, true); - thread_del_write(thread); - break; - case SSL_ERROR_WANT_WRITE: - thread_add_write(thread->master, - http_check_thread, - THREAD_ARG(thread), - thread->u.f.fd, timeout, true); - thread_del_read(thread); - break; - default: - ret = 0; - break; - } - if (ret == -1) - break; - } else if (ret != 1) - ret = 0; - } - - if (ret) { - /* Remote WEB server is connected. - * Register the next step thread ssl_request_thread. - */ - DBG("Remote Web server %s connected.", FMT_CHK(checker)); - thread_add_write(thread->master, - http_request_thread, checker, - thread->u.f.fd, - checker->co->connection_to, true); - thread_del_read(thread); - } else { - DBG("Connection trouble to: %s." - , FMT_CHK(checker)); -#ifdef _DEBUG_ - if (http_get_check->proto == PROTO_SSL) - ssl_printerr(SSL_get_error - (req->ssl, ret)); -#endif - return timeout_epilog(thread, "SSL handshake/communication error" - " connecting to"); - } + http_send_proxy_protocol(thread); + timeout = timer_long(thread->sands) - timer_long(time_now); + thread_add_write(thread->master, http_check_thread, checker, thread->u.f.fd, timeout, true); break; } @@ -1686,7 +1741,7 @@ http_connect_thread(thread_ref_t thread) status = tcp_bind_connect(fd, co); /* handle tcp connection status & register check worker thread */ - if(tcp_connection_state(fd, status, thread, http_check_thread, + if(tcp_connection_state(fd, status, thread, http_proxy_protocol_thread, co->connection_to)) { close(fd); if (status == connect_fail) { @@ -1707,6 +1762,7 @@ register_check_http_addresses(void) { register_thread_address("http_check_thread", http_check_thread); register_thread_address("http_connect_thread", http_connect_thread); + register_thread_address("http_proxy_protocol_thread", http_proxy_protocol_thread); register_thread_address("http_read_thread", http_read_thread); register_thread_address("http_request_thread", http_request_thread); register_thread_address("http_response_thread", http_response_thread); From 2fd48edbebc2974ebb8b2e85ae2243e9b92a841f Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 7 Nov 2023 20:15:19 +0800 Subject: [PATCH 088/105] keepalived: fix a crash problem caused by the missing allowlist/denylist Signed-off-by: ywc689 --- tools/keepalived/keepalived/check/ipwrapper.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tools/keepalived/keepalived/check/ipwrapper.c b/tools/keepalived/keepalived/check/ipwrapper.c index 5d4d7b20d..d2658c067 100755 --- a/tools/keepalived/keepalived/check/ipwrapper.c +++ b/tools/keepalived/keepalived/check/ipwrapper.c @@ -1212,8 +1212,8 @@ clear_all_blklst_entry(list l, virtual_server_t * vs) static int clear_diff_blklst(virtual_server_t * old_vs, virtual_server_t * new_vs) { - blklst_addr_group *old; - blklst_addr_group *new; + blklst_addr_group *old = NULL; + blklst_addr_group *new = NULL; /* * If old vs didn't own blacklist address group, @@ -1225,6 +1225,8 @@ clear_diff_blklst(virtual_server_t * old_vs, virtual_server_t * new_vs) /* Fetch old_vs blacklist address group */ old = ipvs_get_blklst_group_by_name(old_vs->blklst_addr_gname, old_check_data->blklst_group); + if (!old) + return 1; /* if new_vs has no blacklist group, delete all blklst address from old_vs */ if (!new_vs->blklst_addr_gname) { @@ -1238,6 +1240,8 @@ clear_diff_blklst(virtual_server_t * old_vs, virtual_server_t * new_vs) /* Fetch new_vs blacklist address group */ new = ipvs_get_blklst_group_by_name(new_vs->blklst_addr_gname, check_data->blklst_group); + if (!new) + return 1; if (!clear_diff_blklst_entry(old->addr_ip, new->addr_ip, old_vs)) return 0; @@ -1305,8 +1309,8 @@ clear_all_whtlst_entry(list l, virtual_server_t * vs) static int clear_diff_whtlst(virtual_server_t * old_vs, virtual_server_t * new_vs) { - whtlst_addr_group *old; - whtlst_addr_group *new; + whtlst_addr_group *old = NULL; + whtlst_addr_group *new = NULL; /* * If old vs didn't own whitelist address group, * then do nothing and return @@ -1317,6 +1321,9 @@ clear_diff_whtlst(virtual_server_t * old_vs, virtual_server_t * new_vs) /* Fetch whitelist address group */ old = ipvs_get_whtlst_group_by_name(old_vs->whtlst_addr_gname, old_check_data->whtlst_group); + + if (!old) + return 1; /* if new_vs has no whitelist group, delete all whtlst address from old_vs */ if (!new_vs->whtlst_addr_gname) { if (!clear_all_whtlst_entry(old->addr_ip, old_vs)) @@ -1330,6 +1337,8 @@ clear_diff_whtlst(virtual_server_t * old_vs, virtual_server_t * new_vs) new = ipvs_get_whtlst_group_by_name(new_vs->whtlst_addr_gname, check_data->whtlst_group); + if (!new) + return 1; if (!clear_diff_whtlst_entry(old->addr_ip, new->addr_ip, old_vs)) return 0; if (!clear_diff_whtlst_entry(old->range, new->range, old_vs)) From 4a95793fbe6511c2544620ea47bf0e990b46e22d Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 8 Nov 2023 11:33:00 +0800 Subject: [PATCH 089/105] healtcheck: upd_check supports ppv2 Signed-off-by: ywc689 --- .../keepalived/keepalived/check/check_http.c | 16 ++++------ tools/keepalived/keepalived/check/check_udp.c | 29 +++++++++++++++++-- .../keepalived/include/check_data.h | 10 +++++++ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/tools/keepalived/keepalived/check/check_http.c b/tools/keepalived/keepalived/check/check_http.c index 670d0fad1..7d126cfa8 100644 --- a/tools/keepalived/keepalived/check/check_http.c +++ b/tools/keepalived/keepalived/check/check_http.c @@ -1551,26 +1551,22 @@ static int http_send_proxy_protocol(thread_ref_t thread) unsigned int len; char *ppbuf; - const char ppv2_local_cmd[] = { - 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, - 0x55, 0x49, 0x54, 0x0A, 0x20, 0x00, 0x00, 0x00, - }; assert(vs->proxy_protocol >= PROXY_PROTOCOL_DISABLE && vs->proxy_protocol < PROXY_PROTOCOL_MAX); - ppbuf = (char *) MALLOC(16); + ppbuf = (char *) MALLOC(PROXY_PROTOCOL_CHECK_MAX_LEN); if (!ppbuf) { return -1; } - memset(ppbuf, 0, 16); + memset(ppbuf, 0, PROXY_PROTOCOL_CHECK_MAX_LEN); if (PROXY_PROTOCOL_V1 == vs->proxy_protocol) { - len = 15; - sprintf(ppbuf, "%s", "PROXY UNKNOWN\r\n"); + len = PROXY_PROTOCOL_CHECK_V1_LEN; + sprintf(ppbuf, "%s", PROXY_PROTOCOL_CHECK_V1); } else if (PROXY_PROTOCOL_V2 == vs->proxy_protocol) { - len = 16; - memcpy(ppbuf, ppv2_local_cmd, 16); + len = PROXY_PROTOCOL_CHECK_V2_LEN; + memcpy(ppbuf, PROXY_PROTOCOL_CHECK_V2, PROXY_PROTOCOL_CHECK_V2_LEN); } if (send(thread->u.f.fd, ppbuf, len, 0) != len) { diff --git a/tools/keepalived/keepalived/check/check_udp.c b/tools/keepalived/keepalived/check/check_udp.c index 16a7ec336..1054eb634 100644 --- a/tools/keepalived/keepalived/check/check_udp.c +++ b/tools/keepalived/keepalived/check/check_udp.c @@ -321,6 +321,9 @@ udp_connect_thread(thread_ref_t thread) checker_t *checker = THREAD_ARG(thread); udp_check_t *udp_check = CHECKER_ARG(checker); conn_opts_t *co = checker->co; + uint8_t *payload; + uint16_t payload_len; + bool new_payload; int fd; int status; @@ -334,15 +337,35 @@ udp_connect_thread(thread_ref_t thread) return 0; } + if (PROXY_PROTOCOL_V2 == checker->vs->proxy_protocol) { + payload_len = udp_check->payload_len + PROXY_PROTOCOL_CHECK_V2_LEN; + if (!udp_check->payload_len) + payload_len += 16; + payload = MALLOC(payload_len); + if (!payload) + return 1; + new_payload = true; + memcpy(payload, PROXY_PROTOCOL_CHECK_V2, PROXY_PROTOCOL_CHECK_V2_LEN); + if (udp_check->payload_len > 0) + memcpy(payload + PROXY_PROTOCOL_CHECK_V2_LEN, udp_check->payload, udp_check->payload_len); + else + set_buf(payload + PROXY_PROTOCOL_CHECK_V2_LEN, 16); + } else { + payload_len = udp_check->payload_len; + payload = udp_check->payload; + new_payload = false; + } + if ((fd = socket(co->dst.ss_family, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_UDP)) == -1) { log_message(LOG_INFO, "UDP connect fail to create socket. Rescheduling."); thread_add_timer(thread->master, udp_connect_thread, checker, checker->delay_loop); - + if (new_payload) + FREE(payload); return 0; } - status = udp_bind_connect(fd, co, udp_check->payload, udp_check->payload_len); + status = udp_bind_connect(fd, co, payload, payload_len); /* handle udp connection status & register check worker thread */ if (udp_check_state(fd, status, thread, udp_check_thread, co->connection_to)) { @@ -350,6 +373,8 @@ udp_connect_thread(thread_ref_t thread) udp_epilog(thread, false); } + if (new_payload) + FREE(payload); return 0; } diff --git a/tools/keepalived/keepalived/include/check_data.h b/tools/keepalived/keepalived/include/check_data.h index 832a9e8bb..2d5debc66 100644 --- a/tools/keepalived/keepalived/include/check_data.h +++ b/tools/keepalived/keepalived/include/check_data.h @@ -46,6 +46,16 @@ /* Daemon dynamic data structure definition */ #define KEEPALIVED_DEFAULT_DELAY (60 * TIMER_HZ) #define TNLKINDSIZ 16 + +#define PROXY_PROTOCOL_CHECK_V1 "PROXY UNKNOWN\r\n" +static const char PROXY_PROTOCOL_CHECK_V2[] = { + 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, + 0x55, 0x49, 0x54, 0x0A, 0x20, 0x00, 0x00, 0x00, +}; +#define PROXY_PROTOCOL_CHECK_V1_LEN 15 +#define PROXY_PROTOCOL_CHECK_V2_LEN 16 +#define PROXY_PROTOCOL_CHECK_MAX_LEN 16 + /* SSL specific data */ typedef struct _ssl_data { int enable; From 70280c11ad71b4e74663659c0413710b2c33153f Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 8 Nov 2023 11:35:56 +0800 Subject: [PATCH 090/105] test: fix serveral trivial problems in proxy protocol test programs Signed-off-by: ywc689 --- test/proxy_protocol/proxy_protocol.c | 5 +++-- test/proxy_protocol/udp_server.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/test/proxy_protocol/proxy_protocol.c b/test/proxy_protocol/proxy_protocol.c index 3695e3fcb..543a7c1b3 100644 --- a/test/proxy_protocol/proxy_protocol.c +++ b/test/proxy_protocol/proxy_protocol.c @@ -29,10 +29,10 @@ int parse_proxy_protocol(char *buf, int len) { case 0x12: // UDPv4 ((struct sockaddr_in *)&from)->sin_family = AF_INET; ((struct sockaddr_in *)&from)->sin_addr.s_addr = phdr->v2.addr.ip4.src_addr; - ((struct sockaddr_in *)&from)->sin_port = phdr->v2.addr.ip4.src_addr; + ((struct sockaddr_in *)&from)->sin_port = phdr->v2.addr.ip4.src_port; ((struct sockaddr_in *)&to)->sin_family = AF_INET; ((struct sockaddr_in *)&to)->sin_addr.s_addr = phdr->v2.addr.ip4.dst_addr; - ((struct sockaddr_in *)&to)->sin_port = phdr->v2.addr.ip4.dst_addr; + ((struct sockaddr_in *)&to)->sin_port = phdr->v2.addr.ip4.dst_port; goto done; case 0x21: // TCPv6 case 0x22: // UDPv6 @@ -145,6 +145,7 @@ int parse_proxy_protocol(char *buf, int len) { // strip the proxy protocol data if (pplen < len) { memmove(buf, buf + pplen, len - pplen); + memset(buf + len - pplen, 0, len - pplen); } else { memset(buf, 0, len); } diff --git a/test/proxy_protocol/udp_server.c b/test/proxy_protocol/udp_server.c index 48a8cbacb..563f10239 100644 --- a/test/proxy_protocol/udp_server.c +++ b/test/proxy_protocol/udp_server.c @@ -49,7 +49,7 @@ static int handle_reply(int epfd, int fd) { port = ntohs(((struct sockaddr_in6 *)&peer)->sin6_port); } #ifdef LOG_VERBOSE - printf("%d bytes received from %s:%d: %s\n", len, addrbuf, port, buf); + printf("%d bytes received from %s:%d\n", len, addrbuf, port); #endif len = parse_proxy_protocol(buf, len); if (len > 0 && sendto(fd, buf, len, 0, From 94261d7fe3d2431996ae190036ccaf39eec924a9 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 8 Nov 2023 17:59:11 +0800 Subject: [PATCH 091/105] ipvs: fix problems found in debug of proxy protocol implementation Signed-off-by: ywc689 --- src/ipvs/ip_vs_proto_udp.c | 10 ++++++---- src/ipvs/ip_vs_proxy_proto.c | 25 ++++++++++++++++++------- src/ipvs/ip_vs_xmit.c | 3 +++ 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/ipvs/ip_vs_proto_udp.c b/src/ipvs/ip_vs_proto_udp.c index a8706346f..e5b90b344 100644 --- a/src/ipvs/ip_vs_proto_udp.c +++ b/src/ipvs/ip_vs_proto_udp.c @@ -710,7 +710,8 @@ static int udp_insert_uoa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, } static int udp_in_add_proxy_proto(struct dp_vs_conn *conn, - struct rte_mbuf *mbuf, struct rte_udp_hdr *udph, int iphdrlen) + struct rte_mbuf *mbuf, struct rte_udp_hdr *udph, + int iphdrlen, int *hdr_shift) { int offset; struct proxy_info ppinfo = { 0 }; @@ -742,7 +743,7 @@ static int udp_in_add_proxy_proto(struct dp_vs_conn *conn, } } - return proxy_proto_insert(&ppinfo, conn, mbuf, udph, NULL); + return proxy_proto_insert(&ppinfo, conn, mbuf, udph, hdr_shift); } static int udp_fnat_in_handler(struct dp_vs_proto *proto, @@ -755,6 +756,7 @@ static int udp_fnat_in_handler(struct dp_vs_proto *proto, /* af/mbuf may be changed for nat64 which in af is ipv6 and out is ipv4 */ int af = tuplehash_out(conn).af; int err, iphdrlen = 0; + int hdr_shift = 0; uint8_t nxt_proto; if (AF_INET6 == af) { @@ -786,7 +788,7 @@ static int udp_fnat_in_handler(struct dp_vs_proto *proto, if (!conn->pp_sent && (PROXY_PROTOCOL_V2 == conn->pp_version || PROXY_PROTOCOL_V2 == conn->pp_version)) { - err = udp_in_add_proxy_proto(conn, mbuf, uh, iphdrlen); + err = udp_in_add_proxy_proto(conn, mbuf, uh, iphdrlen, &hdr_shift); if (unlikely(EDPVS_OK != err)) RTE_LOG(INFO, IPVS, "%s: insert proxy protocol fail -- %s\n", __func__, dpvs_strerror(err)); @@ -794,8 +796,8 @@ static int udp_fnat_in_handler(struct dp_vs_proto *proto, // - proxy protocol insertion failed // - the first udp packet with proxy protocol data got lost in network conn->pp_sent = 1; + uh = ((void *)uh) + hdr_shift; } - uh->src_port = conn->lport; uh->dst_port = conn->dport; diff --git a/src/ipvs/ip_vs_proxy_proto.c b/src/ipvs/ip_vs_proxy_proto.c index 8804c1844..c145b327e 100644 --- a/src/ipvs/ip_vs_proxy_proto.c +++ b/src/ipvs/ip_vs_proxy_proto.c @@ -259,7 +259,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, } uh->src_port = conn->lport; uh->dst_port = conn->dport; - uh->dgram_len = htons(sizeof(struct rte_udp_hdr)); + uh->dgram_len = htons(sizeof(struct rte_udp_hdr) + ppdlen); uh->dgram_cksum = 0; l4hdr = uh; } @@ -273,10 +273,10 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, if (PROXY_PROTOCOL_V2 == conn->pp_version) { pphv2 = (struct proxy_hdr_v2 *)pph; rte_memcpy(pphv2->sig, PROXY_PROTO_V2_SIGNATURE, sizeof(pphv2->sig)); - pphv2->cmd = ppinfo->cmd & 0xF; - pphv2->ver = ppinfo->version & 0xF; - pphv2->proto = ppinfo->proto & 0xF; - pphv2->af = ppinfo->af & 0xF; + pphv2->cmd = ppinfo->cmd & 0xF; + pphv2->ver = ppinfo->version & 0xF; + pphv2->proto = ppv2_proto_host2pp(ppinfo->proto); + pphv2->af = ppv2_af_host2pp(ppinfo->af); pphv2->addrlen = ntohs(ppdlen - sizeof(struct proxy_hdr_v2)); rte_memcpy(pphv2 + 1, &ppinfo->addr, ppdlen - sizeof(struct proxy_hdr_v2)); } else if (PROXY_PROTOCOL_V1 == conn->pp_version) { @@ -486,19 +486,30 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, rte_memcpy(pphv2->sig, PROXY_PROTO_V2_SIGNATURE, sizeof(pphv2->sig)); pphv2->cmd = ppinfo->cmd & 0xF; pphv2->ver = ppinfo->version & 0xF; - pphv2->proto = ppinfo->proto & 0xF; - pphv2->af = ppinfo->af & 0xF; + pphv2->af = ppv2_af_host2pp(ppinfo->af); + pphv2->proto = ppv2_proto_host2pp(ppinfo->proto); pphv2->addrlen = ntohs(ppdatalen - sizeof(struct proxy_hdr_v2)); rte_memcpy(pphv2 + 1, &ppinfo->addr, ppdatalen - sizeof(struct proxy_hdr_v2)); } else { // PROXY_PROTOCOL_V1 rte_memcpy(pph, ppv1buf, ppdatalen); } + // updata length members in ppinfo and mbuf ppinfo->datalen = ppdatalen; + l4hdr += *hdr_shift; if (IPPROTO_TCP == conn->proto) { // ajust inbound tcp sequence number except for the first segment ((struct tcphdr *)l4hdr)->seq = htonl(((struct tcphdr *)l4hdr)->seq - ppdatalen); conn->fnat_seq.delta += ppdatalen; + } else if (IPPROTO_UDP == conn->proto) { + ((struct rte_udp_hdr *)l4hdr)->dgram_len = htons(ntohs( + ((struct rte_udp_hdr *)l4hdr)->dgram_len) + ppdatalen); } + if (AF_INET == tuplehash_out(conn).af) + ((struct iphdr *)iph)->tot_len = htons(ntohs(((struct iphdr *)iph)->tot_len) + ppdatalen); + else + ((struct rte_ipv6_hdr *)iph)->payload_len = htons(ntohs( + ((struct rte_ipv6_hdr *)iph)->payload_len) + ppdatalen); + return EDPVS_OK; } diff --git a/src/ipvs/ip_vs_xmit.c b/src/ipvs/ip_vs_xmit.c index d9a359ce8..a39b0df10 100644 --- a/src/ipvs/ip_vs_xmit.c +++ b/src/ipvs/ip_vs_xmit.c @@ -70,6 +70,7 @@ static int __dp_vs_fast_xmit_fnat4(struct dp_vs_proto *proto, err = proto->fnat_in_handler(proto, conn, mbuf); if(err != EDPVS_OK) return err; + ip4h = ip4_hdr(mbuf); } if (likely(mbuf->ol_flags & PKT_TX_IP_CKSUM)) { @@ -476,6 +477,7 @@ static int __dp_vs_xmit_fnat4(struct dp_vs_proto *proto, err = proto->fnat_in_handler(proto, conn, mbuf); if (err != EDPVS_OK) goto errout; + iph = ip4_hdr(mbuf); } if (likely(mbuf->ol_flags & PKT_TX_IP_CKSUM)) { @@ -674,6 +676,7 @@ static int __dp_vs_xmit_fnat64(struct dp_vs_proto *proto, err = proto->fnat_in_handler(proto, conn, mbuf); if (err != EDPVS_OK) goto errout; + ip4h = ip4_hdr(mbuf); } if (likely(mbuf->ol_flags & PKT_TX_IP_CKSUM)) { From 60f7789103ff73647cea8e1463001deb16c7c61a Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 10 Nov 2023 14:57:57 +0800 Subject: [PATCH 092/105] ipvs: fix standalone tcp proxy protocol packet sent problem --- include/ipvs/conn.h | 2 +- include/ipvs/proto_tcp.h | 1 + src/ipvs/ip_vs_proto_tcp.c | 2 +- src/ipvs/ip_vs_proxy_proto.c | 112 ++++++++++++++++++++++++++++------- 4 files changed, 93 insertions(+), 24 deletions(-) diff --git a/include/ipvs/conn.h b/include/ipvs/conn.h index 9e3ebf428..843721e92 100644 --- a/include/ipvs/conn.h +++ b/include/ipvs/conn.h @@ -150,7 +150,7 @@ struct dp_vs_conn { rte_atomic32_t dup_ack_cnt; /* count of repeated ack packets */ uint8_t pp_version; /* proxy protocol version */ - uint8_t pp_sent; /* proxy protocol data has sent, for udp only */ + uint8_t pp_sent; /* proxy protocol data has sent */ /* flags and state transition */ volatile uint16_t flags; diff --git a/include/ipvs/proto_tcp.h b/include/ipvs/proto_tcp.h index e166ad364..3d1515a16 100644 --- a/include/ipvs/proto_tcp.h +++ b/include/ipvs/proto_tcp.h @@ -108,5 +108,6 @@ int tcp_send_csum(int af, int iphdrlen, struct tcphdr *th, struct rte_mempool *get_mbuf_pool(const struct dp_vs_conn *conn, int dir); void install_proto_tcp_keywords(void); void tcp_keyword_value_init(void); +void tcp_in_adjust_seq(struct dp_vs_conn *conn, struct tcphdr *th); #endif diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 7b910791a..581966c0f 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -258,7 +258,7 @@ static inline void tcp_in_init_seq(struct dp_vs_conn *conn, return; } -static inline void tcp_in_adjust_seq(struct dp_vs_conn *conn, struct tcphdr *th) +void tcp_in_adjust_seq(struct dp_vs_conn *conn, struct tcphdr *th) { th->seq = htonl(ntohl(th->seq) + conn->fnat_seq.delta); /* recalc checksum later */ diff --git a/src/ipvs/ip_vs_proxy_proto.c b/src/ipvs/ip_vs_proxy_proto.c index c145b327e..35d324f80 100644 --- a/src/ipvs/ip_vs_proxy_proto.c +++ b/src/ipvs/ip_vs_proxy_proto.c @@ -178,27 +178,79 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, int err; int ppdoff; int iaf, oaf; - void *rt; void *iph, *oiph, *pph, *l4hdr; + void *rt; + struct netif_port *dev = NULL; struct tcphdr *th; struct rte_udp_hdr *uh; struct rte_mbuf *mbuf = NULL; struct proxy_hdr_v2 *pphv2; + struct flow4 fl4; + struct flow6 fl6; + uint8_t pp_sent = 1; - rt = MBUF_USERDATA_CONST(ombuf, void *, MBUF_FIELD_ROUTE); - if (unlikely(!rt)) - return EDPVS_NOROUTE; - - iaf = tuplehash_in(conn).af; - oaf = tuplehash_out(conn).af; oiph = rte_pktmbuf_mtod(ombuf, void *); - if (IPPROTO_TCP == conn->proto) + if (IPPROTO_TCP == conn->proto) { ppdoff = ol4hdr + (((struct tcphdr *)ol4hdr)->doff << 2) - oiph; - else + + // Note#1: There's a extremly rare case where the standalone proxy protocol packet + // is triggered by a pure ack tcp packet that contains no application data. The seq + // number of the next packet in this direction would stay the same as this ack packet, + // so proxy protocol data is also inserted to it by mistake, causing problem for the + // tcp connection. The problem is fixed by using a special value 2 for the conn->pp_sent + // flag, at the cost of the loss of tcp retransmission functionality for this standalone + // proxy protocol packet.(Can we not consider this abnormal rare case?) + if (unlikely(ombuf->pkt_len == ppdoff)) { + RTE_LOG(WARNING, IPVS, "%s triggered by a pure ack tcp mbuf of length %d\n", + __func__, ombuf->pkt_len); + pp_sent = 2; + } + } else { ppdoff = ol4hdr + sizeof(struct rte_udp_hdr) - oiph; + } assert(ppdoff > 0); - mbuf = rte_pktmbuf_alloc(ombuf->pool); + iaf = tuplehash_in(conn).af; + oaf = tuplehash_out(conn).af; + rt = MBUF_USERDATA_CONST(ombuf, void *, MBUF_FIELD_ROUTE); + if (!rt) { + // fast-xmit only cached dev, not route, + // so we have to look up route from route table + if (AF_INET6 == oaf) { + memset(&fl6, 0, sizeof(fl6)); + fl6.fl6_saddr = conn->laddr.in6; + fl6.fl6_daddr = conn->daddr.in6; + fl6.fl6_sport = conn->lport; + fl6.fl6_dport = conn->dport; + fl6.fl6_proto = conn->proto; + rt = route6_output(NULL, &fl6); + if (unlikely(!rt)) + return EDPVS_NOROUTE; + dev = ((struct route6 *)rt)->rt6_dev; + route6_put(rt); + } else { + memset(&fl4, 0, sizeof(fl4)); + fl4.fl4_saddr = conn->laddr.in; + fl4.fl4_daddr = conn->daddr.in; + fl4.fl4_sport = conn->lport; + fl4.fl4_dport = conn->dport; + fl4.fl4_proto = conn->proto; + rt = route4_output(&fl4); + if (unlikely(!rt)) + return EDPVS_NOROUTE; + dev = ((struct route_entry *)rt)->port; + route4_put(rt); + } + } else { + if (AF_INET6 == oaf) + dev =((struct route6 *)rt)->rt6_dev; + else + dev = ((struct route_entry *)rt)->port; + } + if (unlikely(!dev)) + return EDPVS_NOROUTE; + + mbuf = rte_pktmbuf_alloc(dev->mbuf_pool); if (unlikely(!mbuf)) return EDPVS_NOMEM; mbuf_userdata_reset(mbuf); @@ -250,6 +302,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, th->ack = 1; th->window = ((struct tcphdr *)ol4hdr)->window; th->check = 0; + tcp_in_adjust_seq(conn, th); l4hdr = th; } else { // IPPROTO_UDP uh = (struct rte_udp_hdr *)rte_pktmbuf_append(mbuf, sizeof(struct rte_udp_hdr)); @@ -350,7 +403,8 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, ppinfo->datalen = 0; } - if (IPPROTO_TCP == conn->proto) { + if (!conn->pp_sent && IPPROTO_TCP == conn->proto) { + conn->pp_sent = pp_sent; conn->fnat_seq.delta += ppdlen; } @@ -368,16 +422,31 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, assert(ppinfo && conn && mbuf && l4hdr); - rt = MBUF_USERDATA_CONST(mbuf, void *, MBUF_FIELD_ROUTE); - if (unlikely(!rt)) - return EDPVS_NOROUTE; - if (unlikely(conn->dest->fwdmode != DPVS_FWD_MODE_FNAT)) return EDPVS_NOTSUPP; if (ppinfo->datalen > 0 && ppinfo->version == conn->pp_version) return EDPVS_OK; // proxy the existing proxy protocol data directly to rs + if (unlikely(2 == conn->pp_sent) && IPPROTO_TCP == conn->proto) + return EDPVS_OK; // refer to comment [Notes#1] in `proxy_proto_send_standalone` + + rt = MBUF_USERDATA_CONST(mbuf, void *, MBUF_FIELD_ROUTE); + if (rt) { + if (AF_INET6 == tuplehash_out(conn).af) + mtu = ((struct route6 *)rt)->rt6_mtu; + else + mtu = ((struct route_entry *)rt)->mtu; + } else if (conn->in_dev) { + // fast-xmit + mtu = conn->in_dev->mtu; + } else { + return EDPVS_NOROUTE; + } + + // just a test + // mtu = 0; + // calculate required space size in mbuf ppdatalen = 0; if (PROXY_PROTOCOL_V2 == conn->pp_version) { @@ -452,10 +521,6 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, room = ppdatalen - ppinfo->datalen; if (room > 0) { // allocate space from mbuf headroom - if (AF_INET6 == tuplehash_out(conn).af) - mtu = ((struct route6 *)rt)->rt6_mtu; - else - mtu = ((struct route_entry *)rt)->mtu; if (mbuf->pkt_len + room > mtu) return proxy_proto_send_standalone(ppinfo, conn, mbuf, l4hdr, hdr_shift, ppdatalen, ppv1buf); niph = rte_pktmbuf_prepend(mbuf, room); @@ -494,13 +559,16 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, rte_memcpy(pph, ppv1buf, ppdatalen); } - // updata length members in ppinfo and mbuf + // updata ppinfo and mbuf headers ppinfo->datalen = ppdatalen; l4hdr += *hdr_shift; if (IPPROTO_TCP == conn->proto) { // ajust inbound tcp sequence number except for the first segment - ((struct tcphdr *)l4hdr)->seq = htonl(((struct tcphdr *)l4hdr)->seq - ppdatalen); - conn->fnat_seq.delta += ppdatalen; + ((struct tcphdr *)l4hdr)->seq = htonl(ntohl(((struct tcphdr *)l4hdr)->seq) - ppdatalen); + if (!conn->pp_sent) { + conn->pp_sent = 1; + conn->fnat_seq.delta += ppdatalen; + } } else if (IPPROTO_UDP == conn->proto) { ((struct rte_udp_hdr *)l4hdr)->dgram_len = htons(ntohs( ((struct rte_udp_hdr *)l4hdr)->dgram_len) + ppdatalen); From 6186642743dead03fffbd550916632ca730d927f Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 10 Nov 2023 17:10:19 +0800 Subject: [PATCH 093/105] ipvs: forbid sending proxy protocol data in pure tcp ack packets Signed-off-by: ywc689 --- src/ipvs/ip_vs_proto_tcp.c | 13 +++++++++++++ src/ipvs/ip_vs_proxy_proto.c | 23 +++-------------------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 581966c0f..4129592b9 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -355,6 +355,19 @@ static int tcp_in_add_proxy_proto(struct dp_vs_conn *conn, struct rte_mbuf *mbuf struct proxy_info ppinfo = { 0 }; offset = iphdrlen + (tcph->doff << 2); + if (offset == mbuf->pkt_len) { + // Don't send proxy protocol data in pure ack packets that contains no + // application data. Otherwise, the proxy protocol data is sent twice, + // one in this ack packet, and another in the first tcp packet with payload + // and same beginning seq number. Worse still, if the proxy protocol data + // is sent in a standalone packet (despite of the rareness of the case), the + // second proxy protocol data would be taken as application payload, causing + // problem for the tcp connection (refer to a fix for the problem in #7561d1087). + // Ths problem would get more complicated when taking into considertation of + // tcp retransmission. + return EDPVS_OK; + } + if (unlikely(EDPVS_OK != proxy_proto_parse(mbuf, offset, &ppinfo))) return EDPVS_INVPKT; diff --git a/src/ipvs/ip_vs_proxy_proto.c b/src/ipvs/ip_vs_proxy_proto.c index 35d324f80..b710d2bbe 100644 --- a/src/ipvs/ip_vs_proxy_proto.c +++ b/src/ipvs/ip_vs_proxy_proto.c @@ -190,24 +190,10 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, uint8_t pp_sent = 1; oiph = rte_pktmbuf_mtod(ombuf, void *); - if (IPPROTO_TCP == conn->proto) { + if (IPPROTO_TCP == conn->proto) ppdoff = ol4hdr + (((struct tcphdr *)ol4hdr)->doff << 2) - oiph; - - // Note#1: There's a extremly rare case where the standalone proxy protocol packet - // is triggered by a pure ack tcp packet that contains no application data. The seq - // number of the next packet in this direction would stay the same as this ack packet, - // so proxy protocol data is also inserted to it by mistake, causing problem for the - // tcp connection. The problem is fixed by using a special value 2 for the conn->pp_sent - // flag, at the cost of the loss of tcp retransmission functionality for this standalone - // proxy protocol packet.(Can we not consider this abnormal rare case?) - if (unlikely(ombuf->pkt_len == ppdoff)) { - RTE_LOG(WARNING, IPVS, "%s triggered by a pure ack tcp mbuf of length %d\n", - __func__, ombuf->pkt_len); - pp_sent = 2; - } - } else { + else ppdoff = ol4hdr + sizeof(struct rte_udp_hdr) - oiph; - } assert(ppdoff > 0); iaf = tuplehash_in(conn).af; @@ -428,9 +414,6 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, if (ppinfo->datalen > 0 && ppinfo->version == conn->pp_version) return EDPVS_OK; // proxy the existing proxy protocol data directly to rs - if (unlikely(2 == conn->pp_sent) && IPPROTO_TCP == conn->proto) - return EDPVS_OK; // refer to comment [Notes#1] in `proxy_proto_send_standalone` - rt = MBUF_USERDATA_CONST(mbuf, void *, MBUF_FIELD_ROUTE); if (rt) { if (AF_INET6 == tuplehash_out(conn).af) @@ -444,7 +427,7 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, return EDPVS_NOROUTE; } - // just a test + // just a test for standalone sending // mtu = 0; // calculate required space size in mbuf From 57d7bc8cf8dc81ca0aa4bce38c6f328b92b816a5 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 13 Nov 2023 17:58:42 +0800 Subject: [PATCH 094/105] ipvs: fix serveral problems in sending standalone proxy protocol packets Signed-off-by: ywc689 --- src/ipvs/ip_vs_proxy_proto.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ipvs/ip_vs_proxy_proto.c b/src/ipvs/ip_vs_proxy_proto.c index b710d2bbe..6bdfa3afb 100644 --- a/src/ipvs/ip_vs_proxy_proto.c +++ b/src/ipvs/ip_vs_proxy_proto.c @@ -198,6 +198,8 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, iaf = tuplehash_in(conn).af; oaf = tuplehash_out(conn).af; + assert(iaf == ppinfo->af); + rt = MBUF_USERDATA_CONST(ombuf, void *, MBUF_FIELD_ROUTE); if (!rt) { // fast-xmit only cached dev, not route, @@ -242,7 +244,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, mbuf_userdata_reset(mbuf); // L3 header - if (AF_INET6 == iaf) { + if (AF_INET6 == oaf) { iph = rte_pktmbuf_append(mbuf, sizeof(struct rte_ipv6_hdr)); if (unlikely(!iph)) { err = EDPVS_NOMEM; @@ -360,7 +362,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, } } else { ((struct iphdr *)iph)->tot_len = htons(mbuf->pkt_len); - // notes: ipv4 udp checksum is not a mandatory + // notes: ipv4 udp checksum is not mandatory err = udp_send_csum(AF_INET, sizeof(struct rte_ipv4_hdr), l4hdr, conn, mbuf, NULL, ((struct route_entry *)rt)->port); if (unlikely(EDPVS_OK != err)) { @@ -463,7 +465,7 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, tbuf2, sizeof(tbuf2)))) return EDPVS_INVAL; sprintf(ppv1buf, "PROXY TCP4 %s %s %d %d\r\n", tbuf1, tbuf2, - ppinfo->addr.ip4.src_port, ppinfo->addr.ip4.dst_port); + htons(ppinfo->addr.ip4.src_port), htons(ppinfo->addr.ip4.dst_port)); break; case AF_INET6: if (unlikely(NULL == inet_ntop(AF_INET6, ppinfo->addr.ip6.src_addr, @@ -473,7 +475,7 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, tbuf2, sizeof(tbuf2)))) return EDPVS_INVAL; sprintf(ppv1buf, "PROXY TCP6 %s %s %d %d\r\n", tbuf1, tbuf2, - ppinfo->addr.ip4.src_port, ppinfo->addr.ip4.dst_port); + htons(ppinfo->addr.ip6.src_port), htons(ppinfo->addr.ip6.dst_port)); break; default: return EDPVS_NOTSUPP; From 4aa1e6836d5cad3694095eb66832a40814fb2e5a Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 15 Nov 2023 16:16:44 +0800 Subject: [PATCH 095/105] ipvs: fix dozens of problems found in proxy protocol cascading test Signed-off-by: ywc689 --- src/ipvs/ip_vs_proto_tcp.c | 13 +++-- src/ipvs/ip_vs_proxy_proto.c | 99 ++++++++++++++++++++++-------------- 2 files changed, 69 insertions(+), 43 deletions(-) diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 4129592b9..1cb403442 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -841,11 +841,14 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, && !th->syn && !th->rst /*&& !th->fin*/) { if (PROXY_PROTOCOL_V2 == conn->pp_version || PROXY_PROTOCOL_V1 == conn->pp_version) { - err = tcp_in_add_proxy_proto(conn, mbuf, th, iphdrlen, &pp_hdr_shift); - if (unlikely(EDPVS_OK != err)) - RTE_LOG(INFO, IPVS, "%s: insert proxy protocol fail -- %s\n", - __func__, dpvs_strerror(err)); - th = ((void *)th) + pp_hdr_shift; + if (conn->fnat_seq.isn - conn->fnat_seq.delta + 1 == ntohl(th->seq)) { + /* avoid inserting repetitive ppdata when the first rs ack delayed */ + err = tcp_in_add_proxy_proto(conn, mbuf, th, iphdrlen, &pp_hdr_shift); + if (unlikely(EDPVS_OK != err)) + RTE_LOG(INFO, IPVS, "%s: insert proxy protocol fail -- %s\n", + __func__, dpvs_strerror(err)); + th = ((void *)th) + pp_hdr_shift; + } } else { if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { tcp_in_remove_toa(th, iaf); diff --git a/src/ipvs/ip_vs_proxy_proto.c b/src/ipvs/ip_vs_proxy_proto.c index 6bdfa3afb..f0a4fbe0e 100644 --- a/src/ipvs/ip_vs_proxy_proto.c +++ b/src/ipvs/ip_vs_proxy_proto.c @@ -36,13 +36,14 @@ int proxy_proto_parse(struct rte_mbuf *mbuf, int ppdoff, struct proxy_info *ppin struct proxy_addr_ipv6 *addr6; struct proxy_addr_unix *addrunx; - offset = ppdoff + 12; - pphdr = rte_pktmbuf_mtod(mbuf, void *); - memset(ppinfo, 0, sizeof(struct proxy_info)); - - if (mbuf_may_pull(mbuf, offset)) + offset = ppdoff; + if (mbuf_may_pull(mbuf, offset + 12)) return EDPVS_OK; /* too small to reside pp data */ + pphdr = rte_pktmbuf_mtod_offset(mbuf, void *, offset); + memset(ppinfo, 0, sizeof(struct proxy_info)); + offset += 12; + if (!memcmp(pphdr, PROXY_PROTO_V2_SIGNATURE, 12)) { offset += 4; if (mbuf_may_pull(mbuf, offset)) @@ -91,19 +92,20 @@ int proxy_proto_parse(struct rte_mbuf *mbuf, int ppdoff, struct proxy_info *ppin return EDPVS_OK; } else if (!memcmp(pphdr, "PROXY ", 6)) { ppdlen = strcspn((const char *)pphdr, "\n"); - if (unlikely(ppdlen > PROXY_PROTO_V1_MAX_DATALEN)) + if (unlikely(ppdlen > PROXY_PROTO_V1_MAX_DATALEN || ppdlen <= 0)) return EDPVS_INVPKT; + ppdlen += 1; // count in '\n' offset = ppdoff + ppdlen; if (mbuf_may_pull(mbuf, offset)) return EDPVS_INVPKT; memcpy(buf, pphdr, ppdlen); - buf[ppdlen] = '\0'; - if (ppdlen > 1 && buf[ppdlen-1] == '\r') - buf[ppdlen-1] = '\0'; + buf[ppdlen-1] = '\0'; + if (ppdlen > 1 && buf[ppdlen-2] == '\r') + buf[ppdlen-2] = '\0'; if (NULL == (token = strtok_r(buf, " ", &tmp))) /* "PROXY" */ return EDPVS_INVAL; ppinfo->version = PROXY_PROTOCOL_V1; - if (NULL == (token = strtok_r(buf, " ", &tmp))) /* TCP4 | TCP6 */ + if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* TCP4 | TCP6 */ return EDPVS_INVAL; if (!memcmp(token, "TCP4", 4)) { ppinfo->af = AF_INET; @@ -177,7 +179,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, { int err; int ppdoff; - int iaf, oaf; + int oaf; void *iph, *oiph, *pph, *l4hdr; void *rt; struct netif_port *dev = NULL; @@ -196,10 +198,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, ppdoff = ol4hdr + sizeof(struct rte_udp_hdr) - oiph; assert(ppdoff > 0); - iaf = tuplehash_in(conn).af; oaf = tuplehash_out(conn).af; - assert(iaf == ppinfo->af); - rt = MBUF_USERDATA_CONST(ombuf, void *, MBUF_FIELD_ROUTE); if (!rt) { // fast-xmit only cached dev, not route, @@ -314,8 +313,8 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, if (PROXY_PROTOCOL_V2 == conn->pp_version) { pphv2 = (struct proxy_hdr_v2 *)pph; rte_memcpy(pphv2->sig, PROXY_PROTO_V2_SIGNATURE, sizeof(pphv2->sig)); - pphv2->cmd = ppinfo->cmd & 0xF; - pphv2->ver = ppinfo->version & 0xF; + pphv2->cmd = 1; + pphv2->ver = PROXY_PROTOCOL_V2; pphv2->proto = ppv2_proto_host2pp(ppinfo->proto); pphv2->af = ppv2_af_host2pp(ppinfo->af); pphv2->addrlen = ntohs(ppdlen - sizeof(struct proxy_hdr_v2)); @@ -382,20 +381,36 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, return err; finish: + // adjust tcp seq number + if (!conn->pp_sent && IPPROTO_TCP == conn->proto) { + conn->pp_sent = pp_sent; + conn->fnat_seq.delta += ppdlen - ppinfo->datalen; + } + + // adjust protocol data in mbuf and // remove the existing proxy protocol data from original mbuf if (ppinfo->datalen > 0) { - memmove(oiph + ppdoff, oiph, ppdoff); + if (IPPROTO_UDP == conn->proto) { + ((struct rte_udp_hdr *)ol4hdr)->dgram_len = htons(ntohs( + ((struct rte_udp_hdr *)ol4hdr)->dgram_len) - ppinfo->datalen); + } else { + // don't count original ppdatalen in tcp seq ajustment for ombuf + ((struct tcphdr *)ol4hdr)->seq = htonl(ntohl( + ((struct tcphdr *)ol4hdr)->seq) + ppinfo->datalen); + } + if (AF_INET == oaf) + ((struct iphdr *)oiph)->tot_len = htons(ntohs(((struct iphdr *) + oiph)->tot_len) - ppinfo->datalen); + else + ((struct rte_ipv6_hdr *)oiph)->payload_len = htons(ntohs(((struct rte_ipv6_hdr *) + oiph)->payload_len) - ppinfo->datalen); + memmove(oiph + ppinfo->datalen, oiph, ppinfo->datalen); if (hdr_shift) - *hdr_shift = ppdoff; - rte_pktmbuf_adj(ombuf, ppdoff); + *hdr_shift = ppinfo->datalen; + rte_pktmbuf_adj(ombuf, ppinfo->datalen); ppinfo->datalen = 0; } - if (!conn->pp_sent && IPPROTO_TCP == conn->proto) { - conn->pp_sent = pp_sent; - conn->fnat_seq.delta += ppdlen; - } - return EDPVS_OK; } @@ -405,20 +420,25 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, void *iph, *pph, *niph; void *rt; int ppdoff, ppdatalen, room, mtu; + int oaf; char ppv1buf[108], tbuf1[64], tbuf2[64]; struct proxy_hdr_v2 *pphv2; assert(ppinfo && conn && mbuf && l4hdr); + if (unlikely(conn->proto != ppinfo->proto)) + return EDPVS_INVAL; + if (unlikely(conn->dest->fwdmode != DPVS_FWD_MODE_FNAT)) return EDPVS_NOTSUPP; if (ppinfo->datalen > 0 && ppinfo->version == conn->pp_version) return EDPVS_OK; // proxy the existing proxy protocol data directly to rs + oaf = tuplehash_out(conn).af; rt = MBUF_USERDATA_CONST(mbuf, void *, MBUF_FIELD_ROUTE); if (rt) { - if (AF_INET6 == tuplehash_out(conn).af) + if (AF_INET6 == oaf) mtu = ((struct route6 *)rt)->rt6_mtu; else mtu = ((struct route_entry *)rt)->mtu; @@ -429,9 +449,6 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, return EDPVS_NOROUTE; } - // just a test for standalone sending - // mtu = 0; - // calculate required space size in mbuf ppdatalen = 0; if (PROXY_PROTOCOL_V2 == conn->pp_version) { @@ -502,6 +519,10 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, default: return EDPVS_NOTSUPP; } + + // just a test for standalone sending + // return proxy_proto_send_standalone(ppinfo, conn, mbuf, l4hdr, hdr_shift, ppdatalen, ppv1buf); + assert(ppdoff > 0); room = ppdatalen - ppinfo->datalen; if (room > 0) { @@ -534,8 +555,8 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, if (PROXY_PROTOCOL_V2 == conn->pp_version) { pphv2 = (struct proxy_hdr_v2 *)pph; rte_memcpy(pphv2->sig, PROXY_PROTO_V2_SIGNATURE, sizeof(pphv2->sig)); - pphv2->cmd = ppinfo->cmd & 0xF; - pphv2->ver = ppinfo->version & 0xF; + pphv2->cmd = 1; + pphv2->ver = PROXY_PROTOCOL_V2; pphv2->af = ppv2_af_host2pp(ppinfo->af); pphv2->proto = ppv2_proto_host2pp(ppinfo->proto); pphv2->addrlen = ntohs(ppdatalen - sizeof(struct proxy_hdr_v2)); @@ -545,24 +566,26 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, } // updata ppinfo and mbuf headers - ppinfo->datalen = ppdatalen; l4hdr += *hdr_shift; if (IPPROTO_TCP == conn->proto) { // ajust inbound tcp sequence number except for the first segment - ((struct tcphdr *)l4hdr)->seq = htonl(ntohl(((struct tcphdr *)l4hdr)->seq) - ppdatalen); + ((struct tcphdr *)l4hdr)->seq = htonl(ntohl(((struct tcphdr *)l4hdr)->seq) + - ppdatalen + ppinfo->datalen); if (!conn->pp_sent) { conn->pp_sent = 1; - conn->fnat_seq.delta += ppdatalen; + conn->fnat_seq.delta += ppdatalen - ppinfo->datalen; } } else if (IPPROTO_UDP == conn->proto) { ((struct rte_udp_hdr *)l4hdr)->dgram_len = htons(ntohs( - ((struct rte_udp_hdr *)l4hdr)->dgram_len) + ppdatalen); + ((struct rte_udp_hdr *)l4hdr)->dgram_len) + ppdatalen - ppinfo->datalen); } - if (AF_INET == tuplehash_out(conn).af) - ((struct iphdr *)iph)->tot_len = htons(ntohs(((struct iphdr *)iph)->tot_len) + ppdatalen); + if (AF_INET == oaf) + ((struct iphdr *)iph)->tot_len = htons(ntohs(((struct iphdr *)iph)->tot_len) + + ppdatalen - ppinfo->datalen); else - ((struct rte_ipv6_hdr *)iph)->payload_len = htons(ntohs( - ((struct rte_ipv6_hdr *)iph)->payload_len) + ppdatalen); + ((struct rte_ipv6_hdr *)iph)->payload_len = htons(ntohs(((struct rte_ipv6_hdr *) + iph)->payload_len) + ppdatalen - ppinfo->datalen); + ppinfo->datalen = ppdatalen; return EDPVS_OK; } From d3f08991a2a083d3090180b3692ccedfb9e1db1f Mon Sep 17 00:00:00 2001 From: ywc689 Date: Wed, 15 Nov 2023 16:41:23 +0800 Subject: [PATCH 096/105] test: add test checklist for proxy protocol Signed-off-by: ywc689 --- test/proxy_protocol/checklist.md | 90 +++++++++++++++++++ test/proxy_protocol/nginx/nginx.conf | 3 +- .../pkg/helthcheck/http_checker_test.go | 2 + 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 test/proxy_protocol/checklist.md diff --git a/test/proxy_protocol/checklist.md b/test/proxy_protocol/checklist.md new file mode 100644 index 000000000..3511aae83 --- /dev/null +++ b/test/proxy_protocol/checklist.md @@ -0,0 +1,90 @@ +Checklist +========= + +> notes: +> * [x]: test passed +> * [ ]: not support or untested + +* [x] PPv2 + FNAT44 + TCP +* [x] PPv2 + FNAT44 + TCP + Synproxy +* [x] PPv2 + FNAT44 + UDP +* [x] PPv1 + FNAT44 + TCP +* [x] PPv1 + FNAT44 + TCP + Synproxy +* [x] standalone PPv2 + FNAT44 + TCP +* [x] standalone PPv2 + FNAT44 + TCP +* [x] standalone PPv2 + FNAT44 + UDP +* [x] standalone PPv1 + FNAT44 + TCP +* [x] standalone PPv1 + FNAT44 + TCP + +* [x] PPv2 + FNAT64 + TCP +* [x] PPv2 + FNAT64 + TCP + Synproxy +* [x] PPv2 + FNAT64 + UDP +* [x] PPv1 + FNAT64 + TCP +* [x] PPv1 + FNAT64 + TCP + Synproxy +* [x] standalone PPv2 + FNAT64 + TCP +* [x] standalone PPv2 + FNAT64 + TCP + Synproxy +* [x] standalone PPv2 + FNAT64 + UDP +* [x] standalone PPv1 + FNAT64 + TCP +* [x] standalone PPv1 + FNAT64 + TCP + Synproxy + +* [x] PPv2 + FNAT66 + TCP +* [x] PPv2 + FNAT66 + TCP + Synproxy +* [x] PPv2 + FNAT66 + UDP +* [x] PPv1 + FNAT66 + TCP +* [x] PPv1 + FNAT66 + TCP + Synproxy +* [x] standalone PPv2 + FNAT66 + TCP +* [x] standalone PPv2 + FNAT66 + TCP + Synproxy +* [x] standalone PPv2 + FNAT66 + UDP +* [x] standalone PPv1 + FNAT66 + TCP +* [x] standalone PPv1 + FNAT66 + TCP + Synproxy + +* [x] tools/keepalived HTTP_CHECKER + IPv4 backends +* [x] tools/keepalived UDP_CHECKER with payload + IPv4 backends +* [x] tools/keepalived HTTP_CHECKER + IPv6 backends +* [x] tools/eepalived UDP_CHECKER with payload + IPv6 backends +* [x] tools/healthcheck http_checker + IPv4 backends +* [ ] tools/healthcheck tcp_checker with payload + IPv4 backends: NOT SUPPORT +* [ ] tools/healthcheck udp_checker with payload + IPv4 backends: NOT SUPPORT +* [ ] tools/healthcheck udpping_checker with payload + IPv4 backends: NOT SUPPORT +* [x] tools/healthcheck http_checker + IPv6 backends +* [ ] tools/healthcheck tcp_checker with payload + IPv6 backends: NOT SUPPORT +* [ ] tools/healthcheck udp_checker with payload + IPv6 backends: NOT SUPPORT +* [ ] tools/healthcheck udpping_checker with payload + IPv6 backends: NOT SUPPORT +* [x] tools/ipvsadm "--proxy-protocol" config option +* [x] tools/keepalived "proxy-protocol" config keyword (v1|v2|disable) +* [ ] tools/dpvs-agent proxy-protocol service config api: NOT SUPPORT + +* [ ] client with PPv2 data + FNAT44 + TCP + PPv2 backends (lb cascading) +* [x] client with PPv1 data + FNAT44 + TCP + PPv1 backends (lb cascading) +* [ ] client with PPv2 data + FNAT44 + UDP + PPv2 backends (lb cascading) +* [ ] client with PPv2 data + FNAT44 + TCP + PPv1 backends (lb cascading) +* [x] client with PPv1 data + FNAT44 + TCP + PPv2 backends (lb cascading) + +* [ ] client with PPv2 data + FNAT66 + TCP + PPv2 backends (lb cascading) +* [ ] client with PPv1 data + FNAT66 + TCP + PPv1 backends (lb cascading) +* [ ] client with PPv2 data + FNAT66 + UDP + PPv2 backends (lb cascading) +* [ ] client with PPv2 data + FNAT66 + TCP + PPv1 backends (lb cascading) +* [ ] client with PPv1 data + FNAT66 + TCP + PPv2 backends (lb cascading) + +* [ ] client with PPv2 data + FNAT64 + TCP + PPv2 backends (lb cascading) +* [x] client with PPv1 data + FNAT64 + TCP + PPv1 backends (lb cascading) +* [ ] client with PPv2 data + FNAT64 + TCP + PPv1 backends (lb cascading) +* [x] client with PPv1 data + FNAT64 + TCP + PPv2 backends (lb cascading) + +* [ ] client with PPv2 data + FNAT44 + TCP + standalone PPv2 backends (lb cascading) +* [x] client with PPv1 data + FNAT44 + TCP + standalone PPv1 backends (lb cascading) +* [ ] client with PPv2 data + FNAT44 + UDP + standalone PPv2 backends (lb cascading) +* [ ] client with PPv2 data + FNAT44 + TCP + standalone PPv1 backends (lb cascading) +* [x] client with PPv1 data + FNAT44 + TCP + standalone PPv2 backends (lb cascading): zero-length duplicated ack may appear + +* [ ] client with PPv2 data + FNAT66 + TCP + standalone PPv2 backends (lb cascading) +* [ ] client with PPv1 data + FNAT66 + TCP + standalone PPv1 backends (lb cascading) +* [ ] client with PPv2 data + FNAT66 + UDP + standalone PPv2 backends (lb cascading) +* [ ] client with PPv2 data + FNAT66 + TCP + standalone PPv1 backends (lb cascading) +* [ ] client with PPv1 data + FNAT66 + TCP + standalone PPv2 backends (lb cascading) + +* [ ] client with PPv2 data + FNAT64 + TCP + standalone PPv2 backends (lb cascading) +* [x] client with PPv1 data + FNAT64 + TCP + standalone PPv1 backends (lb cascading) +* [ ] client with PPv2 data + FNAT64 + TCP + standalone PPv1 backends (lb cascading) +* [x] client with PPv1 data + FNAT64 + TCP + standalone PPv2 backends (lb cascading): zero-length duplicated ack may appear + diff --git a/test/proxy_protocol/nginx/nginx.conf b/test/proxy_protocol/nginx/nginx.conf index b052fcb60..8ac183efc 100644 --- a/test/proxy_protocol/nginx/nginx.conf +++ b/test/proxy_protocol/nginx/nginx.conf @@ -30,7 +30,7 @@ stream { error_log /data/nginx/logs/proxy-error.log; access_log /data/nginx/logs/proxy-access.log main buffer=32k flush=5s; - proxy_pass 127.0.0.1:8002; + proxy_pass localhost:8002; proxy_protocol on; #proxy_protocol_version 2; # Client supports proxy protocol v1 only for open sourced nginx. } @@ -61,6 +61,7 @@ http { listen 8002 proxy_protocol; # Server supoorts both proxy protocol v1 and v2. # V2 requires nginx version >= 1.13.11, refer to # "http://nginx.org/en/CHANGES" for more details. + listen [::]:8002 proxy_protocol; error_log /data/nginx/logs/backend-error.log; access_log /data/nginx/logs/backend-access.log backend buffer=32k flush=5s; diff --git a/tools/healthcheck/pkg/helthcheck/http_checker_test.go b/tools/healthcheck/pkg/helthcheck/http_checker_test.go index dcf9412ad..0fbbff3b4 100644 --- a/tools/healthcheck/pkg/helthcheck/http_checker_test.go +++ b/tools/healthcheck/pkg/helthcheck/http_checker_test.go @@ -33,10 +33,12 @@ var http_targets = []Target{ {net.ParseIP("2001::30"), 80, utils.IPProtoTCP}, {net.ParseIP("2001::30"), 443, utils.IPProtoTCP}, {net.ParseIP("192.168.88.30"), 8002, utils.IPProtoTCP}, // control group for proxy protocol + {net.ParseIP("2001::30"), 8002, utils.IPProtoTCP}, } var http_proxy_proto_targets = []Target{ {net.ParseIP("192.168.88.30"), 8002, utils.IPProtoTCP}, + {net.ParseIP("2001::30"), 8002, utils.IPProtoTCP}, } var http_url_targets = []string{ From bc95eedbdaa4a99facf9981062fc4f699a46cc94 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 17 Nov 2023 11:29:06 +0800 Subject: [PATCH 097/105] ipvs: fix issues in proxy protocol v2 parsing --- include/ipvs/proxy_proto.h | 1 + src/ipvs/ip_vs_proxy_proto.c | 34 +++++++++++++++++--------------- test/proxy_protocol/checklist.md | 8 ++++---- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/include/ipvs/proxy_proto.h b/include/ipvs/proxy_proto.h index 2cef07da2..cc9c865bf 100644 --- a/include/ipvs/proxy_proto.h +++ b/include/ipvs/proxy_proto.h @@ -32,6 +32,7 @@ #define PROXY_PROTO_V1_MAX_DATALEN 107 #define PROXY_PROTO_HDR_LEN_V4 28 #define PROXY_PROTO_HDR_LEN_V6 52 +#define PROXY_PROTO_HDR_LEN_UX 232 #define PROXY_PROTO_V2_SIGNATURE "\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A" #define PROXY_PROTO_V2_AF_MAX 4 diff --git a/src/ipvs/ip_vs_proxy_proto.c b/src/ipvs/ip_vs_proxy_proto.c index f0a4fbe0e..c4b515059 100644 --- a/src/ipvs/ip_vs_proxy_proto.c +++ b/src/ipvs/ip_vs_proxy_proto.c @@ -55,35 +55,37 @@ int proxy_proto_parse(struct rte_mbuf *mbuf, int ppdoff, struct proxy_info *ppin ppinfo->version = pphdrv2->ver; if (unlikely(ppinfo->version != PROXY_PROTOCOL_V2 || ppinfo->cmd > 1)) return EDPVS_INVAL; - ppinfo->datalen = offset; ppinfo->cmd = pphdrv2->cmd; if (!ppinfo->cmd) return EDPVS_OK; /* LOCAL command */ - ppinfo->af = ppv2_proto_pp2host(pphdrv2->af); + ppinfo->af = ppv2_af_pp2host(pphdrv2->af); if (unlikely(AF_UNSPEC == ppinfo->af)) return EDPVS_NOTSUPP; ppinfo->proto = ppv2_proto_pp2host(pphdrv2->proto); - if (unlikely(0 != ppinfo->proto)) + if (unlikely(!ppinfo->proto)) return EDPVS_NOTSUPP; switch (ppinfo->af) { case AF_INET: addr4 = (struct proxy_addr_ipv4 *)(pphdrv2 + 1); - ppinfo->addr.ip4.src_addr = ntohl(addr4->src_addr); - ppinfo->addr.ip4.dst_addr = ntohl(addr4->dst_addr); - ppinfo->addr.ip4.src_port = ntohs(addr4->src_port); - ppinfo->addr.ip4.dst_port = ntohs(addr4->dst_port); + ppinfo->addr.ip4.src_addr = addr4->src_addr; + ppinfo->addr.ip4.dst_addr = addr4->dst_addr; + ppinfo->addr.ip4.src_port = addr4->src_port; + ppinfo->addr.ip4.dst_port = addr4->dst_port; + ppinfo->datalen = PROXY_PROTO_HDR_LEN_V4; break; case AF_INET6: addr6 = (struct proxy_addr_ipv6 *)(pphdrv2 + 1); memcpy(ppinfo->addr.ip6.src_addr, addr6->src_addr, 16); memcpy(ppinfo->addr.ip6.dst_addr, addr6->dst_addr, 16); - ppinfo->addr.ip6.src_port = ntohs(addr6->src_port); - ppinfo->addr.ip6.dst_port = ntohs(addr6->dst_port); + ppinfo->addr.ip6.src_port = addr6->src_port; + ppinfo->addr.ip6.dst_port = addr6->dst_port; + ppinfo->datalen = PROXY_PROTO_HDR_LEN_V6; break; case AF_UNIX: addrunx = (struct proxy_addr_unix *)(pphdrv2 + 1); memcpy(ppinfo->addr.unx.src_addr, addrunx->src_addr, 108); memcpy(ppinfo->addr.unx.dst_addr, addrunx->dst_addr, 108); + ppinfo->datalen = PROXY_PROTO_HDR_LEN_UX; break; default: return EDPVS_NOTSUPP; @@ -121,12 +123,12 @@ int proxy_proto_parse(struct rte_mbuf *mbuf, int ppdoff, struct proxy_info *ppin return EDPVS_INVAL; if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* source port */ return EDPVS_INVAL; - ppinfo->addr.ip4.src_port = ntohs(strtol(token, &end, 10)); + ppinfo->addr.ip4.src_port = htons(strtol(token, &end, 10)); if (*end != '\0') return EDPVS_INVAL; if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* dest port */ return EDPVS_INVAL; - ppinfo->addr.ip4.dst_port = ntohs(strtol(token, &end, 10)); + ppinfo->addr.ip4.dst_port = htons(strtol(token, &end, 10)); if (*end != '\0') return EDPVS_INVAL; if (NULL != strtok_r(NULL, " ", &tmp)) @@ -147,12 +149,12 @@ int proxy_proto_parse(struct rte_mbuf *mbuf, int ppdoff, struct proxy_info *ppin return EDPVS_INVAL; if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* source port */ return EDPVS_INVAL; - ppinfo->addr.ip6.src_port = ntohs(strtol(token, &end, 10)); + ppinfo->addr.ip6.src_port = htons(strtol(token, &end, 10)); if (*end != '\0') return EDPVS_INVAL; if (NULL == (token = strtok_r(NULL, " ", &tmp))) /* dest port */ return EDPVS_INVAL; - ppinfo->addr.ip6.dst_port = ntohs(strtol(token, &end, 10)); + ppinfo->addr.ip6.dst_port = htons(strtol(token, &end, 10)); if (*end != '\0') return EDPVS_INVAL; if (NULL != strtok_r(NULL, " ", &tmp)) @@ -404,7 +406,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, else ((struct rte_ipv6_hdr *)oiph)->payload_len = htons(ntohs(((struct rte_ipv6_hdr *) oiph)->payload_len) - ppinfo->datalen); - memmove(oiph + ppinfo->datalen, oiph, ppinfo->datalen); + memmove(oiph + ppinfo->datalen, oiph, ppdoff); if (hdr_shift) *hdr_shift = ppinfo->datalen; rte_pktmbuf_adj(ombuf, ppinfo->datalen); @@ -482,7 +484,7 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, tbuf2, sizeof(tbuf2)))) return EDPVS_INVAL; sprintf(ppv1buf, "PROXY TCP4 %s %s %d %d\r\n", tbuf1, tbuf2, - htons(ppinfo->addr.ip4.src_port), htons(ppinfo->addr.ip4.dst_port)); + ntohs(ppinfo->addr.ip4.src_port), ntohs(ppinfo->addr.ip4.dst_port)); break; case AF_INET6: if (unlikely(NULL == inet_ntop(AF_INET6, ppinfo->addr.ip6.src_addr, @@ -492,7 +494,7 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, tbuf2, sizeof(tbuf2)))) return EDPVS_INVAL; sprintf(ppv1buf, "PROXY TCP6 %s %s %d %d\r\n", tbuf1, tbuf2, - htons(ppinfo->addr.ip6.src_port), htons(ppinfo->addr.ip6.dst_port)); + ntohs(ppinfo->addr.ip6.src_port), ntohs(ppinfo->addr.ip6.dst_port)); break; default: return EDPVS_NOTSUPP; diff --git a/test/proxy_protocol/checklist.md b/test/proxy_protocol/checklist.md index 3511aae83..63c9babf0 100644 --- a/test/proxy_protocol/checklist.md +++ b/test/proxy_protocol/checklist.md @@ -61,10 +61,10 @@ Checklist * [x] client with PPv1 data + FNAT44 + TCP + PPv2 backends (lb cascading) * [ ] client with PPv2 data + FNAT66 + TCP + PPv2 backends (lb cascading) -* [ ] client with PPv1 data + FNAT66 + TCP + PPv1 backends (lb cascading) +* [x] client with PPv1 data + FNAT66 + TCP + PPv1 backends (lb cascading) * [ ] client with PPv2 data + FNAT66 + UDP + PPv2 backends (lb cascading) * [ ] client with PPv2 data + FNAT66 + TCP + PPv1 backends (lb cascading) -* [ ] client with PPv1 data + FNAT66 + TCP + PPv2 backends (lb cascading) +* [x] client with PPv1 data + FNAT66 + TCP + PPv2 backends (lb cascading) * [ ] client with PPv2 data + FNAT64 + TCP + PPv2 backends (lb cascading) * [x] client with PPv1 data + FNAT64 + TCP + PPv1 backends (lb cascading) @@ -78,10 +78,10 @@ Checklist * [x] client with PPv1 data + FNAT44 + TCP + standalone PPv2 backends (lb cascading): zero-length duplicated ack may appear * [ ] client with PPv2 data + FNAT66 + TCP + standalone PPv2 backends (lb cascading) -* [ ] client with PPv1 data + FNAT66 + TCP + standalone PPv1 backends (lb cascading) +* [x] client with PPv1 data + FNAT66 + TCP + standalone PPv1 backends (lb cascading) * [ ] client with PPv2 data + FNAT66 + UDP + standalone PPv2 backends (lb cascading) * [ ] client with PPv2 data + FNAT66 + TCP + standalone PPv1 backends (lb cascading) -* [ ] client with PPv1 data + FNAT66 + TCP + standalone PPv2 backends (lb cascading) +* [x] client with PPv1 data + FNAT66 + TCP + standalone PPv2 backends (lb cascading): zero-length duplicated ack may appear * [ ] client with PPv2 data + FNAT64 + TCP + standalone PPv2 backends (lb cascading) * [x] client with PPv1 data + FNAT64 + TCP + standalone PPv1 backends (lb cascading) From 679e076f6b23440451e2e50ba0c249bde54e65bd Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 17 Nov 2023 11:29:36 +0800 Subject: [PATCH 098/105] test: update checklist for proxy protocol --- test/proxy_protocol/checklist.md | 34 +++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/test/proxy_protocol/checklist.md b/test/proxy_protocol/checklist.md index 63c9babf0..d1881c00b 100644 --- a/test/proxy_protocol/checklist.md +++ b/test/proxy_protocol/checklist.md @@ -54,37 +54,39 @@ Checklist * [x] tools/keepalived "proxy-protocol" config keyword (v1|v2|disable) * [ ] tools/dpvs-agent proxy-protocol service config api: NOT SUPPORT -* [ ] client with PPv2 data + FNAT44 + TCP + PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT44 + TCP + PPv2 backends (lb cascading) * [x] client with PPv1 data + FNAT44 + TCP + PPv1 backends (lb cascading) -* [ ] client with PPv2 data + FNAT44 + UDP + PPv2 backends (lb cascading) -* [ ] client with PPv2 data + FNAT44 + TCP + PPv1 backends (lb cascading) +* [x] client with PPv2 data + FNAT44 + UDP + PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT44 + TCP + PPv1 backends (lb cascading) * [x] client with PPv1 data + FNAT44 + TCP + PPv2 backends (lb cascading) -* [ ] client with PPv2 data + FNAT66 + TCP + PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT66 + TCP + PPv2 backends (lb cascading) * [x] client with PPv1 data + FNAT66 + TCP + PPv1 backends (lb cascading) -* [ ] client with PPv2 data + FNAT66 + UDP + PPv2 backends (lb cascading) -* [ ] client with PPv2 data + FNAT66 + TCP + PPv1 backends (lb cascading) +* [x] client with PPv2 data + FNAT66 + UDP + PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT66 + TCP + PPv1 backends (lb cascading) * [x] client with PPv1 data + FNAT66 + TCP + PPv2 backends (lb cascading) -* [ ] client with PPv2 data + FNAT64 + TCP + PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT64 + TCP + PPv2 backends (lb cascading) * [x] client with PPv1 data + FNAT64 + TCP + PPv1 backends (lb cascading) -* [ ] client with PPv2 data + FNAT64 + TCP + PPv1 backends (lb cascading) +* [x] client with PPv2 data + FNAT64 + UDP + PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT64 + TCP + PPv1 backends (lb cascading) * [x] client with PPv1 data + FNAT64 + TCP + PPv2 backends (lb cascading) -* [ ] client with PPv2 data + FNAT44 + TCP + standalone PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT44 + TCP + standalone PPv2 backends (lb cascading) * [x] client with PPv1 data + FNAT44 + TCP + standalone PPv1 backends (lb cascading) -* [ ] client with PPv2 data + FNAT44 + UDP + standalone PPv2 backends (lb cascading) -* [ ] client with PPv2 data + FNAT44 + TCP + standalone PPv1 backends (lb cascading) +* [x] client with PPv2 data + FNAT44 + UDP + standalone PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT44 + TCP + standalone PPv1 backends (lb cascading) * [x] client with PPv1 data + FNAT44 + TCP + standalone PPv2 backends (lb cascading): zero-length duplicated ack may appear -* [ ] client with PPv2 data + FNAT66 + TCP + standalone PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT66 + TCP + standalone PPv2 backends (lb cascading) * [x] client with PPv1 data + FNAT66 + TCP + standalone PPv1 backends (lb cascading) -* [ ] client with PPv2 data + FNAT66 + UDP + standalone PPv2 backends (lb cascading) -* [ ] client with PPv2 data + FNAT66 + TCP + standalone PPv1 backends (lb cascading) +* [x] client with PPv2 data + FNAT66 + UDP + standalone PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT66 + TCP + standalone PPv1 backends (lb cascading) * [x] client with PPv1 data + FNAT66 + TCP + standalone PPv2 backends (lb cascading): zero-length duplicated ack may appear -* [ ] client with PPv2 data + FNAT64 + TCP + standalone PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT64 + TCP + standalone PPv2 backends (lb cascading) * [x] client with PPv1 data + FNAT64 + TCP + standalone PPv1 backends (lb cascading) -* [ ] client with PPv2 data + FNAT64 + TCP + standalone PPv1 backends (lb cascading) +* [x] client with PPv2 data + FNAT64 + UDP + standalone PPv2 backends (lb cascading) +* [x] client with PPv2 data + FNAT64 + TCP + standalone PPv1 backends (lb cascading) * [x] client with PPv1 data + FNAT64 + TCP + standalone PPv2 backends (lb cascading): zero-length duplicated ack may appear From af55bca4976190cc98d36bbb3f0e0803cf4f3426 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 17 Nov 2023 18:45:07 +0800 Subject: [PATCH 099/105] tools: add more supports for proxy protocol Signed-off-by: ywc689 --- test/proxy_protocol/checklist.md | 12 ++++---- test/proxy_protocol/proxy_protocol.c | 6 ++-- tools/healthcheck/pkg/helthcheck/checker.go | 8 +++++ .../pkg/helthcheck/http_checker.go | 10 +------ tools/healthcheck/pkg/helthcheck/server.go | 10 +++---- .../healthcheck/pkg/helthcheck/tcp_checker.go | 29 ++++++++++++++++--- .../healthcheck/pkg/helthcheck/udp_checker.go | 22 +++++++++++--- .../pkg/helthcheck/udp_ping_checker.go | 8 +++-- .../pkg/helthcheck/udp_ping_checker_test.go | 2 +- 9 files changed, 72 insertions(+), 35 deletions(-) diff --git a/test/proxy_protocol/checklist.md b/test/proxy_protocol/checklist.md index d1881c00b..02e8f68af 100644 --- a/test/proxy_protocol/checklist.md +++ b/test/proxy_protocol/checklist.md @@ -43,13 +43,13 @@ Checklist * [x] tools/keepalived HTTP_CHECKER + IPv6 backends * [x] tools/eepalived UDP_CHECKER with payload + IPv6 backends * [x] tools/healthcheck http_checker + IPv4 backends -* [ ] tools/healthcheck tcp_checker with payload + IPv4 backends: NOT SUPPORT -* [ ] tools/healthcheck udp_checker with payload + IPv4 backends: NOT SUPPORT -* [ ] tools/healthcheck udpping_checker with payload + IPv4 backends: NOT SUPPORT +* [x] tools/healthcheck tcp_checker with payload + IPv4 backends +* [x] tools/healthcheck udp_checker with payload + IPv4 backends +* [x] tools/healthcheck udpping_checker with payload + IPv4 backends * [x] tools/healthcheck http_checker + IPv6 backends -* [ ] tools/healthcheck tcp_checker with payload + IPv6 backends: NOT SUPPORT -* [ ] tools/healthcheck udp_checker with payload + IPv6 backends: NOT SUPPORT -* [ ] tools/healthcheck udpping_checker with payload + IPv6 backends: NOT SUPPORT +* [x] tools/healthcheck tcp_checker with payload + IPv6 backends +* [x] tools/healthcheck udp_checker with payload + IPv6 backends +* [x] tools/healthcheck udpping_checker with payload + IPv6 backends * [x] tools/ipvsadm "--proxy-protocol" config option * [x] tools/keepalived "proxy-protocol" config keyword (v1|v2|disable) * [ ] tools/dpvs-agent proxy-protocol service config api: NOT SUPPORT diff --git a/test/proxy_protocol/proxy_protocol.c b/test/proxy_protocol/proxy_protocol.c index 543a7c1b3..c31445afe 100644 --- a/test/proxy_protocol/proxy_protocol.c +++ b/test/proxy_protocol/proxy_protocol.c @@ -67,7 +67,7 @@ int parse_proxy_protocol(char *buf, int len) { if (NULL == (token = strtok_r((char *)ppv1data, " ", &tmp))) // "PROXY" return len; - if (NULL == (token = strtok_r(NULL, " ", &tmp))) // "TCP4|TCP6" + if (NULL == (token = strtok_r(NULL, " ", &tmp))) // "TCP4|TCP6|UNKNOWN" return len; if (memcmp(token, "TCP4", 4) == 0) { ((struct sockaddr_in *)&from)->sin_family = AF_INET; @@ -119,8 +119,8 @@ int parse_proxy_protocol(char *buf, int len) { goto done; } else if (memcmp(token, "UNKNOWN", 7) == 0) { // LOCAL command if (NULL != strtok_r(NULL, " ", &tmp)) - goto done; - return len; + return len; + goto done; } else { // unsupported protocol // UDP4, UDP6 are not supported in v1 return len; diff --git a/tools/healthcheck/pkg/helthcheck/checker.go b/tools/healthcheck/pkg/helthcheck/checker.go index 52b2357a4..745924b7b 100644 --- a/tools/healthcheck/pkg/helthcheck/checker.go +++ b/tools/healthcheck/pkg/helthcheck/checker.go @@ -26,6 +26,14 @@ import ( const uweightDefault uint16 = 1 +var ( + proxyProtoV1LocalCmd = "PROXY UNKNOWN\r\n" + proxyProtoV2LocalCmd []byte = []byte{ + 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, + 0x55, 0x49, 0x54, 0x0A, 0x20, 0x00, 0x00, 0x00, + } +) + // Checks provides a map of healthcheck configurations. type Checkers struct { Configs map[Id]*CheckerConfig diff --git a/tools/healthcheck/pkg/helthcheck/http_checker.go b/tools/healthcheck/pkg/helthcheck/http_checker.go index 8343fdea0..97b7d5102 100644 --- a/tools/healthcheck/pkg/helthcheck/http_checker.go +++ b/tools/healthcheck/pkg/helthcheck/http_checker.go @@ -33,14 +33,6 @@ import ( var _ CheckMethod = (*HttpChecker)(nil) -var ( - proxyProtoV1LocalCmd = "PROXY UNKNOWN\r\n" - proxyProtoV2LocalCmd []byte = []byte{ - 0x0D, 0x0A, 0x0D, 0x0A, 0x00, 0x0D, 0x0A, 0x51, - 0x55, 0x49, 0x54, 0x0A, 0x20, 0x00, 0x00, 0x00, - } -) - type HttpCodeRange struct { start int // inclusive end int // inclusive @@ -155,7 +147,7 @@ func (hc *HttpChecker) Check(target Target, timeout time.Duration) *Result { // https://pkg.go.dev/github.com/pires/go-proxyproto if hc.ProxyProto == 2 { n, err := bytes.NewReader(proxyProtoV2LocalCmd).WriteTo(conn) - if err != nil || n < 16 { + if err != nil || n < int64(len(proxyProtoV2LocalCmd)) { return nil, err } } else if hc.ProxyProto == 1 { diff --git a/tools/healthcheck/pkg/helthcheck/server.go b/tools/healthcheck/pkg/helthcheck/server.go index 9e5712570..d7af16f08 100644 --- a/tools/healthcheck/pkg/helthcheck/server.go +++ b/tools/healthcheck/pkg/helthcheck/server.go @@ -73,20 +73,20 @@ func (s *Server) NewChecker(typ lb.Checker, proto utils.IPProto) CheckMethod { var checker CheckMethod switch typ { case lb.CheckerTCP: - checker = NewTCPChecker("", "") + checker = NewTCPChecker("", "", 0) case lb.CheckerUDP: - checker = NewUDPChecker("", "") + checker = NewUDPChecker("", "", 0) case lb.CheckerPING: checker = NewPingChecker() case lb.CheckerUDPPing: - checker = NewUDPPingChecker("", "") + checker = NewUDPPingChecker("", "", 0) case lb.CheckerNone: if s.config.LbAutoMethod { switch proto { case utils.IPProtoTCP: - checker = NewTCPChecker("", "") + checker = NewTCPChecker("", "", 0) case utils.IPProtoUDP: - checker = NewUDPPingChecker("", "") + checker = NewUDPPingChecker("", "", 0) } } } diff --git a/tools/healthcheck/pkg/helthcheck/tcp_checker.go b/tools/healthcheck/pkg/helthcheck/tcp_checker.go index 5b6026cc0..7e58c824f 100644 --- a/tools/healthcheck/pkg/helthcheck/tcp_checker.go +++ b/tools/healthcheck/pkg/helthcheck/tcp_checker.go @@ -18,9 +18,11 @@ package hc import ( + "bytes" "fmt" "io" "net" + "strings" "time" ) @@ -30,13 +32,18 @@ var _ CheckMethod = (*TCPChecker)(nil) type TCPChecker struct { Config *CheckerConfig - Receive string - Send string + Receive string + Send string + ProxyProto int // proxy protocol: 0 - close, 1 - version 1, 2 - version 2 } // NewTCPChecker returns an initialised TCPChecker. -func NewTCPChecker(recv, send string) *TCPChecker { - return &TCPChecker{Receive: recv, Send: send} +func NewTCPChecker(recv, send string, proxyProto int) *TCPChecker { + return &TCPChecker{ + Receive: recv, + Send: send, + ProxyProto: proxyProto, + } } func (hc *TCPChecker) BindConfig(conf *CheckerConfig) { @@ -84,6 +91,20 @@ func (hc *TCPChecker) Check(target Target, timeout time.Duration) *Result { return NewResult(start, msg, false, err) } + if 2 == hc.ProxyProto { + n, err := bytes.NewReader(proxyProtoV2LocalCmd).WriteTo(tcpConn) + if err != nil || n < int64(len(proxyProtoV2LocalCmd)) { + msg = fmt.Sprintf("%s: failed to send proxy protocol v2 data", msg) + return NewResult(start, msg, false, err) + } + } else if 1 == hc.ProxyProto { + n, err := strings.NewReader(proxyProtoV1LocalCmd).WriteTo(tcpConn) + if err != nil || n < int64(len(proxyProtoV1LocalCmd)) { + msg = fmt.Sprintf("%s: failed to send proxy protocol v1 data", msg) + return NewResult(start, msg, false, err) + } + } + if hc.Send != "" { err = writeFull(tcpConn, []byte(hc.Send)) if err != nil { diff --git a/tools/healthcheck/pkg/helthcheck/udp_checker.go b/tools/healthcheck/pkg/helthcheck/udp_checker.go index 4cf385da6..89e4f4b3b 100644 --- a/tools/healthcheck/pkg/helthcheck/udp_checker.go +++ b/tools/healthcheck/pkg/helthcheck/udp_checker.go @@ -18,6 +18,7 @@ package hc import ( + "bytes" "fmt" "net" "time" @@ -29,13 +30,18 @@ var _ CheckMethod = (*UDPChecker)(nil) type UDPChecker struct { Config *CheckerConfig - Receive string - Send string + Receive string + Send string + ProxyProto int // proxy protocol: 0 - close, 2 - version 2 } // NewUDPChecker returns an initialised UDPChecker. -func NewUDPChecker(recv, send string) *UDPChecker { - return &UDPChecker{Receive: recv, Send: send} +func NewUDPChecker(recv, send string, proxyProto int) *UDPChecker { + return &UDPChecker{ + Receive: recv, + Send: send, + ProxyProto: proxyProto, + } } func (hc *UDPChecker) BindConfig(conf *CheckerConfig) { @@ -76,6 +82,14 @@ func (hc *UDPChecker) Check(target Target, timeout time.Duration) *Result { return NewResult(start, msg, false, err) } + if 2 == hc.ProxyProto { + n, err := bytes.NewReader(proxyProtoV2LocalCmd).WriteTo(udpConn) + if err != nil || n < int64(len(proxyProtoV2LocalCmd)) { + msg = fmt.Sprintf("%s: failed to send proxy protocol v2 data", msg) + return NewResult(start, msg, false, err) + } + } + if _, err = udpConn.Write([]byte(hc.Send)); err != nil { msg = fmt.Sprintf("%s: failed to send request", msg) return NewResult(start, msg, false, err) diff --git a/tools/healthcheck/pkg/helthcheck/udp_ping_checker.go b/tools/healthcheck/pkg/helthcheck/udp_ping_checker.go index 6fbcee13d..a5af68c0b 100644 --- a/tools/healthcheck/pkg/helthcheck/udp_ping_checker.go +++ b/tools/healthcheck/pkg/helthcheck/udp_ping_checker.go @@ -33,9 +33,11 @@ type UDPPingChecker struct { } // NewUDPPingChecker returns an initialised UDPPingChecker. -func NewUDPPingChecker(recv, send string) *UDPPingChecker { - return &UDPPingChecker{UDPChecker: NewUDPChecker(recv, send), - PingChecker: NewPingChecker()} +func NewUDPPingChecker(recv, send string, proxyProto int) *UDPPingChecker { + return &UDPPingChecker{ + UDPChecker: NewUDPChecker(recv, send, proxyProto), + PingChecker: NewPingChecker(), + } } func (hc *UDPPingChecker) BindConfig(conf *CheckerConfig) { diff --git a/tools/healthcheck/pkg/helthcheck/udp_ping_checker_test.go b/tools/healthcheck/pkg/helthcheck/udp_ping_checker_test.go index f20e69ac7..321035336 100644 --- a/tools/healthcheck/pkg/helthcheck/udp_ping_checker_test.go +++ b/tools/healthcheck/pkg/helthcheck/udp_ping_checker_test.go @@ -37,7 +37,7 @@ var udpping_targets = []Target{ func TestUDPPingChecker(t *testing.T) { for _, target := range udpping_targets { - checker := NewUDPPingChecker("", "") + checker := NewUDPPingChecker("", "", 0) id := Id(target.String()) config := NewCheckerConfig(&id, checker, &target, StateUnknown, 0, From 2b6e4576c83eb15e0d943b58fd960150fafc8fe9 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 20 Nov 2023 15:46:16 +0800 Subject: [PATCH 100/105] tools: dpvs-agent supports proxy protocol config Signed-off-by: ywc689 --- tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go | 2 + tools/dpvs-agent/dpvs-agent-api.yaml | 11 +++- .../models/virtual_server_spec_expand.go | 5 +- .../models/virtual_server_spec_tiny.go | 53 +++++++++++++++++++ .../dpvs-agent/pkg/ipc/types/virtualserver.go | 19 +++++-- tools/dpvs-agent/restapi/embedded_spec.go | 28 +++++++++- 6 files changed, 110 insertions(+), 8 deletions(-) diff --git a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go index 1ba7a08e3..e96b4c697 100644 --- a/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go +++ b/tools/dpvs-agent/cmd/ipvs/put_vs_vip_port.go @@ -72,6 +72,8 @@ func (h *putVsItem) Handle(params apiVs.PutVsVipPortParams) middleware.Responder if params.Spec.SynProxy != nil && *params.Spec.SynProxy { vs.SetFlagsSynProxy() } + + vs.SetProxyProto(params.Spec.ProxyProtocol) } vs.SetSchedName(schedName) diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml index 9d9f3a91e..af3886458 100644 --- a/tools/dpvs-agent/dpvs-agent-api.yaml +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -488,7 +488,10 @@ definitions: format: "uint32" Proto: type: "integer" - format: "uint16" + format: "uint8" + ProxyProto: + type: "integer" + format: "uint8" Port: type: "integer" format: "uint16" @@ -579,6 +582,12 @@ definitions: format: "uint32" #Addr: # type: "string" + ProxyProtocol: + type: "string" + enum: + - v2 + - v1 + - disable SchedName: type: "string" enum: diff --git a/tools/dpvs-agent/models/virtual_server_spec_expand.go b/tools/dpvs-agent/models/virtual_server_spec_expand.go index 88525c785..da101eb6c 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_expand.go +++ b/tools/dpvs-agent/models/virtual_server_spec_expand.go @@ -59,7 +59,10 @@ type VirtualServerSpecExpand struct { Port uint16 `json:"Port,omitempty"` // proto - Proto uint16 `json:"Proto,omitempty"` + Proto uint8 `json:"Proto,omitempty"` + + // proxy proto + ProxyProto uint8 `json:"ProxyProto,omitempty"` // r ss RSs *RealServerExpandList `json:"RSs,omitempty"` diff --git a/tools/dpvs-agent/models/virtual_server_spec_tiny.go b/tools/dpvs-agent/models/virtual_server_spec_tiny.go index 837040a94..490e578ce 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_tiny.go +++ b/tools/dpvs-agent/models/virtual_server_spec_tiny.go @@ -38,6 +38,10 @@ type VirtualServerSpecTiny struct { // match Match *MatchSpec `json:"Match,omitempty"` + // proxy protocol + // Enum: [v2 v1 disable] + ProxyProtocol string `json:"ProxyProtocol,omitempty"` + // sched name // Enum: [rr wrr wlc conhash] SchedName string `json:"SchedName,omitempty"` @@ -57,6 +61,10 @@ func (m *VirtualServerSpecTiny) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateProxyProtocol(formats); err != nil { + res = append(res, err) + } + if err := m.validateSchedName(formats); err != nil { res = append(res, err) } @@ -86,6 +94,51 @@ func (m *VirtualServerSpecTiny) validateMatch(formats strfmt.Registry) error { return nil } +var virtualServerSpecTinyTypeProxyProtocolPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["v2","v1","disable"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecTinyTypeProxyProtocolPropEnum = append(virtualServerSpecTinyTypeProxyProtocolPropEnum, v) + } +} + +const ( + + // VirtualServerSpecTinyProxyProtocolV2 captures enum value "v2" + VirtualServerSpecTinyProxyProtocolV2 string = "v2" + + // VirtualServerSpecTinyProxyProtocolV1 captures enum value "v1" + VirtualServerSpecTinyProxyProtocolV1 string = "v1" + + // VirtualServerSpecTinyProxyProtocolDisable captures enum value "disable" + VirtualServerSpecTinyProxyProtocolDisable string = "disable" +) + +// prop value enum +func (m *VirtualServerSpecTiny) validateProxyProtocolEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecTinyTypeProxyProtocolPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecTiny) validateProxyProtocol(formats strfmt.Registry) error { + if swag.IsZero(m.ProxyProtocol) { // not required + return nil + } + + // value enum + if err := m.validateProxyProtocolEnum("ProxyProtocol", "body", m.ProxyProtocol); err != nil { + return err + } + + return nil +} + var virtualServerSpecTinyTypeSchedNamePropEnum []interface{} func init() { diff --git a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go index f2a397fec..740c32d13 100644 --- a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go @@ -118,7 +118,8 @@ type dpvsDestCheck struct { type VirtualServerSpec struct { af uint32 - proto uint16 + proto uint8 + proxyProto uint8 port uint16 fwmark uint32 flags uint32 @@ -146,7 +147,7 @@ func (vs *VirtualServerSpec) Convert2NewRsFront() *RealServerFront { front.af = vs.af front.port = vs.port - front.proto = vs.proto + front.proto = uint16(vs.proto) front.fwmark = vs.fwmark front.numDests = vs.numDests front.cid = uint32(vs.cid) @@ -238,10 +239,20 @@ func (vs *VirtualServerSpec) GetAf() uint32 { return vs.af } -func (vs *VirtualServerSpec) SetProto(proto uint16) { +func (vs *VirtualServerSpec) SetProto(proto uint8) { vs.proto = proto } +func (vs *VirtualServerSpec) SetProxyProto(version string) { + if version == models.VirtualServerSpecTinyProxyProtocolV2 { + vs.proxyProto = 2 + } else if version == models.VirtualServerSpecTinyProxyProtocolV1 { + vs.proxyProto = 1 + } else { + vs.proxyProto = 0 + } +} + func (vs *VirtualServerSpec) SetPort(port uint16) { buf := new(bytes.Buffer) binary.Write(buf, binary.LittleEndian, uint16(port)) @@ -254,7 +265,7 @@ func (vs *VirtualServerSpec) GetPort() uint16 { return binary.BigEndian.Uint16(buf.Bytes()) } -func (vs *VirtualServerSpec) GetProto() uint16 { +func (vs *VirtualServerSpec) GetProto() uint8 { return vs.proto } diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go index f1052021b..2a57e3c85 100644 --- a/tools/dpvs-agent/restapi/embedded_spec.go +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -1848,7 +1848,11 @@ func init() { }, "Proto": { "type": "integer", - "format": "uint16" + "format": "uint8" + }, + "ProxyProto": { + "type": "integer", + "format": "uint8" }, "RSs": { "$ref": "#/definitions/RealServerExpandList" @@ -1904,6 +1908,14 @@ func init() { "Match": { "$ref": "#/definitions/MatchSpec" }, + "ProxyProtocol": { + "type": "string", + "enum": [ + "v2", + "v1", + "disable" + ] + }, "SchedName": { "type": "string", "enum": [ @@ -4189,7 +4201,11 @@ func init() { }, "Proto": { "type": "integer", - "format": "uint16" + "format": "uint8" + }, + "ProxyProto": { + "type": "integer", + "format": "uint8" }, "RSs": { "$ref": "#/definitions/RealServerExpandList" @@ -4245,6 +4261,14 @@ func init() { "Match": { "$ref": "#/definitions/MatchSpec" }, + "ProxyProtocol": { + "type": "string", + "enum": [ + "v2", + "v1", + "disable" + ] + }, "SchedName": { "type": "string", "enum": [ From 109a491caab04d801b4aa1e60f0ca9d4a24a9df7 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 21 Nov 2023 11:02:08 +0800 Subject: [PATCH 101/105] doc: add doc client-address-conservation-in-fullnat.md Signed-off-by: ywc689 --- doc/client-address-conservation-in-fullnat.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 doc/client-address-conservation-in-fullnat.md diff --git a/doc/client-address-conservation-in-fullnat.md b/doc/client-address-conservation-in-fullnat.md new file mode 100644 index 000000000..f552b5c6d --- /dev/null +++ b/doc/client-address-conservation-in-fullnat.md @@ -0,0 +1,47 @@ +Client Address Conservation in Fullnat +--- + +The original client addresses are substituted by DPVS's local addresses in Fullnat forwarding mode so that auxiliary means is required to pass them to realservers. Three solutions are provided in DPVS to solve the problem -- toa, uoa, and proxy protocol, with each having its own pros and cons. The doc will elaborate on them. + +* **TOA** + +Client address is encapsulated in a private TCP option (opcode 254) by DPVS, and parsed into the connected TCP socket on realserver by a kernel module named [toa.ko](../kmod/toa/). By default, it requires no changes in realserver application programs for fnat44, fnat66. But an extra syscall to `getsockopt` with parameters `IPPROTO_IP` and `TOA_SO_GET_LOOKUP` is required for fnat64 to retrieve the original IPv6 client address from toa. + +* **UOA** + +UOA is the counterpart in UDP protocol. It supports two mode: IP option mode (ipo) and Private Protocol mode (opp). Client address is encapsulated into a private IPv4 option (opcode 31) in ipo mode, and into a private layer4 protocol named "option protocol" (protocol number 248) in opp mode respectively. Similarly, a kernel module name [uoa.ko](../kmod/uoa/) is required to parse the original client address from raw packets on realserver. Realserver application programs should use `getsockopt` with parameters `IPPROTO_IP` and `UOA_SO_GET_LOOKUP` immediately after user data reception to retrieve the original address from uoa. Note that not all kinds of network switches or routers support private IPv4 options or layer4 private protocols. Be aware of your network restrictions before using UOA. + +* **Proxy Protocol**: + +[Proxy Protocol](https://www.haproxy.org/download/2.9/doc/proxy-protocol.txt) is a widely-used protocol for client address conservation on reverse proxy. It's been drafted by haproxy.org and supported two versions up to now. The version 1 is a human-readable format and supports TCP only, while version 2 is a binary format supporting both TCP and UDP. DPVS implements both versions and users can choose which one to use on basis of a per-service configuration. Moreover, DPVS allows for clients that have already carried proxy protocol data, which is often the case when DPVS's virtual IP is used as the realserver for some other reverse proxy such as nginx, envoy, or another DPVS, where DPVS doesn't insert client address by itself, but just retains the client address encapsulated in the packet, and makes protocol version translation if necessary. Proxy protocol has advantages of broad and uniform supports for layer3 and layer4 protocols(including IP, IPv6, TCP, UDP), both source and destination address conveying, no dependency on kernel modules, tolerances of network infrastructure differences. The client addresses are encapsulated into the layer4 payload in the begginning position. Application programs on realservers must receive the data and parse it to obtain the original client addresses immediately on establishment of TCP/UDP connection. The client address data may be taken as application data by mistake if not processed, resulting in unexpected behavior in your application. Fortunately, parsing the client address from proxy protocol in application server is quite straightforward, and a variety of well-known proxy servers have supported it. Actually, proxy protocol is becoming a defato standard in this area. + +Next ,let's compare the three client address conservation solutions in detail in the following two tables. + +The first table below lists the forwarding modes (FNAT44/FNAT66/FNAT64) and L4 protocols (TCP/UDP) supported by different solutions. + +| | toa | uoa (ipo) | uoa (opp) | proxy protocol (v1) | proxy protocol (v2) | +| ------ | ---- | --------- | --------- | --------------------- | --------------------- | +| FNAT44 | √ | √ | √ | √ | √ | +| FNAT66 | √ | × | √ | √ | √ | +| FNAT64 | √ | × | √ | √ | √ | +| TCP | √ | × | × | √ | √ | +| UDP | × | √ | √ | × | √ | + +The second table details differences among toa, uoa and proxy protocol from aspects of functional features, configuraitons, application adaption and examples. + +| | toa | uoa (ipo mode) | uoa (opp mode) | proxy protocol (v1 & v2) | +| --------------------------------------- | ------------------------------------------------------------ | --------------------------------------- | --------------------------------------- | ---------------------------------------------------------- | +| configuration switch | always on | global, default off | global, default on | per-service, toa/uoa mutal exclusive | +| where client address resides | tcp option | ipv4 option | private ip protocol | tcp/udp beginnig payload | +| standardization | private standard | private implementation | private implementation | defacto standard | +| application intrusiveness | transparent | transparent (only fnat44 supported) | transparent when uoa.ko installed | intrusive | +| client address resolution intrusiveness | transparent for fnat44/fnat66; intrusive for fnat64 | intrusive | intrusive | intrusive | +| client source address resolution | support | support | support | support | +| client destination address resolution | not support | not support | not support | support | +| kernel module requirement on realserver | toa.ko, not compulsory when client addresses aren't concerned | uoa.ko | uoa.ko | no kernel module required | +| load balancer cascading | not support | not support | not support | support | +| retransmission | support | fixed times, default 3 | fixed times, default 3 | support for tcp, not support for udp | +| underlay network supports | good | bad | medium | good | +| client address loss cases | when no enough tcp option room in first ack seg | general udp packet loss | general udp packet loss | no loss for tcp, general udp packet loss for udp | +| well-known application supports | - | - | - | haproxy, nginx, envoy, ... | +| intrusive application server examples | [fnat64](../kmod/toa/example_nat64/server.c) | [udp_serv](../kmod/uoa/example/udp_serv.c) | [udp_serv](../kmod/uoa/example/udp_serv.c) | [tcp_server](../test/proxy_protocol/tcp_server.c), [udp_server](../test/proxy_protocol/udp_server.c), [official sample code](https://www.haproxy.org/download/2.9/doc/proxy-protocol.txt) | From 486ed1e00715ec4ce2e804407f40ef5d63795032 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Fri, 1 Dec 2023 19:04:58 +0800 Subject: [PATCH 102/105] ipvs: protect proxy protocol from source address spoofing attack Two versions -- v1-insecure and v2-insecure -- ared added for the proxy cascading case where the proxy protocol addresses should remain unchanged in the backend proxy server. Meanwhile, the v1 and v2 versions are always using the addresses from client's ip header of inbound packets. Signed-off-by: ywc689 --- doc/client-address-conservation-in-fullnat.md | 6 +-- include/conf/service.h | 31 ++++++++++--- src/ipvs/ip_vs_proto_tcp.c | 16 ++++--- src/ipvs/ip_vs_proto_udp.c | 15 ++++--- src/ipvs/ip_vs_proxy_proto.c | 13 +++--- tools/dpvs-agent/dpvs-agent-api.yaml | 14 ++++++ .../models/virtual_server_spec_expand.go | 45 ++++++++++++++++++- .../models/virtual_server_spec_tiny.go | 10 ++++- .../dpvs-agent/pkg/ipc/types/virtualserver.go | 11 +++-- tools/dpvs-agent/restapi/embedded_spec.go | 24 +++++++++- tools/ipvsadm/ipvsadm.c | 2 +- 11 files changed, 148 insertions(+), 39 deletions(-) diff --git a/doc/client-address-conservation-in-fullnat.md b/doc/client-address-conservation-in-fullnat.md index f552b5c6d..6ccc4b5b8 100644 --- a/doc/client-address-conservation-in-fullnat.md +++ b/doc/client-address-conservation-in-fullnat.md @@ -1,7 +1,7 @@ Client Address Conservation in Fullnat --- -The original client addresses are substituted by DPVS's local addresses in Fullnat forwarding mode so that auxiliary means is required to pass them to realservers. Three solutions are provided in DPVS to solve the problem -- toa, uoa, and proxy protocol, with each having its own pros and cons. The doc will elaborate on them. +The original client addresses are substituted with DPVS's local addresses in Fullnat forwarding mode so that auxiliary means is required to pass them to realservers. Three solutions have been developed in DPVS for the problem -- *TOA*, *UOA*, and *Proxy Protocol*, with each having its own pros and cons. The document is to elaborate on them. * **TOA** @@ -9,11 +9,11 @@ Client address is encapsulated in a private TCP option (opcode 254) by DPVS, and * **UOA** -UOA is the counterpart in UDP protocol. It supports two mode: IP option mode (ipo) and Private Protocol mode (opp). Client address is encapsulated into a private IPv4 option (opcode 31) in ipo mode, and into a private layer4 protocol named "option protocol" (protocol number 248) in opp mode respectively. Similarly, a kernel module name [uoa.ko](../kmod/uoa/) is required to parse the original client address from raw packets on realserver. Realserver application programs should use `getsockopt` with parameters `IPPROTO_IP` and `UOA_SO_GET_LOOKUP` immediately after user data reception to retrieve the original address from uoa. Note that not all kinds of network switches or routers support private IPv4 options or layer4 private protocols. Be aware of your network restrictions before using UOA. +UOA is the counterpart in UDP protocol. It supports two modes: *IP Option Mode* (ipo) and *Private Protocol Mode* (opp). Client address is encapsulated into a private IPv4 option (opcode 31) in ipo mode, and into a private layer4 protocol named "option protocol" (protocol number 248) in opp mode respectively. Similarly, a kernel module name [uoa.ko](../kmod/uoa/) is required to parse the original client address from raw packets on realserver. Realserver application programs should use `getsockopt` with parameters `IPPROTO_IP` and `UOA_SO_GET_LOOKUP` immediately after user data reception to retrieve the original address from uoa. Note that not all kinds of network switches or routers support private IPv4 options or layer4 private protocols. Be aware of your network restrictions before using UOA. * **Proxy Protocol**: -[Proxy Protocol](https://www.haproxy.org/download/2.9/doc/proxy-protocol.txt) is a widely-used protocol for client address conservation on reverse proxy. It's been drafted by haproxy.org and supported two versions up to now. The version 1 is a human-readable format and supports TCP only, while version 2 is a binary format supporting both TCP and UDP. DPVS implements both versions and users can choose which one to use on basis of a per-service configuration. Moreover, DPVS allows for clients that have already carried proxy protocol data, which is often the case when DPVS's virtual IP is used as the realserver for some other reverse proxy such as nginx, envoy, or another DPVS, where DPVS doesn't insert client address by itself, but just retains the client address encapsulated in the packet, and makes protocol version translation if necessary. Proxy protocol has advantages of broad and uniform supports for layer3 and layer4 protocols(including IP, IPv6, TCP, UDP), both source and destination address conveying, no dependency on kernel modules, tolerances of network infrastructure differences. The client addresses are encapsulated into the layer4 payload in the begginning position. Application programs on realservers must receive the data and parse it to obtain the original client addresses immediately on establishment of TCP/UDP connection. The client address data may be taken as application data by mistake if not processed, resulting in unexpected behavior in your application. Fortunately, parsing the client address from proxy protocol in application server is quite straightforward, and a variety of well-known proxy servers have supported it. Actually, proxy protocol is becoming a defato standard in this area. +[Proxy Protocol](https://www.haproxy.org/download/2.9/doc/proxy-protocol.txt) is a widely-used protocol for client address conservation on reverse proxies. It's been drafted by haproxy.org and supported two versions up to now. The version v1 is a human-readable format which supports TCP only, while version v2 is a binary format supporting both TCP and UDP. DPVS implements both versions and users can choose which one to use on basis of a per-service configuration. Moreover, if configured to the insecure mode, DPVS allows for clients that have already carried proxy protocol data, which is often the case when DPVS's virtual IP is behind of other reverse proxies such as nginx, envoy, or another DPVS, where DPVS doesn't insert client address by itself, but just retains the client address encapsulated in the packet, and makes protocol version translation if necessary. Proxy protocol has advantages of broad and uniform supports for layer3 and layer4 protocols(including IP, IPv6, TCP, UDP), both source and destination addresses conveying, no dependency on kernel modules, tolerance of network infrastructure differences. The client addresses are encapsulated into the very begginning position of layer4 payload. Application programs on realservers must receive the data and parse it to obtain the original client addresses immediately on establishment of TCP/UDP connection. Otherwise, the client address data may be taken as application data by mistake, resulting in unexpected behavior in the application program. Fortunately, parsing the client address from proxy protocol is quite straightforward, and a variety of well-known proxy servers have supported it. Actually, proxy protocol is becoming a defato standard in this area. Next ,let's compare the three client address conservation solutions in detail in the following two tables. diff --git a/include/conf/service.h b/include/conf/service.h index 401bf5f0a..d16164f3c 100644 --- a/include/conf/service.h +++ b/include/conf/service.h @@ -62,11 +62,24 @@ #define DEST_INHIBIT_DURATION_MIN 5 // 5s #define DEST_INHIBIT_DURATION_MAX 3600 // 1h +#define PROXY_PROTOCOL_VERSION_MASK 0x0F +#define PROXY_PROTOCOL_FLAGS_MASK 0xF0 + +#define PROXY_PROTOCOL_VERSION(verflag) ((verflag) & PROXY_PROTOCOL_VERSION_MASK) +#define PROXY_PROTOCOL_FLAGS(verflag) ((verflag) & PROXY_PROTOCOL_FLAGS_MASK) +#define PROXY_PROTOCOL_IS_INSECURE(verflag) (!!((verflag) & PROXY_PROTOCOL_F_INSECURE)) + enum { - PROXY_PROTOCOL_DISABLE = 0, - PROXY_PROTOCOL_V1, - PROXY_PROTOCOL_V2, - PROXY_PROTOCOL_MAX, + PROXY_PROTOCOL_DISABLE = 0x00, + PROXY_PROTOCOL_V1 = 0x01, + PROXY_PROTOCOL_V2 = 0x02, + PROXY_PROTOCOL_MAX = PROXY_PROTOCOL_VERSION_MASK, + + /* The proxy protocol addresses existing in the received mbuf are passed to backends + * in insecure mode, making the service subject to Source Address Spoofing Attack, + * but it's useful when multiple proxies exist before the backend. */ + PROXY_PROTOCOL_F_INSECURE = 0x10, + PROXY_PROTOCOL_F_MAX = PROXY_PROTOCOL_FLAGS_MASK, }; struct dest_check_configs { @@ -183,17 +196,21 @@ static inline uint8_t proxy_protocol_type(const char *str) { return PROXY_PROTOCOL_V1; if (!strcasecmp(str, "v2")) return PROXY_PROTOCOL_V2; + if (!strcasecmp(str, "v1-insecure")) + return PROXY_PROTOCOL_V1 | PROXY_PROTOCOL_F_INSECURE; + if (!strcasecmp(str, "v2-insecure")) + return PROXY_PROTOCOL_V2 | PROXY_PROTOCOL_F_INSECURE; return PROXY_PROTOCOL_DISABLE; } static inline const char *proxy_protocol_str(uint8_t type) { - switch (type) { + switch (PROXY_PROTOCOL_VERSION(type)) { case PROXY_PROTOCOL_DISABLE: return "disable"; case PROXY_PROTOCOL_V1: - return "v1"; + return PROXY_PROTOCOL_IS_INSECURE(type) ? "v1-insecure" : "v1"; case PROXY_PROTOCOL_V2: - return "v2"; + return PROXY_PROTOCOL_IS_INSECURE(type) ? "v2-insecure" : "v2"; } return "unknown"; } diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 1cb403442..75e5713a6 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -371,13 +371,15 @@ static int tcp_in_add_proxy_proto(struct dp_vs_conn *conn, struct rte_mbuf *mbuf if (unlikely(EDPVS_OK != proxy_proto_parse(mbuf, offset, &ppinfo))) return EDPVS_INVPKT; - if (ppinfo.datalen > 0 && ppinfo.version == conn->pp_version) + if (ppinfo.datalen > 0 + && ppinfo.version == PROXY_PROTOCOL_VERSION(conn->pp_version) + && PROXY_PROTOCOL_IS_INSECURE(conn->pp_version)) return EDPVS_OK; // keep intact the orginal proxy protocol data - if (!ppinfo.datalen) { + if (!ppinfo.datalen || !PROXY_PROTOCOL_IS_INSECURE(conn->pp_version)) { ppinfo.af = tuplehash_in(conn).af; ppinfo.proto = IPPROTO_TCP; - ppinfo.version = conn->pp_version; + ppinfo.version = PROXY_PROTOCOL_VERSION(conn->pp_version); ppinfo.cmd = 1; if (AF_INET == ppinfo.af) { ppinfo.addr.ip4.src_addr = conn->caddr.in.s_addr; @@ -828,8 +830,8 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, tcp_in_remove_ts(th); tcp_in_init_seq(conn, mbuf, th); - if (PROXY_PROTOCOL_V1 != conn->pp_version && - PROXY_PROTOCOL_V2 != conn->pp_version) { + if (PROXY_PROTOCOL_V1 != PROXY_PROTOCOL_VERSION(conn->pp_version) + && PROXY_PROTOCOL_V2 != PROXY_PROTOCOL_VERSION(conn->pp_version)) { if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { tcp_in_remove_toa(th, iaf); } @@ -839,8 +841,8 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, /* add toa/proxy_proto to first data packet */ if (ntohl(th->ack_seq) == conn->fnat_seq.fdata_seq && !th->syn && !th->rst /*&& !th->fin*/) { - if (PROXY_PROTOCOL_V2 == conn->pp_version || - PROXY_PROTOCOL_V1 == conn->pp_version) { + if (PROXY_PROTOCOL_V2 == PROXY_PROTOCOL_VERSION(conn->pp_version) + || PROXY_PROTOCOL_V1 == PROXY_PROTOCOL_VERSION(conn->pp_version)) { if (conn->fnat_seq.isn - conn->fnat_seq.delta + 1 == ntohl(th->seq)) { /* avoid inserting repetitive ppdata when the first rs ack delayed */ err = tcp_in_add_proxy_proto(conn, mbuf, th, iphdrlen, &pp_hdr_shift); diff --git a/src/ipvs/ip_vs_proto_udp.c b/src/ipvs/ip_vs_proto_udp.c index e5b90b344..a3f2a4690 100644 --- a/src/ipvs/ip_vs_proto_udp.c +++ b/src/ipvs/ip_vs_proto_udp.c @@ -720,13 +720,15 @@ static int udp_in_add_proxy_proto(struct dp_vs_conn *conn, if (unlikely(EDPVS_OK != proxy_proto_parse(mbuf, offset, &ppinfo))) return EDPVS_INVPKT; - if (ppinfo.datalen > 0 && ppinfo.version == conn->pp_version) + if (ppinfo.datalen > 0 + && ppinfo.version == PROXY_PROTOCOL_VERSION(conn->pp_version) + && PROXY_PROTOCOL_IS_INSECURE(conn->pp_version)) return EDPVS_OK; // keep intact the original proxy protocol data - if (!ppinfo.datalen) { + if (!ppinfo.datalen || !PROXY_PROTOCOL_IS_INSECURE(conn->pp_version)) { ppinfo.af = tuplehash_in(conn).af; ppinfo.proto = IPPROTO_UDP; - ppinfo.version = conn->pp_version; + ppinfo.version = PROXY_PROTOCOL_VERSION(conn->pp_version); ppinfo.cmd = 1; if (AF_INET == ppinfo.af) { ppinfo.addr.ip4.src_addr = conn->caddr.in.s_addr; @@ -786,8 +788,8 @@ static int udp_fnat_in_handler(struct dp_vs_proto *proto, if (unlikely(!uh)) return EDPVS_INVPKT; - if (!conn->pp_sent && (PROXY_PROTOCOL_V2 == conn->pp_version || - PROXY_PROTOCOL_V2 == conn->pp_version)) { + if (!conn->pp_sent && + (PROXY_PROTOCOL_V2 == PROXY_PROTOCOL_VERSION(conn->pp_version))) { err = udp_in_add_proxy_proto(conn, mbuf, uh, iphdrlen, &hdr_shift); if (unlikely(EDPVS_OK != err)) RTE_LOG(INFO, IPVS, "%s: insert proxy protocol fail -- %s\n", @@ -832,8 +834,7 @@ static int udp_fnat_in_pre_handler(struct dp_vs_proto *proto, { struct conn_uoa *uoa = (struct conn_uoa *)conn->prot_data; - if (PROXY_PROTOCOL_V2 == conn->pp_version || - PROXY_PROTOCOL_V1 == conn->pp_version) + if (PROXY_PROTOCOL_V2 == PROXY_PROTOCOL_VERSION(conn->pp_version)) return EDPVS_OK; if (uoa && g_uoa_max_trail > 0) diff --git a/src/ipvs/ip_vs_proxy_proto.c b/src/ipvs/ip_vs_proxy_proto.c index c4b515059..8f08f9228 100644 --- a/src/ipvs/ip_vs_proxy_proto.c +++ b/src/ipvs/ip_vs_proxy_proto.c @@ -312,7 +312,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, err = EDPVS_NOMEM; goto errout; } - if (PROXY_PROTOCOL_V2 == conn->pp_version) { + if (PROXY_PROTOCOL_V2 == PROXY_PROTOCOL_VERSION(conn->pp_version)) { pphv2 = (struct proxy_hdr_v2 *)pph; rte_memcpy(pphv2->sig, PROXY_PROTO_V2_SIGNATURE, sizeof(pphv2->sig)); pphv2->cmd = 1; @@ -321,7 +321,7 @@ static int proxy_proto_send_standalone(struct proxy_info *ppinfo, pphv2->af = ppv2_af_host2pp(ppinfo->af); pphv2->addrlen = ntohs(ppdlen - sizeof(struct proxy_hdr_v2)); rte_memcpy(pphv2 + 1, &ppinfo->addr, ppdlen - sizeof(struct proxy_hdr_v2)); - } else if (PROXY_PROTOCOL_V1 == conn->pp_version) { + } else if (PROXY_PROTOCOL_V1 == PROXY_PROTOCOL_VERSION(conn->pp_version)) { rte_memcpy(pph, ppv1data, ppdlen); } else { err = EDPVS_NOTSUPP; @@ -434,7 +434,8 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, if (unlikely(conn->dest->fwdmode != DPVS_FWD_MODE_FNAT)) return EDPVS_NOTSUPP; - if (ppinfo->datalen > 0 && ppinfo->version == conn->pp_version) + if (ppinfo->datalen > 0 && PROXY_PROTOCOL_IS_INSECURE(conn->pp_version) + && ppinfo->version == PROXY_PROTOCOL_VERSION(conn->pp_version)) return EDPVS_OK; // proxy the existing proxy protocol data directly to rs oaf = tuplehash_out(conn).af; @@ -453,7 +454,7 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, // calculate required space size in mbuf ppdatalen = 0; - if (PROXY_PROTOCOL_V2 == conn->pp_version) { + if (PROXY_PROTOCOL_V2 == PROXY_PROTOCOL_VERSION(conn->pp_version)) { ppdatalen = sizeof(struct proxy_hdr_v2); if (ppinfo->cmd == 1) { switch (ppinfo->af) { @@ -471,7 +472,7 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, return EDPVS_NOTSUPP; } } - } else if (PROXY_PROTOCOL_V1 == conn->pp_version) { + } else if (PROXY_PROTOCOL_V1 == PROXY_PROTOCOL_VERSION(conn->pp_version)) { if (ppinfo->cmd == 1) { if (IPPROTO_TCP != ppinfo->proto) return EDPVS_NOTSUPP; // v1 only supports tcp @@ -554,7 +555,7 @@ int proxy_proto_insert(struct proxy_info *ppinfo, struct dp_vs_conn *conn, } // fill in proxy protocol data - if (PROXY_PROTOCOL_V2 == conn->pp_version) { + if (PROXY_PROTOCOL_V2 == PROXY_PROTOCOL_VERSION(conn->pp_version)) { pphv2 = (struct proxy_hdr_v2 *)pph; rte_memcpy(pphv2->sig, PROXY_PROTO_V2_SIGNATURE, sizeof(pphv2->sig)); pphv2->cmd = 1; diff --git a/tools/dpvs-agent/dpvs-agent-api.yaml b/tools/dpvs-agent/dpvs-agent-api.yaml index af3886458..bd4ff3340 100644 --- a/tools/dpvs-agent/dpvs-agent-api.yaml +++ b/tools/dpvs-agent/dpvs-agent-api.yaml @@ -490,8 +490,20 @@ definitions: type: "integer" format: "uint8" ProxyProto: + description: | + 0 (0x00): disable + 1 (0x01): v1 + 2 (0x02): v2 + 17 (0x11): v1-insecure + 18 (0x12): v2-insecure type: "integer" format: "uint8" + enum: + - 0 + - 1 + - 2 + - 17 + - 18 Port: type: "integer" format: "uint16" @@ -586,7 +598,9 @@ definitions: type: "string" enum: - v2 + - v2-insecure - v1 + - v1-insecure - disable SchedName: type: "string" diff --git a/tools/dpvs-agent/models/virtual_server_spec_expand.go b/tools/dpvs-agent/models/virtual_server_spec_expand.go index da101eb6c..fbd31358d 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_expand.go +++ b/tools/dpvs-agent/models/virtual_server_spec_expand.go @@ -61,7 +61,13 @@ type VirtualServerSpecExpand struct { // proto Proto uint8 `json:"Proto,omitempty"` - // proxy proto + // 0 (0x00): disable + // 1 (0x01): v1 + // 2 (0x02): v2 + // 17 (0x11): v1-insecure + // 18 (0x12): v2-insecure + // + // Enum: [0 1 2 17 18] ProxyProto uint8 `json:"ProxyProto,omitempty"` // r ss @@ -98,6 +104,10 @@ func (m *VirtualServerSpecExpand) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateProxyProto(formats); err != nil { + res = append(res, err) + } + if err := m.validateRSs(formats); err != nil { res = append(res, err) } @@ -202,6 +212,39 @@ func (m *VirtualServerSpecExpand) validateMatch(formats strfmt.Registry) error { return nil } +var virtualServerSpecExpandTypeProxyProtoPropEnum []interface{} + +func init() { + var res []uint8 + if err := json.Unmarshal([]byte(`[0,1,2,17,18]`), &res); err != nil { + panic(err) + } + for _, v := range res { + virtualServerSpecExpandTypeProxyProtoPropEnum = append(virtualServerSpecExpandTypeProxyProtoPropEnum, v) + } +} + +// prop value enum +func (m *VirtualServerSpecExpand) validateProxyProtoEnum(path, location string, value uint8) error { + if err := validate.EnumCase(path, location, value, virtualServerSpecExpandTypeProxyProtoPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *VirtualServerSpecExpand) validateProxyProto(formats strfmt.Registry) error { + if swag.IsZero(m.ProxyProto) { // not required + return nil + } + + // value enum + if err := m.validateProxyProtoEnum("ProxyProto", "body", m.ProxyProto); err != nil { + return err + } + + return nil +} + func (m *VirtualServerSpecExpand) validateRSs(formats strfmt.Registry) error { if swag.IsZero(m.RSs) { // not required return nil diff --git a/tools/dpvs-agent/models/virtual_server_spec_tiny.go b/tools/dpvs-agent/models/virtual_server_spec_tiny.go index 490e578ce..0219c186d 100644 --- a/tools/dpvs-agent/models/virtual_server_spec_tiny.go +++ b/tools/dpvs-agent/models/virtual_server_spec_tiny.go @@ -39,7 +39,7 @@ type VirtualServerSpecTiny struct { Match *MatchSpec `json:"Match,omitempty"` // proxy protocol - // Enum: [v2 v1 disable] + // Enum: [v2 v2-insecure v1 v1-insecure disable] ProxyProtocol string `json:"ProxyProtocol,omitempty"` // sched name @@ -98,7 +98,7 @@ var virtualServerSpecTinyTypeProxyProtocolPropEnum []interface{} func init() { var res []string - if err := json.Unmarshal([]byte(`["v2","v1","disable"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["v2","v2-insecure","v1","v1-insecure","disable"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -111,9 +111,15 @@ const ( // VirtualServerSpecTinyProxyProtocolV2 captures enum value "v2" VirtualServerSpecTinyProxyProtocolV2 string = "v2" + // VirtualServerSpecTinyProxyProtocolV2DashInsecure captures enum value "v2-insecure" + VirtualServerSpecTinyProxyProtocolV2DashInsecure string = "v2-insecure" + // VirtualServerSpecTinyProxyProtocolV1 captures enum value "v1" VirtualServerSpecTinyProxyProtocolV1 string = "v1" + // VirtualServerSpecTinyProxyProtocolV1DashInsecure captures enum value "v1-insecure" + VirtualServerSpecTinyProxyProtocolV1DashInsecure string = "v1-insecure" + // VirtualServerSpecTinyProxyProtocolDisable captures enum value "disable" VirtualServerSpecTinyProxyProtocolDisable string = "disable" ) diff --git a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go index 740c32d13..1dc99f35a 100644 --- a/tools/dpvs-agent/pkg/ipc/types/virtualserver.go +++ b/tools/dpvs-agent/pkg/ipc/types/virtualserver.go @@ -244,11 +244,16 @@ func (vs *VirtualServerSpec) SetProto(proto uint8) { } func (vs *VirtualServerSpec) SetProxyProto(version string) { - if version == models.VirtualServerSpecTinyProxyProtocolV2 { + switch version { + case models.VirtualServerSpecTinyProxyProtocolV2: vs.proxyProto = 2 - } else if version == models.VirtualServerSpecTinyProxyProtocolV1 { + case models.VirtualServerSpecTinyProxyProtocolV1: vs.proxyProto = 1 - } else { + case models.VirtualServerSpecTinyProxyProtocolV2DashInsecure: + vs.proxyProto = 18 + case models.VirtualServerSpecTinyProxyProtocolV1DashInsecure: + vs.proxyProto = 17 + default: vs.proxyProto = 0 } } diff --git a/tools/dpvs-agent/restapi/embedded_spec.go b/tools/dpvs-agent/restapi/embedded_spec.go index 2a57e3c85..7c6773a97 100644 --- a/tools/dpvs-agent/restapi/embedded_spec.go +++ b/tools/dpvs-agent/restapi/embedded_spec.go @@ -1851,8 +1851,16 @@ func init() { "format": "uint8" }, "ProxyProto": { + "description": "0 (0x00): disable\n1 (0x01): v1\n2 (0x02): v2\n17 (0x11): v1-insecure\n18 (0x12): v2-insecure\n", "type": "integer", - "format": "uint8" + "format": "uint8", + "enum": [ + 0, + 1, + 2, + 17, + 18 + ] }, "RSs": { "$ref": "#/definitions/RealServerExpandList" @@ -1912,7 +1920,9 @@ func init() { "type": "string", "enum": [ "v2", + "v2-insecure", "v1", + "v1-insecure", "disable" ] }, @@ -4204,8 +4214,16 @@ func init() { "format": "uint8" }, "ProxyProto": { + "description": "0 (0x00): disable\n1 (0x01): v1\n2 (0x02): v2\n17 (0x11): v1-insecure\n18 (0x12): v2-insecure\n", "type": "integer", - "format": "uint8" + "format": "uint8", + "enum": [ + 0, + 1, + 2, + 17, + 18 + ] }, "RSs": { "$ref": "#/definitions/RealServerExpandList" @@ -4265,7 +4283,9 @@ func init() { "type": "string", "enum": [ "v2", + "v2-insecure", "v1", + "v1-insecure", "disable" ] }, diff --git a/tools/ipvsadm/ipvsadm.c b/tools/ipvsadm/ipvsadm.c index 549ecd71f..dd234691e 100644 --- a/tools/ipvsadm/ipvsadm.c +++ b/tools/ipvsadm/ipvsadm.c @@ -1709,7 +1709,7 @@ static void usage_exit(const char *program, const int exit_status) " --connection -c output of current IPVS connections\n" " --timeout output of timeout (tcp tcpfin udp)\n" " --conn-timeout set connection established timeout\n" - " --proxy-protocol proxy protocol config (disable|v1|v2)\n" + " --proxy-protocol proxy protocol config (disable|v1|v2|v1-insecure|v2-insecure)\n" " --daemon output of daemon information\n" " --stats output of statistics information\n" " --rate output of rate information\n" From 30f421d1ea49c2999430da4f815c52ebf431e0cc Mon Sep 17 00:00:00 2001 From: ywc689 Date: Mon, 11 Dec 2023 18:06:57 +0800 Subject: [PATCH 103/105] ipvs: toa enhancements 1. Do not insert toa data in syn packets any more. 2. Compact tcp option space or remove some options when inserting toa data failed and then try again. 3. Emit a warning log for audit when toa insertion failed finally. Signed-off-by: ywc689 --- src/ipvs/ip_vs_proto_tcp.c | 184 +++++++++++++++++++++++++++---------- 1 file changed, 136 insertions(+), 48 deletions(-) diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c index 75e5713a6..8c7edb501 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c @@ -306,46 +306,129 @@ static void tcp_in_remove_ts(struct tcphdr *tcph) } } -/* use NOP option to replace TCP_OLEN_IP4_ADDR and TCP_OLEN_IP6_ADDR opt */ -static void tcp_in_remove_toa(struct tcphdr *tcph, int af) +/* + * Remove NOP and TOA options preset in the mbuf and compact option space. + * If still no enough space, trim more options except for the protected ones. + * + * Return the trimmed length on success, otherwise dpvs error num on failure. + * */ +static int tcp_in_prune_options(int af, int reqlen, struct rte_mbuf *mbuf, struct tcphdr *tcph) { - unsigned char *ptr; - int len, i; - uint32_t tcp_opt_len = af == AF_INET ? TCP_OLEN_IP4_ADDR : TCP_OLEN_IP6_ADDR; + unsigned char *ptr, *fast, *slow; + const unsigned char *l3hdr, *payload; + int i, optlen; + unsigned int pruned; + uint8_t opcode, opsize; + uint64_t opts_protected; + const uint8_t opts_maxlen[64] = { + [2] = 4, [3] = 3, [4] = 2, + [8] = 10, [30] = 40, [34] = 18 + }; ptr = (unsigned char *)(tcph + 1); - len = (tcph->doff << 2) - sizeof(struct tcphdr); + fast = slow = ptr; + optlen = (tcph->doff << 2) - sizeof(struct tcphdr); + payload = ptr + optlen; - while (len > 0) { - int opcode = *ptr++; - int opsize; + if (optlen < reqlen) /* make no sense to do anything */ + return 0; + while (optlen > 0) { + opcode = *ptr++; switch (opcode) { case TCP_OPT_EOL: - return; + goto fini; case TCP_OPT_NOP: - len--; + fast++; + optlen--; continue; default: opsize = *ptr++; - if (opsize < 2) /* silly options */ - return; - if (opsize > len) - return; /* partial options */ - if ((opcode == TCP_OPT_ADDR) && (opsize == tcp_opt_len)) { - for (i = 0; i < tcp_opt_len; i++) { - *(ptr - 2 + i) = TCP_OPT_NOP; + if (opsize < 2) /* silly options */ + goto fini; + if (opsize > optlen) /* partial options */ + goto fini; + if (opcode == TCP_OPT_ADDR) { + fast += opsize; + } else { + for (i = 0; i < opsize; i++) { + if (slow != fast) + *slow = *fast; + slow++; + fast++; } - /* DON'T RETURN - * keep search other TCP_OPT_ADDR ,and clear them. - * See https://github.com/iqiyi/dpvs/pull/925 for more detail. */ } ptr += opsize - 2; - len -= opsize; + optlen -= opsize; break; } } + +fini: + pruned = payload - slow; + if (pruned < reqlen) { + /* further trim the options, the tcp functionality relies on unprotected + * options may get hurt, refer to: + * https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml + * #tcp-parameters-1 + * */ + ptr = slow; + slow = fast = (unsigned char *)(tcph + 1); + if (tcph->syn) + opts_protected = (1ULL << 2) | (1ULL << 3) | (1ULL << 4) /* MSS, WS, SACKP */ + | (1ULL << 8) | (1ULL << 30) | (1ULL << 34); /* TS, MPTCP, TFO */ + else + opts_protected = (1ULL << 8); /* TS, drop SACK, MPTCP DSS/REMOVE_ADDR */ + while (fast < ptr) { + opcode = *fast; + opsize = *(fast + 1); + if (opcode < 64 && ((1ULL << opcode) & opts_protected) + && (opsize <= opts_maxlen[opcode])) { + for (i = 0; i < opsize; i++) + *slow++ = *fast++; + opts_protected ^= (1ULL << opcode); + } else { + fast += opsize; + pruned += opsize; + if (pruned >= reqlen) { + while (fast < ptr) + *slow++ = *fast++; + break; + } + } + } + pruned = payload - slow; + } + if (pruned > 0) { + while (pruned & 0x3) { /* 4-bytes alignment for tcp options */ + *slow++ = 0; + pruned--; + } + if (!pruned) + return 0; + /* trim the packet */ + l3hdr = rte_pktmbuf_mtod(mbuf, void *); + if (unlikely(mbuf_may_pull(mbuf, mbuf->pkt_len) != 0)) { + memset(slow, 0, pruned); + return EDPVS_INVPKT; + } + if (unlikely(payload - l3hdr > mbuf->pkt_len)) { + memset(slow, 0, pruned); + return EDPVS_INVPKT; + } + memmove(slow, payload, mbuf->pkt_len - (payload - l3hdr)); + rte_pktmbuf_trim(mbuf, pruned); + tcph->doff -= (pruned >> 2); + if (af == AF_INET) + ((struct rte_ipv4_hdr *)l3hdr)->total_length = + htons(ntohs(((struct rte_ipv4_hdr *)l3hdr)->total_length) - pruned); + else + ((struct rte_ipv6_hdr *)l3hdr)->payload_len = + htons(ntohs(((struct rte_ipv6_hdr *)l3hdr)->payload_len) - pruned); + return pruned; + } + return 0; } static int tcp_in_add_proxy_proto(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, @@ -797,15 +880,12 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, struct dp_vs_conn *conn, struct rte_mbuf *mbuf) { struct tcphdr *th; - /* af/mbuf may be changed for nat64 which in af is ipv6 and out is ipv4 */ - int iaf, oaf; - int iphdrlen; + int af; /* outbound af */ + int iphdrlen, toalen; int err, pp_hdr_shift = 0; - iaf = tuplehash_in(conn).af; - oaf = tuplehash_out(conn).af; - - iphdrlen = ((AF_INET6 == oaf) ? ip6_hdrlen(mbuf): ip4_hdrlen(mbuf)); + af = tuplehash_out(conn).af; + iphdrlen = ((AF_INET6 == af) ? ip6_hdrlen(mbuf): ip4_hdrlen(mbuf)); if (mbuf_may_pull(mbuf, iphdrlen + sizeof(*th)) != 0) return EDPVS_INVPKT; @@ -819,41 +899,49 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, /* * for SYN packet - * 1. remove tcp timestamp option - * laddress for different client have diff timestamp. - * 2. save original TCP sequence for seq-adjust later. - * since TCP option will be change. - * 3. add TOA option - * so that RS with TOA module can get real client IP. + * 1. remove tcp timestamp option, + * laddrs for different clients have diff timestamp. + * 2. save original TCP sequence for seq-adjust later + * since TCP option will be changed. */ if (th->syn && !th->ack) { tcp_in_remove_ts(th); - tcp_in_init_seq(conn, mbuf, th); - if (PROXY_PROTOCOL_V1 != PROXY_PROTOCOL_VERSION(conn->pp_version) - && PROXY_PROTOCOL_V2 != PROXY_PROTOCOL_VERSION(conn->pp_version)) { - if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { - tcp_in_remove_toa(th, iaf); - } - } } - /* add toa/proxy_proto to first data packet */ + /* Add toa/proxy_protocol to the first data packet */ if (ntohl(th->ack_seq) == conn->fnat_seq.fdata_seq && !th->syn && !th->rst /*&& !th->fin*/) { if (PROXY_PROTOCOL_V2 == PROXY_PROTOCOL_VERSION(conn->pp_version) || PROXY_PROTOCOL_V1 == PROXY_PROTOCOL_VERSION(conn->pp_version)) { if (conn->fnat_seq.isn - conn->fnat_seq.delta + 1 == ntohl(th->seq)) { - /* avoid inserting repetitive ppdata when the first rs ack delayed */ + /* avoid inserting repetitive proxy protocol data + * when the first rs ack is delayed */ err = tcp_in_add_proxy_proto(conn, mbuf, th, iphdrlen, &pp_hdr_shift); if (unlikely(EDPVS_OK != err)) RTE_LOG(INFO, IPVS, "%s: insert proxy protocol fail -- %s\n", __func__, dpvs_strerror(err)); th = ((void *)th) + pp_hdr_shift; } - } else { - if (unlikely(tcp_in_add_toa(conn, mbuf, th) != EDPVS_OK)) { - tcp_in_remove_toa(th, iaf); + } else { /* use toa */ + err = tcp_in_add_toa(conn, mbuf, th); + if (unlikely(EDPVS_OK != err)) { + toalen = tuplehash_in(conn).af == AF_INET ? TCP_OLEN_IP4_ADDR : TCP_OLEN_IP6_ADDR; + if (tcp_in_prune_options(af, toalen, mbuf, th) >= toalen + && (EDPVS_NOROOM == err || EDPVS_FRAG == err)) { + err = tcp_in_add_toa(conn, mbuf, th); + } + if (EDPVS_OK != err) { + char caddrbuf[64], vaddrbuf[64], laddrbuf[64], daddrbuf[64]; + const char *caddr, *vaddr, *laddr, *daddr; + caddr = inet_ntop(conn->af, &conn->caddr, caddrbuf, sizeof(caddrbuf)) ? caddrbuf : "::"; + vaddr = inet_ntop(conn->af, &conn->vaddr, vaddrbuf, sizeof(vaddrbuf)) ? vaddrbuf : "::"; + laddr = inet_ntop(af, &conn->laddr, laddrbuf, sizeof(laddrbuf)) ? laddrbuf : "::"; + daddr = inet_ntop(af, &conn->daddr, daddrbuf, sizeof(daddrbuf)) ? daddrbuf : "::"; + RTE_LOG(WARNING, IPVS, "TOA add failed(%s): [%s]:%d -> [%s]:%d; [%s]:%d -> [%s]:%d\n", + dpvs_strerror(err), caddr, htons(conn->cport), vaddr, htons(conn->vport), + laddr, htons(conn->lport), daddr, htons(conn->dport)); + } } } } @@ -864,7 +952,7 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, th->source = conn->lport; th->dest = conn->dport; - return tcp_send_csum(oaf, iphdrlen, th, conn, mbuf, conn->in_dev); + return tcp_send_csum(af, iphdrlen, th, conn, mbuf, conn->in_dev); } static int tcp_fnat_out_handler(struct dp_vs_proto *proto, From 58a0e7528a972da16966e6294c04be909874ce28 Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 12 Dec 2023 10:35:31 +0800 Subject: [PATCH 104/105] patch: update dcdn-toa.patch Signed-off-by: ywc689 --- patch/dcdn-toa.patch | 47 +++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/patch/dcdn-toa.patch b/patch/dcdn-toa.patch index 5107fcd42..3d9c84a9b 100644 --- a/patch/dcdn-toa.patch +++ b/patch/dcdn-toa.patch @@ -1,32 +1,31 @@ -From 55e8e5da2b4b0893d36cb3f621bedf9833c4ea50 Mon Sep 17 00:00:00 2001 +From cee6889685240558ebea795615539b7289070842 Mon Sep 17 00:00:00 2001 From: wangyetong Date: Thu, 14 Sep 2023 15:33:42 +0800 Subject: [PATCH] added dcdn toa --- - include/ipvs/conn.h | 5 +++++ + include/ipvs/conn.h | 4 ++++ include/ipvs/proto_tcp.h | 2 ++ - src/ipvs/ip_vs_proto_tcp.c | 54 +++++++++++++++++++++++++++++++++++++++++++++- + src/ipvs/ip_vs_proto_tcp.c | 55 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/include/ipvs/conn.h b/include/ipvs/conn.h -index fa0bdeb..88dcb44 100644 +index 843721e..78fb0ba 100644 --- a/include/ipvs/conn.h +++ b/include/ipvs/conn.h -@@ -166,6 +166,11 @@ struct dp_vs_conn { - /* flag for gfwip */ - bool outwall; +@@ -167,6 +167,10 @@ struct dp_vs_conn { + /* connection redirect in fnat/snat/nat modes */ + struct dp_vs_redirect *redirect; + /* dcdn toa found or not */ + bool dcdn_found; + /* dcdn toa address */ + struct in_addr dcdn_addr; -+ } __rte_cache_aligned; /* for syn-proxy to save all ack packet in conn before rs's syn-ack arrives */ diff --git a/include/ipvs/proto_tcp.h b/include/ipvs/proto_tcp.h -index 9f5162a..41d5646 100644 +index 3d1515a..f0cf50c 100644 --- a/include/ipvs/proto_tcp.h +++ b/include/ipvs/proto_tcp.h @@ -28,6 +28,7 @@ enum { @@ -46,11 +45,11 @@ index 9f5162a..41d5646 100644 #define TCP_OLEN_TSTAMP_ALIGNED 12 #define TCP_OLEN_SACK_BASE 2 diff --git a/src/ipvs/ip_vs_proto_tcp.c b/src/ipvs/ip_vs_proto_tcp.c -index cbb7cb2..2cd889a 100644 +index 6acbbca..5b185fa 100644 --- a/src/ipvs/ip_vs_proto_tcp.c +++ b/src/ipvs/ip_vs_proto_tcp.c -@@ -305,6 +305,43 @@ static void tcp_in_remove_ts(struct tcphdr *tcph) - } +@@ -441,6 +441,43 @@ static int tcp_in_add_proxy_proto(struct dp_vs_conn *conn, struct rte_mbuf *mbuf + return proxy_proto_insert(&ppinfo, conn, mbuf, tcph, hdr_shift); } +/* check dcdn toa option */ @@ -90,10 +89,10 @@ index cbb7cb2..2cd889a 100644 + return EDPVS_NOTEXIST; +} + - static inline int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, + static int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, struct tcphdr *tcph) { -@@ -382,7 +419,10 @@ static inline int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, +@@ -518,7 +555,10 @@ static int tcp_in_add_toa(struct dp_vs_conn *conn, struct rte_mbuf *mbuf, if (conn->af == AF_INET) { struct tcpopt_ip4_addr *toa_ip4 = (struct tcpopt_ip4_addr *)(tcph + 1); @@ -105,21 +104,18 @@ index cbb7cb2..2cd889a 100644 } else { struct tcpopt_ip6_addr *toa_ip6 = (struct tcpopt_ip6_addr *)(tcph + 1); -@@ -694,9 +734,13 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, - struct dp_vs_conn *conn, struct rte_mbuf *mbuf) - { - struct tcphdr *th; +@@ -842,6 +882,10 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, + int af; /* outbound af */ + int iphdrlen; + int err, pp_hdr_shift = 0; + struct in_addr dcdn_addr; - /* af/mbuf may be changed for nat64 which in af is ipv6 and out is ipv4 */ - int af = tuplehash_out(conn).af; - int iphdrlen = ((AF_INET6 == af) ? ip6_hdrlen(mbuf): ip4_hdrlen(mbuf)); +#ifdef CONFIG_DPVS_IPVS_DEBUG + char dcdn_buf[64]; +#endif - if (mbuf_may_pull(mbuf, iphdrlen + sizeof(*th)) != 0) - return EDPVS_INVPKT; -@@ -720,6 +764,14 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, + af = tuplehash_out(conn).af; + iphdrlen = ((AF_INET6 == af) ? ip6_hdrlen(mbuf): ip4_hdrlen(mbuf)); +@@ -866,6 +910,15 @@ static int tcp_fnat_in_handler(struct dp_vs_proto *proto, if (th->syn && !th->ack) { tcp_in_remove_ts(th); tcp_in_init_seq(conn, mbuf, th); @@ -131,9 +127,10 @@ index cbb7cb2..2cd889a 100644 + RTE_LOG(DEBUG, IPVS, "get dcdn toa addr %s\n", dcdn_buf); +#endif + } - tcp_in_add_toa(conn, mbuf, th); ++ tcp_in_add_toa(conn, mbuf, th); } + /* Add toa/proxy_protocol to the first data packet */ -- 1.8.3.1 From 3336c3e8d43dd572d0c304d55109baad7af51dee Mon Sep 17 00:00:00 2001 From: ywc689 Date: Tue, 19 Dec 2023 15:42:00 +0800 Subject: [PATCH 105/105] release v1.9.6 Signed-off-by: ywc689 --- src/VERSION | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/src/VERSION b/src/VERSION index 1c9eb11df..7a8b5d13b 100755 --- a/src/VERSION +++ b/src/VERSION @@ -1,17 +1,44 @@ #!/bin/sh # program: dpvs -# Jul 13, 2023 -# +# Dec 19, 2023 # +## # Features -# - Add new tools: dpvs-agent and healthcheck. +# - New tool: **dpvs-agent**, a management daemon tool for dpvs based on OpenAPI. +# - New tool: **healthcheck**, a service health check daemon tool cooperating with dpvs-agent. +# - Dpvs: Develop **passive health check** methods for tcp and bidirectional udp backends. +# - Dpvs: Add supports for **Proxy Protocol** with both v1 and v2 versions. +# - Dpvs: Add supports for extended statistics of ethernet devices. +# - Dpvs: Add configuration file and dpip supports for allmulticast setting switch. +# - Build: Transfer all build configurations to a top-level file `config.mk`. +# - Containerization: Draft a Dockerfile and a tutorial document to build and run dpvs in container. # # Bugfixes -# - Dpvs: Improve config of adding/removing multicast ether addresses. -# - Dpvs: Fix synproxy config problems. -# - Keepalived: Fix session disturbance problem when vs/rs updated and reloaded. +# - Dpvs: Protect toa from source address spoofing attack and increase success ratio for source address delievery via toa. +# - Dpvs: Adjust tcp window scale in outbound direction for synproxy to improve throughput in bulk upload cases. +# - Dpvs: Fix timer inaccuracy problem when timing over 524s. +# - Dpvs: Fix the crash problem caused by ether address list buffer overflow. +# - Dpvs: Fix the crash problem caused by dividing by zero when bonding slaves attempt to send packets out. +# - Dpvs: Fix the crash problem caused by inconsistent data structures of `dp_vs_dest_compat` between dpvs and keepalived. +# - Dpvs: Correct ipo option length for judgement of branching to standalone uoa. +# - Dpvs: Inhibit setting multicast ether address from slave lcores. +# - Dpvs: Fix service flag conflicts of synproxy and expire-quiescent. +# - Dpvs: Fix the chaos use of flag, flags and fwdmode in dest and service structures. +# - Dpvs: Fix service flush function not usable problem. +# - Dpvs: Fix invalid port problem when getting verbose information of netif devices. +# - Dpvs: Use atomic operation to generate packet id for ipv4 header. +# - Dpvs: Remove fragile implementations of strategy routing for snat. +# - Dpvs: Remove the stale config item "ipc_msg/unix_domain". +# - Keepalived: Do not delete and re-add vs/rs to eliminate service disturbances at reload. +# - Keepalived: Fix a carsh problem caused by missing definition of allowlist/denylist config items. +# - Ipvsadm: Add `conn-timeout` configuration option for service. +# - Ipvsadm: Fix the ambiguous use of '-Y' configuration option. +# - Ipvsadm: Fix icmpv6 configuration option `-1` lost problem.. +# - Ipvsadm: Update help text, including supported schedulers, laddr and allow/deny ip list. +# - Dpip: Fix line break problem in help message. +# - Uoa: Enable ipv6 with a macro for uoa example server. # export VERSION=1.9 -export RELEASE=5 +export RELEASE=6 echo $VERSION-$RELEASE