This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
tango-tsg-service-chaining-…/common/include/tuple.h

366 lines
10 KiB
C

#ifndef _TUPLE_H
#define _TUPLE_H
#ifdef __cpluscplus
extern "C"
{
#endif
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include "uthash.h"
enum address_type
{
ADDR_TYPE_IPV4,
ADDR_TYPE_IPV6,
};
struct ipv4_address
{
struct in_addr src; /* network order */
struct in_addr dst; /* network order */
};
struct ipv6_address
{
struct in6_addr src; /* network order */
struct in6_addr dst; /* network order */
};
union ip_address
{
struct ipv4_address ipv4; /* network order */
struct ipv6_address ipv6; /* network order */
};
struct two_tuple
{
enum address_type type;
union ip_address addr; /* network order */
};
struct four_tuple
{
struct two_tuple two_tuple;
in_port_t src_port; /* network order */
in_port_t dst_port; /* network order */
};
#define SET_HUMAN_READABLE_IPV4_TUPLE(tuple, src_addr_str, src_port, dst_addr_str, dst_port) \
do \
{ \
memset(tuple, 0, sizeof(struct four_tuple)); \
two_tuple_set_ipv4_string(&(tuple)->two_tuple, src_addr_str, dst_addr_str); \
four_tuple_set_port(tuple, htons(src_port), htons(dst_port)); \
} while (0)
#define SET_HUMAN_READABLE_IPV6_TUPLE(tuple, src_addr_str, src_port, dst_addr_str, dst_port) \
do \
{ \
memset(tuple, 0, sizeof(struct four_tuple)); \
two_tuple_set_ipv6_string(&(tuple)->two_tuple, src_addr_str, dst_addr_str); \
four_tuple_set_port(tuple, htons(src_port), htons(dst_port)); \
} while (0)
/******************************************************************************
* two tuple
******************************************************************************/
inline void two_tuple_set_ipv4_string(struct two_tuple *tuple, const char *src, const char *dst)
{
memset(tuple, 0, sizeof(struct two_tuple));
struct ipv4_address *ipv4 = &(tuple->addr.ipv4);
tuple->type = ADDR_TYPE_IPV4;
inet_pton(AF_INET, src, &ipv4->src);
inet_pton(AF_INET, dst, &ipv4->dst);
}
inline void two_tuple_set_ipv6_string(struct two_tuple *tuple, const char *src, const char *dst)
{
memset(tuple, 0, sizeof(struct two_tuple));
struct ipv6_address *ipv6 = &(tuple->addr.ipv6);
tuple->type = ADDR_TYPE_IPV6;
inet_pton(AF_INET6, src, &ipv6->src);
inet_pton(AF_INET6, dst, &ipv6->dst);
}
inline void two_tuple_set_ipv4_address(struct two_tuple *tuple, const struct in_addr *src, const struct in_addr *dst)
{
memset(tuple, 0, sizeof(struct two_tuple));
struct ipv4_address *ipv4 = &(tuple->addr.ipv4);
tuple->type = ADDR_TYPE_IPV4;
ipv4->src = *src;
ipv4->dst = *dst;
}
inline void two_tuple_set_ipv6_address(struct two_tuple *tuple, const struct in6_addr *src, const struct in6_addr *dst)
{
memset(tuple, 0, sizeof(struct two_tuple));
struct ipv6_address *ipv6 = &(tuple->addr.ipv6);
tuple->type = ADDR_TYPE_IPV6;
ipv6->src = *src;
ipv6->dst = *dst;
}
inline int two_tuple_get_address_length(const struct two_tuple *tuple)
{
if (tuple->type == ADDR_TYPE_IPV4)
{
return sizeof(struct in_addr);
}
else
{
return sizeof(struct in6_addr);
}
}
inline const char *two_tuple_get_src_address(const struct two_tuple *tuple)
{
if (tuple->type == ADDR_TYPE_IPV4)
{
return (const char *)&(tuple->addr.ipv4.src);
}
else
{
return (const char *)&(tuple->addr.ipv6.src);
}
}
inline const char *two_tuple_get_dst_address(const struct two_tuple *tuple)
{
if (tuple->type == ADDR_TYPE_IPV4)
{
return (const char *)&(tuple->addr.ipv4.dst);
}
else
{
return (const char *)&(tuple->addr.ipv6.dst);
}
}
inline void two_tuple_copy(struct two_tuple *dst, const struct two_tuple *src)
{
memset(dst, 0, sizeof(struct two_tuple));
dst->type = src->type;
if (src->type == ADDR_TYPE_IPV4)
{
dst->addr.ipv4 = src->addr.ipv4;
}
else
{
dst->addr.ipv6 = src->addr.ipv6;
}
}
inline int two_tuple_cmp(const struct two_tuple *tuple1, const struct two_tuple *tuple2)
{
if (tuple1->type != tuple2->type)
{
return -1;
}
if (tuple1->type == ADDR_TYPE_IPV4)
{
if (memcmp(&(tuple1->addr.ipv4.src), &(tuple2->addr.ipv4.src), sizeof(struct in_addr)) != 0)
{
return -1;
}
if (memcmp(&(tuple1->addr.ipv4.dst), &(tuple2->addr.ipv4.dst), sizeof(struct in_addr)) != 0)
{
return -1;
}
return 0;
}
else
{
if (memcmp(&(tuple1->addr.ipv6.src), &(tuple2->addr.ipv6.src), sizeof(struct in6_addr)) != 0)
{
return -1;
}
if (memcmp(&(tuple1->addr.ipv6.dst), &(tuple2->addr.ipv6.dst), sizeof(struct in6_addr)) != 0)
{
return -1;
}
return 0;
}
}
inline void two_tuple_reverse(const struct two_tuple *orin, struct two_tuple *out)
{
memset(out, 0, sizeof(struct two_tuple));
if (orin->type == ADDR_TYPE_IPV4)
{
out->type = ADDR_TYPE_IPV4;
struct ipv4_address *ipv4_out = &(out->addr.ipv4);
const struct ipv4_address *ipv4_orin = &(orin->addr.ipv4);
ipv4_out->src = ipv4_orin->dst;
ipv4_out->dst = ipv4_orin->src;
}
if (orin->type == ADDR_TYPE_IPV6)
{
out->type = ADDR_TYPE_IPV6;
struct ipv6_address *ipv6_out = &(out->addr.ipv6);
const struct ipv6_address *ipv6_orin = &(orin->addr.ipv6);
ipv6_out->src = ipv6_orin->dst;
ipv6_out->dst = ipv6_orin->src;
}
}
inline char *two_tuple_tostring(const struct two_tuple *tuple)
{
char *str_ret = NULL;
if (tuple->type == ADDR_TYPE_IPV4)
{
char src[INET_ADDRSTRLEN] = {0};
char dst[INET_ADDRSTRLEN] = {0};
inet_ntop(AF_INET, &tuple->addr.ipv4.src, src, sizeof(src));
inet_ntop(AF_INET, &tuple->addr.ipv4.dst, dst, sizeof(dst));
asprintf(&str_ret, "%s %s", src, dst);
}
if (tuple->type == ADDR_TYPE_IPV6)
{
char src[INET6_ADDRSTRLEN] = {0};
char dst[INET6_ADDRSTRLEN] = {0};
inet_ntop(AF_INET6, &tuple->addr.ipv6.src, src, sizeof(src));
inet_ntop(AF_INET6, &tuple->addr.ipv6.dst, dst, sizeof(dst));
asprintf(&str_ret, "%s %s", src, dst);
}
return str_ret;
}
/******************************************************************************
* four tuple
******************************************************************************/
inline void four_tuple_set_ipv4_string(struct four_tuple *tuple, const char *src, const char *dst)
{
two_tuple_set_ipv4_string(&(tuple->two_tuple), src, dst);
}
inline void four_tuple_set_ipv6_string(struct four_tuple *tuple, const char *src, const char *dst)
{
two_tuple_set_ipv6_string(&(tuple->two_tuple), src, dst);
}
inline void four_tuple_set_ipv4_address(struct four_tuple *tuple, const struct in_addr *src, const struct in_addr *dst)
{
two_tuple_set_ipv4_address(&(tuple->two_tuple), src, dst);
}
inline void four_tuple_set_ipv6_address(struct four_tuple *tuple, const struct in6_addr *src, const struct in6_addr *dst)
{
two_tuple_set_ipv6_address(&(tuple->two_tuple), src, dst);
}
inline void four_tuple_set_port(struct four_tuple *tuple, const in_port_t src, const in_port_t dst)
{
tuple->src_port = 0;
tuple->dst_port = 0;
tuple->src_port = src;
tuple->dst_port = dst;
}
inline int four_tuple_get_address_length(const struct four_tuple *tuple)
{
return two_tuple_get_address_length(&(tuple->two_tuple));
}
inline const char *four_tuple_get_src_address(const struct four_tuple *tuple)
{
return two_tuple_get_src_address(&(tuple->two_tuple));
}
inline const char *four_tuple_get_dst_address(const struct four_tuple *tuple)
{
return two_tuple_get_dst_address(&(tuple->two_tuple));
}
inline void four_tuple_copy(struct four_tuple *dst, const struct four_tuple *src)
{
memset(dst, 0, sizeof(struct four_tuple));
two_tuple_copy(&(dst->two_tuple), &(src->two_tuple));
dst->src_port = src->src_port;
dst->dst_port = src->dst_port;
}
inline int four_tuple_cmp(const struct four_tuple *tuple1, const struct four_tuple *tuple2)
{
if (tuple1->src_port != tuple2->src_port)
{
return -1;
}
if (tuple1->dst_port != tuple2->dst_port)
{
return -1;
}
return two_tuple_cmp(&(tuple1->two_tuple), &(tuple2->two_tuple));
}
inline void four_tuple_reverse(const struct four_tuple *orin, struct four_tuple *out)
{
memset(out, 0, sizeof(struct four_tuple));
out->src_port = orin->dst_port;
out->dst_port = orin->src_port;
two_tuple_reverse(&(orin->two_tuple), &(out->two_tuple));
}
inline char *four_tuple_tostring(const struct four_tuple *tuple)
{
char *str_ret = NULL;
if (tuple->two_tuple.type == ADDR_TYPE_IPV4)
{
char src[INET_ADDRSTRLEN] = {0};
char dst[INET_ADDRSTRLEN] = {0};
uint16_t src_port = ntohs((uint16_t)tuple->src_port);
uint16_t dst_port = ntohs((uint16_t)tuple->dst_port);
inet_ntop(AF_INET, &tuple->two_tuple.addr.ipv4.src, src, sizeof(src));
inet_ntop(AF_INET, &tuple->two_tuple.addr.ipv4.dst, dst, sizeof(dst));
asprintf(&str_ret, "%s %u %s %u", src, src_port, dst, dst_port);
}
if (tuple->two_tuple.type == ADDR_TYPE_IPV6)
{
char src[INET6_ADDRSTRLEN] = {0};
char dst[INET6_ADDRSTRLEN] = {0};
uint16_t src_port = ntohs((uint16_t)tuple->src_port);
uint16_t dst_port = ntohs((uint16_t)tuple->dst_port);
inet_ntop(AF_INET6, &tuple->two_tuple.addr.ipv6.src, src, sizeof(src));
inet_ntop(AF_INET6, &tuple->two_tuple.addr.ipv6.dst, dst, sizeof(dst));
asprintf(&str_ret, "%s %u %s %u", src, src_port, dst, dst_port);
}
return str_ret;
}
inline uint64_t four_tuple_hash(const struct four_tuple *tuple)
{
uint64_t hash_value = 0;
HASH_VALUE(tuple, sizeof(struct four_tuple), hash_value);
return hash_value;
}
#ifdef __cpluscplus
}
#endif
#endif