From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> To: tarantool-patches@freelists.org Cc: kostja@tarantool.org Subject: [tarantool-patches] [PATCH 3/6] test: introduce swim packet filter by destination address Date: Wed, 24 Apr 2019 17:36:17 +0300 [thread overview] Message-ID: <d71d08ba37fe427f6f8a309899410984a30b06fa.1556116199.git.v.shpilevoy@tarantool.org> (raw) In-Reply-To: <cover.1556116199.git.v.shpilevoy@tarantool.org> The filter is going to be used to test the SWIM suspicion component. The destination filter will break certain network channels, and the suspicion component shall withstand that. Part of #3234 --- test/unit/swim_test_transport.c | 10 +-- test/unit/swim_test_transport.h | 6 +- test/unit/swim_test_utils.c | 114 +++++++++++++++++++++++++++++++- test/unit/swim_test_utils.h | 11 +++ 4 files changed, 133 insertions(+), 8 deletions(-) diff --git a/test/unit/swim_test_transport.c b/test/unit/swim_test_transport.c index 513274c2c..c4a1dd774 100644 --- a/test/unit/swim_test_transport.c +++ b/test/unit/swim_test_transport.c @@ -238,14 +238,16 @@ swim_fd_close(struct swim_fd *fd) * Check all the packet filters if any wants to drop @a p packet. * @a dir parameter says direction. Values are the same as for * standard in/out descriptors: 0 for input, 1 for output. + * @a peer_fd says sender/receiver file descriptor depending on + * @a dir. */ static inline bool swim_fd_test_if_drop(struct swim_fd *fd, const struct swim_test_packet *p, - int dir) + int dir, int peer_fd) { struct swim_fd_filter *f; rlist_foreach_entry(f, &fd->filters, in_filters) { - if (f->check(p->data, p->size, f->udata, dir)) + if (f->check(p->data, p->size, f->udata, dir, peer_fd)) return true; } return false; @@ -380,8 +382,8 @@ static inline void swim_move_packet(struct swim_fd *src, struct swim_fd *dst, struct swim_test_packet *p) { - if (dst->is_opened && !swim_fd_test_if_drop(dst, p, 0) && - !swim_fd_test_if_drop(src, p, 1)) + if (dst->is_opened && !swim_fd_test_if_drop(dst, p, 0, src->evfd) && + !swim_fd_test_if_drop(src, p, 1, dst->evfd)) rlist_add_tail_entry(&dst->recv_queue, p, in_queue); else swim_test_packet_delete(p); diff --git a/test/unit/swim_test_transport.h b/test/unit/swim_test_transport.h index a66cf2d81..6235278d0 100644 --- a/test/unit/swim_test_transport.h +++ b/test/unit/swim_test_transport.h @@ -45,10 +45,12 @@ struct ev_loop; * arbitrary user data, and should return true, if the packet * should be dropped. False otherwise. Direction is said via * @a dir parameter. 0 means incoming packet, 1 means outgoing - * packet, just like standard IO descriptors. + * packet, just like standard IO descriptors. Via @a peer_fd + * parameter a sender/receiver descriptor number is passed + * depending on @a dir. */ typedef bool (*swim_test_filter_check_f)(const char *data, int size, - void *udata, int dir); + void *udata, int dir, int peer_fd); /** * Until there are no new IO events, feed EV_WRITE event to all diff --git a/test/unit/swim_test_utils.c b/test/unit/swim_test_utils.c index 0beeab65d..de1bef6e7 100644 --- a/test/unit/swim_test_utils.c +++ b/test/unit/swim_test_utils.c @@ -80,6 +80,67 @@ swim_drop_components_create(struct swim_drop_components *dc, const int *keys, dc->key_count = key_count; } +/** Packet filter to drop packets with specified destinations. */ +struct swim_drop_channel { + /** + * An array of file descriptors to drop messages sent to + * them. + */ + int *drop_fd; + /** Length of @a drop_fd. */ + int drop_fd_size; + /** Capacity of @a drop_fd. */ + int drop_fd_cap; +}; + +/** Initialize drop channel packet filter. */ +static inline void +swim_drop_channel_create(struct swim_drop_channel *dc) +{ + dc->drop_fd = NULL; + dc->drop_fd_size = 0; + dc->drop_fd_cap = 0; +} + +/** + * Set @a new_fd file descriptor into @a dc drop channel packet + * filter in place of @a old_fd descriptor. Just like dup2() + * system call. + * @retval 0 Success. + * @retval -1 @a old_fd is not found. + */ +static inline int +swim_drop_channel_dup_fd(const struct swim_drop_channel *dc, int new_fd, + int old_fd) +{ + for (int i = 0; i < dc->drop_fd_size; ++i) { + if (dc->drop_fd[i] == old_fd) { + dc->drop_fd[i] = new_fd; + return 0; + } + } + return -1; +} + +/** Add @a fd to @a dc drop channel packet filter. */ +static inline void +swim_drop_channel_add_fd(struct swim_drop_channel *dc, int fd) +{ + if (swim_drop_channel_dup_fd(dc, fd, -1) == 0) + return; + dc->drop_fd_cap += dc->drop_fd_cap + 1; + int new_bsize = dc->drop_fd_cap * sizeof(int); + dc->drop_fd = (int *) realloc(dc->drop_fd, new_bsize); + dc->drop_fd[dc->drop_fd_size++] = fd; +} + +/** Destroy drop channel packet filter. */ +static inline void +swim_drop_channel_destroy(struct swim_drop_channel *dc) +{ + free(dc->drop_fd); +} + /** * SWIM cluster node and its UUID. UUID is stored separately * because sometimes a test wants to drop a SWIM instance, but @@ -104,6 +165,8 @@ struct swim_node { * Filter to drop packets with specified SWIM components. */ struct swim_drop_components drop_components; + /** Filter to drop packets with specified destinations. */ + struct swim_drop_channel drop_channel; }; /** @@ -144,6 +207,7 @@ swim_node_create(struct swim_node *n, int id) swim_drop_rate_create(&n->drop_rate, 0, false, false); swim_drop_components_create(&n->drop_components, NULL, 0); + swim_drop_channel_create(&n->drop_channel); } struct swim_cluster * @@ -191,6 +255,7 @@ swim_cluster_delete(struct swim_cluster *cluster) for (int i = 0; i < cluster->size; ++i) { if (cluster->node[i].swim != NULL) swim_delete(cluster->node[i].swim); + swim_drop_channel_destroy(&cluster->node[i].drop_channel); } free(cluster->node); free(cluster); @@ -347,10 +412,12 @@ swim_drop_rate_new(double rate, bool is_for_in, bool is_for_out) * A packet filter dropping a packet with a certain probability. */ static bool -swim_filter_drop_rate(const char *data, int size, void *udata, int dir) +swim_filter_drop_rate(const char *data, int size, void *udata, int dir, + int peer_fd) { (void) data; (void) size; + (void) peer_fd; struct swim_drop_rate *dr = (struct swim_drop_rate *) udata; if ((dir == 0 && !dr->is_for_in) || (dir == 1 && !dr->is_for_out)) return false; @@ -397,10 +464,12 @@ swim_cluster_set_drop_in(struct swim_cluster *cluster, int i, double value) * Check if a packet contains any of the components to filter out. */ static bool -swim_filter_drop_component(const char *data, int size, void *udata, int dir) +swim_filter_drop_component(const char *data, int size, void *udata, int dir, + int peer_fd) { (void) size; (void) dir; + (void) peer_fd; struct swim_drop_components *dc = (struct swim_drop_components *) udata; /* Skip meta. */ mp_next(&data); @@ -433,6 +502,47 @@ swim_cluster_drop_components(struct swim_cluster *cluster, int i, &n->drop_components); } +/** + * Check if the packet sender should drop a packet outgoing to + * @a peer_fd file descriptor. + */ +static bool +swim_filter_drop_channel(const char *data, int size, void *udata, int dir, + int peer_fd) +{ + (void) data; + (void) size; + if (dir != 1) + return false; + struct swim_drop_channel *dc = (struct swim_drop_channel *) udata; + /* + * Fullscan is totally ok - there are no more than 2-3 + * blocks simultaneously in the tests. + */ + for (int i = 0; i < dc->drop_fd_size; ++i) { + if (dc->drop_fd[i] == peer_fd) + return true; + } + return false; +} + +void +swim_cluster_set_drop_channel(struct swim_cluster *cluster, int from_id, + int to_id, bool value) +{ + int to_fd = swim_fd(swim_cluster_member(cluster, to_id)); + struct swim_node *from_node = swim_cluster_node(cluster, from_id); + struct swim_drop_channel *dc = &from_node->drop_channel; + if (! value) { + swim_drop_channel_dup_fd(dc, -1, to_fd); + return; + } + swim_drop_channel_add_fd(dc, to_fd); + swim_test_transport_add_filter(swim_fd(from_node->swim), + swim_filter_drop_channel, + &from_node->drop_channel); +} + /** Check if @a s1 knows every member of @a s2's table. */ static inline bool swim1_contains_swim2(struct swim *s1, struct swim *s2) diff --git a/test/unit/swim_test_utils.h b/test/unit/swim_test_utils.h index 145af9b1f..c78894820 100644 --- a/test/unit/swim_test_utils.h +++ b/test/unit/swim_test_utils.h @@ -118,6 +118,17 @@ void swim_cluster_drop_components(struct swim_cluster *cluster, int i, const int *keys, int key_count); +/** + * When @a value is true, break a one direction network link + * between @a to_id and @a from_id SWIM instances. It is a pure + * network block, the member tables are not touched. All the + * packets trying to go directly from @a from_id to @a to_id are + * dropped. When @a value is false, the channel is restored. + */ +void +swim_cluster_set_drop_channel(struct swim_cluster *cluster, int from_id, + int to_id, bool value); + /** * Explicitly add a member of id @a from_id to a member of id * @a to_id. -- 2.20.1 (Apple Git-117)
next prev parent reply other threads:[~2019-04-24 14:36 UTC|newest] Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top 2019-04-24 14:36 [tarantool-patches] [PATCH 0/6] swim suspicion Vladislav Shpilevoy 2019-04-24 14:36 ` [tarantool-patches] [PATCH 1/6] test: rename swim_cluster_node to swim_cluster_member Vladislav Shpilevoy 2019-04-24 16:37 ` [tarantool-patches] " Konstantin Osipov 2019-04-24 14:36 ` [tarantool-patches] [PATCH 2/6] test: remove swim packet filter destructors Vladislav Shpilevoy 2019-04-24 16:37 ` [tarantool-patches] " Konstantin Osipov 2019-04-24 14:36 ` Vladislav Shpilevoy [this message] 2019-04-24 16:38 ` [tarantool-patches] Re: [PATCH 3/6] test: introduce swim packet filter by destination address Konstantin Osipov 2019-04-24 14:36 ` [tarantool-patches] [PATCH 4/6] swim: wrap sio_strfaddr() Vladislav Shpilevoy 2019-04-24 16:40 ` [tarantool-patches] " Konstantin Osipov 2019-04-24 20:23 ` Vladislav Shpilevoy 2019-04-25 10:34 ` Konstantin Osipov 2019-04-25 13:50 ` Vladislav Shpilevoy 2019-04-24 14:36 ` [tarantool-patches] [PATCH 5/6] swim: introduce routing Vladislav Shpilevoy 2019-04-24 16:46 ` [tarantool-patches] " Konstantin Osipov 2019-04-24 20:25 ` Vladislav Shpilevoy 2019-04-25 10:39 ` Konstantin Osipov 2019-04-25 13:50 ` Vladislav Shpilevoy 2019-04-25 13:57 ` Konstantin Osipov 2019-04-24 14:36 ` [tarantool-patches] [PATCH 6/6] swim: introduce suspicion Vladislav Shpilevoy 2019-04-24 17:01 ` [tarantool-patches] " Konstantin Osipov 2019-04-24 20:28 ` Vladislav Shpilevoy 2019-04-25 10:42 ` Konstantin Osipov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=d71d08ba37fe427f6f8a309899410984a30b06fa.1556116199.git.v.shpilevoy@tarantool.org \ --to=v.shpilevoy@tarantool.org \ --cc=kostja@tarantool.org \ --cc=tarantool-patches@freelists.org \ --subject='Re: [tarantool-patches] [PATCH 3/6] test: introduce swim packet filter by destination address' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox