|
10 | 10 | */
|
11 | 11 |
|
12 | 12 | #include "qemu/osdep.h"
|
| 13 | +#include "trace.h" |
13 | 14 | #include "net/colo.h"
|
14 | 15 | #include "net/filter.h"
|
15 | 16 | #include "net/net.h"
|
@@ -58,6 +59,93 @@ static int is_tcp_packet(Packet *pkt)
|
58 | 59 | }
|
59 | 60 | }
|
60 | 61 |
|
| 62 | +/* handle tcp packet from primary guest */ |
| 63 | +static int handle_primary_tcp_pkt(NetFilterState *nf, |
| 64 | + Connection *conn, |
| 65 | + Packet *pkt) |
| 66 | +{ |
| 67 | + struct tcphdr *tcp_pkt; |
| 68 | + |
| 69 | + tcp_pkt = (struct tcphdr *)pkt->transport_header; |
| 70 | + if (trace_event_get_state(TRACE_COLO_FILTER_REWRITER_DEBUG)) { |
| 71 | + char *sdebug, *ddebug; |
| 72 | + sdebug = strdup(inet_ntoa(pkt->ip->ip_src)); |
| 73 | + ddebug = strdup(inet_ntoa(pkt->ip->ip_dst)); |
| 74 | + trace_colo_filter_rewriter_pkt_info(__func__, sdebug, ddebug, |
| 75 | + ntohl(tcp_pkt->th_seq), ntohl(tcp_pkt->th_ack), |
| 76 | + tcp_pkt->th_flags); |
| 77 | + trace_colo_filter_rewriter_conn_offset(conn->offset); |
| 78 | + g_free(sdebug); |
| 79 | + g_free(ddebug); |
| 80 | + } |
| 81 | + |
| 82 | + if (((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_SYN)) { |
| 83 | + /* |
| 84 | + * we use this flag update offset func |
| 85 | + * run once in independent tcp connection |
| 86 | + */ |
| 87 | + conn->syn_flag = 1; |
| 88 | + } |
| 89 | + |
| 90 | + if (((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_ACK)) { |
| 91 | + if (conn->syn_flag) { |
| 92 | + /* |
| 93 | + * offset = secondary_seq - primary seq |
| 94 | + * ack packet sent by guest from primary node, |
| 95 | + * so we use th_ack - 1 get primary_seq |
| 96 | + */ |
| 97 | + conn->offset -= (ntohl(tcp_pkt->th_ack) - 1); |
| 98 | + conn->syn_flag = 0; |
| 99 | + } |
| 100 | + /* handle packets to the secondary from the primary */ |
| 101 | + tcp_pkt->th_ack = htonl(ntohl(tcp_pkt->th_ack) + conn->offset); |
| 102 | + |
| 103 | + net_checksum_calculate((uint8_t *)pkt->data, pkt->size); |
| 104 | + } |
| 105 | + |
| 106 | + return 0; |
| 107 | +} |
| 108 | + |
| 109 | +/* handle tcp packet from secondary guest */ |
| 110 | +static int handle_secondary_tcp_pkt(NetFilterState *nf, |
| 111 | + Connection *conn, |
| 112 | + Packet *pkt) |
| 113 | +{ |
| 114 | + struct tcphdr *tcp_pkt; |
| 115 | + |
| 116 | + tcp_pkt = (struct tcphdr *)pkt->transport_header; |
| 117 | + |
| 118 | + if (trace_event_get_state(TRACE_COLO_FILTER_REWRITER_DEBUG)) { |
| 119 | + char *sdebug, *ddebug; |
| 120 | + sdebug = strdup(inet_ntoa(pkt->ip->ip_src)); |
| 121 | + ddebug = strdup(inet_ntoa(pkt->ip->ip_dst)); |
| 122 | + trace_colo_filter_rewriter_pkt_info(__func__, sdebug, ddebug, |
| 123 | + ntohl(tcp_pkt->th_seq), ntohl(tcp_pkt->th_ack), |
| 124 | + tcp_pkt->th_flags); |
| 125 | + trace_colo_filter_rewriter_conn_offset(conn->offset); |
| 126 | + g_free(sdebug); |
| 127 | + g_free(ddebug); |
| 128 | + } |
| 129 | + |
| 130 | + if (((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == (TH_ACK | TH_SYN))) { |
| 131 | + /* |
| 132 | + * save offset = secondary_seq and then |
| 133 | + * in handle_primary_tcp_pkt make offset |
| 134 | + * = secondary_seq - primary_seq |
| 135 | + */ |
| 136 | + conn->offset = ntohl(tcp_pkt->th_seq); |
| 137 | + } |
| 138 | + |
| 139 | + if ((tcp_pkt->th_flags & (TH_ACK | TH_SYN)) == TH_ACK) { |
| 140 | + /* handle packets to the primary from the secondary*/ |
| 141 | + tcp_pkt->th_seq = htonl(ntohl(tcp_pkt->th_seq) - conn->offset); |
| 142 | + |
| 143 | + net_checksum_calculate((uint8_t *)pkt->data, pkt->size); |
| 144 | + } |
| 145 | + |
| 146 | + return 0; |
| 147 | +} |
| 148 | + |
61 | 149 | static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
|
62 | 150 | NetClientState *sender,
|
63 | 151 | unsigned flags,
|
@@ -97,10 +185,30 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf,
|
97 | 185 |
|
98 | 186 | if (sender == nf->netdev) {
|
99 | 187 | /* NET_FILTER_DIRECTION_TX */
|
100 |
| - /* handle_primary_tcp_pkt */ |
| 188 | + if (!handle_primary_tcp_pkt(nf, conn, pkt)) { |
| 189 | + qemu_net_queue_send(s->incoming_queue, sender, 0, |
| 190 | + (const uint8_t *)pkt->data, pkt->size, NULL); |
| 191 | + packet_destroy(pkt, NULL); |
| 192 | + pkt = NULL; |
| 193 | + /* |
| 194 | + * We block the packet here,after rewrite pkt |
| 195 | + * and will send it |
| 196 | + */ |
| 197 | + return 1; |
| 198 | + } |
101 | 199 | } else {
|
102 | 200 | /* NET_FILTER_DIRECTION_RX */
|
103 |
| - /* handle_secondary_tcp_pkt */ |
| 201 | + if (!handle_secondary_tcp_pkt(nf, conn, pkt)) { |
| 202 | + qemu_net_queue_send(s->incoming_queue, sender, 0, |
| 203 | + (const uint8_t *)pkt->data, pkt->size, NULL); |
| 204 | + packet_destroy(pkt, NULL); |
| 205 | + pkt = NULL; |
| 206 | + /* |
| 207 | + * We block the packet here,after rewrite pkt |
| 208 | + * and will send it |
| 209 | + */ |
| 210 | + return 1; |
| 211 | + } |
104 | 212 | }
|
105 | 213 | }
|
106 | 214 |
|
|
0 commit comments