summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xsrc/bp_gtest.cpp2
-rwxr-xr-xsrc/bp_sim.cpp110
-rwxr-xr-xsrc/bp_sim.h42
-rw-r--r--src/flow_stat_parser.h72
-rwxr-xr-xsrc/nat_check.cpp70
-rwxr-xr-xsrc/nat_check.h13
6 files changed, 183 insertions, 126 deletions
diff --git a/src/bp_gtest.cpp b/src/bp_gtest.cpp
index 8de8fa0e..87f3f7ca 100755
--- a/src/bp_gtest.cpp
+++ b/src/bp_gtest.cpp
@@ -2656,7 +2656,7 @@ TEST_F(file_flow_info, load_cap_file_errors) {
po->m_learn_mode = CParserOption::LEARN_MODE_TCP_ACK_NO_SERVER_SEQ_RAND;
// udp in tcp learn mode
- load_cap_file_errors_helper("cap2/dns.pcap", CCapFileFlowInfo::kNoTCPFromServer);
+ load_cap_file_errors_helper("cap2/dns.pcap", CCapFileFlowInfo::kOK);
// no SYN in first packet
load_cap_file_errors_helper("./exp/tcp_no_syn.pcap", CCapFileFlowInfo::kNoSyn);
// TCP flags offset is too big. We don't allow IP option, so can comment this.
diff --git a/src/bp_sim.cpp b/src/bp_sim.cpp
index 080a6b5e..a757cce0 100755
--- a/src/bp_sim.cpp
+++ b/src/bp_sim.cpp
@@ -38,7 +38,6 @@ limitations under the License.
#include <valgrind/callgrind.h>
#endif
-
CPluginCallback * CPluginCallback::callback;
@@ -1776,7 +1775,7 @@ char * CFlowPktInfo::push_ipv4_option_offline(uint8_t bytes){
return (p);
}
-void CFlowPktInfo::mask_as_learn(){
+void CFlowPktInfo::mark_as_learn(){
CNatOption *lpNat;
if ( m_pkt_indication.is_ipv6() ) {
lpNat=(CNatOption *)push_ipv6_option_offline(CNatOption::noOPTION_LEN);
@@ -1940,7 +1939,12 @@ void CCapFileFlowInfo::generate_flow(CTupleTemplateGeneratorSmart * tuple_gen,
// check if flow is two direction
if ( lp->m_pkt_indication.m_desc.IsBiDirectionalFlow() ) {
/* we are in learn mode */
- lpThread->associate(((uint32_t)flow_id) & NAT_FLOW_ID_MASK, node); /* associate flow_id=>node */
+ if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_IP_OPTION) ||
+ node->m_pkt_info->m_pkt_indication.l3.m_ipv4->getProtocol() == IPPROTO_TCP) {
+ lpThread->associate(((uint32_t)flow_id) & NAT_FLOW_ID_MASK_TCP_ACK, node); /* associate flow_id=>node */
+ } else {
+ lpThread->associate(((uint32_t)flow_id) & NAT_FLOW_ID_MASK_IP_ID, node); /* associate flow_id=>node */
+ }
node->set_nat_first_state();
}
}
@@ -2047,6 +2051,8 @@ typedef flow_tmp_map_t::iterator flow_tmp_map_iter_t;
enum CCapFileFlowInfo::load_cap_file_err CCapFileFlowInfo::is_valid_template_load_time(){
int i;
+ bool is_tcp = false;
+
for (i=0; i<Size(); i++) {
CFlowPktInfo * lp= GetPacket((uint32_t)i);
CPacketIndication * lpd=&lp->m_pkt_indication;
@@ -2063,13 +2069,6 @@ enum CCapFileFlowInfo::load_cap_file_err CCapFileFlowInfo::is_valid_template_loa
fprintf(stderr, "Error: Bad CAP file. In learn (NAT) mode, no IP options allowed \n");
return kIPOptionNotAllowed;
}
- if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP)) {
- if (lpd->getIpProto() != IPPROTO_TCP && !lpd->m_desc.IsInitSide()) {
- fprintf(stderr, "Error: In the chosen learn mode, all packets from server to client in CAP file should be TCP.\n");
- fprintf(stderr, " Please give different CAP file, or try different --learn-mode\n");
- return kNoTCPFromServer;
- }
- }
}
}
@@ -2081,7 +2080,8 @@ enum CCapFileFlowInfo::load_cap_file_err CCapFileFlowInfo::is_valid_template_loa
return kPlugInWithLearn;
}
- if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP)) {
+ if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP) && (pkt_0_indication.getIpProto() == IPPROTO_TCP)) {
+ is_tcp = true;
if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP_ACK)) {
if (Size() < 3) {
fprintf(stderr
@@ -2113,7 +2113,7 @@ enum CCapFileFlowInfo::load_cap_file_err CCapFileFlowInfo::is_valid_template_loa
fprintf(stderr, " Please give different CAP file, or try different --learn-mode\n");
return kTCPOffsetTooBig;
}
- if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP_ACK)) {
+ if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP_ACK) && is_tcp) {
// To support TCP seq randomization from server to client, we need second packet in flow to be the server SYN+ACK
bool error = false;
if (pkt_1_indication.getIpProto() != IPPROTO_TCP) {
@@ -2229,7 +2229,9 @@ void CCapFileFlowInfo::update_info(CFlowYamlInfo * flow_info){
lp->m_pkt_indication.m_desc.SetBiPluginEnable(true);
}
-
+ if (CGlobalInfo::is_learn_mode()) {
+ lp->m_pkt_indication.setIpIdNat(false);
+ }
lpCurPacket->SetMaxPkts(lpFlow->m_per_dir[dir].m_pkt_id);
lp->m_pkt_indication.m_desc.SetMaxPktsPerFlow(lpFlow->m_max_pkts);
lp->m_pkt_indication.m_desc.SetMaxFlowTimeout(lpFlow->m_max_aging_sec);
@@ -2257,17 +2259,24 @@ void CCapFileFlowInfo::update_info(CFlowYamlInfo * flow_info){
if ( CGlobalInfo::is_learn_mode() ) {
CFlowPktInfo * lp= GetPacket(0);
assert(lp);
- /* only for bi directionl traffic mask the learn flag , only for the first packet */
+ /* only for bi directionl traffic, first packet, put learn flag */
if ( lp->m_pkt_indication.m_desc.IsBiDirectionalFlow() ){
- lp->mask_as_learn();
+ lp->m_pkt_indication.setTTL(TTL_RESERVE_DUPLICATE);
+ lp->m_pkt_indication.setTOSReserve();
+ lp->mark_as_learn();
+ lp->m_pkt_indication.setIpIdNat(true);
}
if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP_ACK)) {
- // In this mode, we need to see the SYN+ACK as well.
- lp = GetPacket(1);
- assert(lp);
- lp->m_pkt_indication.setTTL(TTL_RESERVE_DUPLICATE);
- lp->m_pkt_indication.setTOSReserve();
+ if (Size() > 1) {
+ // In this mode, we need to see the SYN+ACK as well.
+ lp = GetPacket(1);
+ assert(lp);
+ if (lp->m_pkt_indication.getIpProto() == IPPROTO_TCP) {
+ lp->m_pkt_indication.setTTL(TTL_RESERVE_DUPLICATE);
+ lp->m_pkt_indication.setTOSReserve();
+ }
+ }
}
}
@@ -3743,23 +3752,23 @@ inline bool CNodeGenerator::handle_stl_node(CGenNode * node,
#define unsafe_container_of(var,ptr, type, member) \
- ((type *) ((uint8_t *)(ptr) - offsetof(type, member)))
+ ((type *) ((uint8_t *)(ptr) - offsetof(type, member)))
-/*TEARDOWN is true for stateful in second phase we wait for all the flow to finish
-with --nc there is no TEARDOWN
+/*TEARDOWN is true for stateful in second phase we wait for all the flow to finish
+with --nc there is no TEARDOWN
first phase ==> TEARDOWN =false
last phase ==> TEARDOWN =true
-this is relevant for repeatable flows
+this is relevant for repeatable flows
*/
template<bool TEARDOWN>
inline void CFlowGenListPerThread::on_flow_tick(CGenNode *node){
#ifdef TREX_SIM
- node->m_time=m_cur_time_sec;
+ node->m_time=m_cur_time_sec;
#endif
#ifdef _DEBUG
m_node_gen.update_stats(node);
@@ -3769,7 +3778,7 @@ inline void CFlowGenListPerThread::on_flow_tick(CGenNode *node){
if ( likely (!node->is_repeat_flow()) ) {
if ( likely (!node->is_last_in_flow()) ) {
m_tw.timer_start(&node->m_tmr,node->update_next_pkt_in_flow_tw() );
- }else{
+ }else{
free_last_flow_node( node);
}
}else{
@@ -3778,11 +3787,11 @@ inline void CFlowGenListPerThread::on_flow_tick(CGenNode *node){
if ( TEARDOWN == false ){
node->m_time=m_cur_time_sec; /* update the node time as we schedule it */
- reschedule_flow(node);
+ reschedule_flow(node);
}else{
free_last_flow_node( node);
}
-
+
}else{
m_tw.timer_start(&node->m_tmr,node->update_next_pkt_in_flow_tw() );
}
@@ -3794,7 +3803,7 @@ inline void CFlowGenListPerThread::on_flow_tick(CGenNode *node){
# define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
# define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
#define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \
- GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x))
+ GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x))
#define GCC_DIAG_ON() GCC_DIAG_PRAGMA(pop)
#define UNSAFE_CONTAINER_OF_PUSH GCC_DIAG_OFF(invalid-offsetof)
@@ -3882,9 +3891,9 @@ inline bool CNodeGenerator::do_work_both(CGenNode * node,
m_p_queue.pop();
if ( ON_TERMINATE == false) {
thread->m_cur_time_sec = node->m_time ;
-
+
thread->generate_flows_roundrobin(&done);
-
+
if (!done) {
node->m_time +=d_time;
m_p_queue.push(node);
@@ -3894,7 +3903,7 @@ inline bool CNodeGenerator::do_work_both(CGenNode * node,
}else{
thread->free_node(node);
}
-
+
}else{
exit_scheduler = handle_slow_messages(type,node,thread,ON_TERMINATE);
}
@@ -4072,14 +4081,14 @@ FORCE_NO_INLINE void CNodeGenerator::handle_slow_operations(sch_state_t &state,
}
/**
- * when time is streched - the flow_sync node
- * might be postpond too much
- * this can result a watchdog crash and lack
- * of responsivness from the DP core
- * (no handling of messages)
- *
+ * when time is streched - the flow_sync node
+ * might be postpond too much
+ * this can result a watchdog crash and lack
+ * of responsivness from the DP core
+ * (no handling of messages)
+ *
* @author imarom (7/31/2016)
- *
+ *
*/
void CNodeGenerator::handle_time_strech(CGenNode * &node,
dsec_t &cur_time,
@@ -4212,7 +4221,7 @@ void CNodeGenerator::handle_flow_pkt(CGenNode *node, CFlowGenListPerThread *thre
void CNodeGenerator::handle_flow_sync(CGenNode *node, CFlowGenListPerThread *thread, bool &exit_scheduler) {
-
+
/* flow sync message is a sync point for time */
thread->m_cur_time_sec = node->m_time;
@@ -4240,7 +4249,7 @@ CNodeGenerator::handle_maintenance(CFlowGenListPerThread *thread) {
/* tickle and check messages */
thread->tickle();
thread->check_msgs();
-
+
m_v_if->flush_tx_queue(); /* flush pkt each timeout */
/* save last sync time as realtime */
@@ -4495,7 +4504,13 @@ void CFlowGenListPerThread::terminate_nat_flows(CGenNode *p){
} else {
m_stats.m_nat_lookup_wait_ack_state++;
}
- m_flow_id_to_node_lookup.remove_no_lookup(p->get_short_fid());
+
+ if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_IP_OPTION) ||
+ p->m_pkt_info->m_pkt_indication.l3.m_ipv4->getProtocol() == IPPROTO_TCP) {
+ m_flow_id_to_node_lookup.remove_no_lookup(p->get_short_fid() & NAT_FLOW_ID_MASK_TCP_ACK);
+ } else {
+ m_flow_id_to_node_lookup.remove_no_lookup(p->get_short_fid() & NAT_FLOW_ID_MASK_IP_ID);
+ }
free_last_flow_node( p);
}
@@ -4516,7 +4531,7 @@ void CFlowGenListPerThread::handle_latency_pkt_msg(CGenNodeLatencyPktInfo * msg)
latency_header * h = (latency_header *)(p+msg->m_latency_offset);
h->time_stamp = os_get_hr_tick_64();
}
-
+
m_node_gen.m_v_if->send_one_pkt((pkt_dir_t)msg->m_dir,msg->m_pkt);
}
@@ -4541,7 +4556,8 @@ void CFlowGenListPerThread::handle_nat_msg(CGenNodeNatInfo * msg){
// Calculate diff between tcp seq of SYN packet, and TCP ack of SYN+ACK packet
// For supporting firewalls who do TCP seq num randomization
- if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP)) {
+ if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP) &&
+ (node->m_pkt_info->m_pkt_indication.getIpProto() == IPPROTO_TCP)) {
if (node->is_nat_wait_state()) {
char *syn_pkt = node->m_flow_info->GetPacket(0)->m_packet->raw;
TCPHeader *tcp = (TCPHeader *)(syn_pkt + node->m_pkt_info->m_pkt_indication.getFastTcpOffset());
@@ -4628,14 +4644,14 @@ bool CFlowGenListPerThread::check_msgs_from_rx() {
CGlobalInfo::free_node(node);
}
-
+
return true;
}
bool CFlowGenListPerThread::check_msgs() {
bool had_msg = false;
-
+
/* inlined for performance */
if (m_stateless_dp_info.periodic_check_for_cp_messages()) {
had_msg = true;
@@ -4644,7 +4660,7 @@ bool CFlowGenListPerThread::check_msgs() {
if (check_msgs_from_rx()) {
had_msg = true;
}
-
+
return had_msg;
}
diff --git a/src/bp_sim.h b/src/bp_sim.h
index fe8f55ac..e8a37f6f 100755
--- a/src/bp_sim.h
+++ b/src/bp_sim.h
@@ -78,7 +78,6 @@ class CGenNodePCAP;
/* reserve both 0xFF and 0xFE , router will -1 FF */
#define TTL_RESERVE_DUPLICATE 0xff
#define TOS_TTL_RESERVE_DUPLICATE 0x1
-
/*
* Length of string needed to hold the largest port (16-bit) address
*/
@@ -1687,7 +1686,7 @@ public:
public:
inline uint32_t get_short_fid(void){
- return (((uint32_t)m_flow_id) & NAT_FLOW_ID_MASK);
+ return (((uint32_t)m_flow_id) & NAT_FLOW_ID_MASK_TCP_ACK);
}
inline uint8_t get_thread_id(void){
@@ -2681,6 +2680,17 @@ public:
}
}
+ // if is_nat is true, turn on MSB of IP_ID, else turn it off
+ void setIpIdNat(bool is_nat) {
+ BP_ASSERT(l3.m_ipv4);
+ if (! is_ipv6()) {
+ if (is_nat) {
+ l3.m_ipv4->setId(l3.m_ipv4->getId() | 0x8000);
+ } else {
+ l3.m_ipv4->setId(l3.m_ipv4->getId() & 0x7fff);
+ }
+ }
+ }
void setTOSReserve(){
BP_ASSERT(l3.m_ipv4);
@@ -2909,10 +2919,10 @@ public:
* mark this packet as learn packet
* should
* 1. push ipv4 option ( 8 bytes)
- * 2. mask the packet as learn
+ * 2. mark the packet as learn
* 3. update the option pointer
*/
- void mask_as_learn();
+ void mark_as_learn();
private:
inline void append_big_mbuf(rte_mbuf_t * m,
@@ -3038,11 +3048,6 @@ inline void CFlowPktInfo::update_pkt_info(char *p,
IPHeader * ipv4=
(IPHeader *)(p + m_pkt_indication.getFastIpOffsetFast());
- EthernetHeader * et =
- (EthernetHeader * )(p + m_pkt_indication.getFastEtherOffset());
-
- (void)et;
-
uint16_t src_port = node->m_src_port;
uint32_t tcp_seq_diff_client = 0;
uint32_t tcp_seq_diff_server = 0;
@@ -3071,19 +3076,15 @@ inline void CFlowPktInfo::update_pkt_info(char *p,
#ifdef NAT_TRACE_
printf(" %.3f : DP : learn packet !\n",now_sec());
#endif
- ipv4->setTimeToLive(TTL_RESERVE_DUPLICATE);
- ipv4->setTOS(ipv4->getTOS()|TOS_TTL_RESERVE_DUPLICATE);
-
-
/* first ipv4 option add the info in case of learn packet, usualy only the first packet */
if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_IP_OPTION)) {
CNatOption *lpNat =(CNatOption *)ipv4->getOption();
lpNat->set_fid(node->get_short_fid());
lpNat->set_thread_id(node->get_thread_id());
} else {
- // This method only work on first TCP SYN
if (ipv4->getProtocol() == IPPROTO_TCP) {
TCPHeader *tcp = (TCPHeader *)(((uint8_t *)ipv4) + ipv4->getHeaderLength());
+ // Put NAT info in first TCP SYN
if (tcp->getSynFlag()) {
tcp->setAckNumber(CNatRxManager::calc_tcp_ack_val(node->get_short_fid(), node->get_thread_id()));
}
@@ -3092,6 +3093,9 @@ inline void CFlowPktInfo::update_pkt_info(char *p,
,now_sec(), node->get_short_fid(), node->get_thread_id(), tcp->getAckNumber()
, tcp->getSeqNumber());
#endif
+ } else {
+ // If protocol is not TCP, put NAT info in IP_ID
+ ipv4->setId(CNatRxManager::calc_ip_id_val(node->get_short_fid(), node->get_thread_id()));
}
}
}
@@ -3121,7 +3125,6 @@ inline void CFlowPktInfo::update_pkt_info(char *p,
ipv4->updateIpDst(node->get_nat_ipv4_addr());
}
- /* TBD remove this */
#ifdef NAT_TRACE_
if (node->m_flags != CGenNode::NODE_FLAGS_LATENCY ) {
if ( m_pkt_indication.m_desc.IsInitSide() ==false ){
@@ -3935,7 +3938,7 @@ private:
private:
FORCE_NO_INLINE void associate(uint32_t fid,CGenNode * node ){
- assert(m_flow_id_to_node_lookup.lookup(fid)==0);
+ assert(m_flow_id_to_node_lookup.lookup(fid)==0);
m_stats.m_nat_lookup_add_flow_id++;
m_flow_id_to_node_lookup.add(fid,node);
}
@@ -4060,13 +4063,6 @@ public:
ClientCfgDB m_client_config_info;
};
-
-
-
-
-
-
-
inline void CFlowGeneratorRecPerThread::generate_flow(CNodeGenerator * gen,
dsec_t time,
uint64_t flow_id,
diff --git a/src/flow_stat_parser.h b/src/flow_stat_parser.h
index df70e4ec..51816e1a 100644
--- a/src/flow_stat_parser.h
+++ b/src/flow_stat_parser.h
@@ -52,24 +52,34 @@ class CFlowStatParser {
uint8_t * get_l4() {return m_l4;}
inline bool IsNatInfoPkt(bool &first) {
- if (!m_ipv4 || (m_l4_proto != IPPROTO_TCP)) {
+ if (! m_ipv4 ) {
return false;
}
- if ((m_l4 + TCP_HEADER_LEN) > (uint8_t *)m_ipv4 + get_pkt_size()) {
- return false;
- }
- // If we are here, relevant fields from tcp header are inside the packet boundaries
- // We want to handle SYN and SYN+ACK packets
- TCPHeader *tcp = (TCPHeader *)m_l4;
- if (! tcp->getSynFlag())
- return false;
- if (! tcp->getAckFlag()) {
- first = true;
+ if (m_l4_proto == IPPROTO_TCP) {
+ if ((m_l4 + TCP_HEADER_LEN) > (uint8_t *)m_ipv4 + get_pkt_size()) {
+ return false;
+ }
+ // If we are here, relevant fields from tcp header are inside the packet boundaries
+ // We want to handle SYN and SYN+ACK packets
+ TCPHeader *tcp = (TCPHeader *)m_l4;
+ if (! tcp->getSynFlag())
+ return false;
+
+ if (! tcp->getAckFlag()) {
+ first = true;
+ } else {
+ first = false;
+ }
+ return true;
} else {
- first = false;
+ if ((m_ipv4->getId() & 0x8000) != 0) {
+ first = true;
+ return true;
+ } else {
+ return false;
+ }
}
- return true;
}
private:
@@ -122,24 +132,34 @@ class CSimplePacketParser {
// first - set to true if this is the first packet of the flow. false otherwise.
// relevant only if return value is true
inline bool IsNatInfoPkt(bool &first) {
- if (!m_ipv4 || (m_protocol != IPPROTO_TCP)) {
+ if (! m_ipv4 ) {
return false;
}
- if (! m_l4 || (m_l4 - rte_pktmbuf_mtod(m_m, uint8_t*) + TCP_HEADER_LEN) > m_m->data_len) {
- return false;
- }
- // If we are here, relevant fields from tcp header are guaranteed to be in first mbuf
- // We want to handle SYN and SYN+ACK packets
- TCPHeader *tcp = (TCPHeader *)m_l4;
- if (! tcp->getSynFlag())
- return false;
- if (! tcp->getAckFlag()) {
- first = true;
+ if (m_ipv4->getProtocol() == IPPROTO_TCP) {
+ if (! m_l4 || (m_l4 - rte_pktmbuf_mtod(m_m, uint8_t*) + TCP_HEADER_LEN) > m_m->data_len) {
+ return false;
+ }
+ // If we are here, relevant fields from tcp header are inside the packet boundaries
+ // We want to handle SYN and SYN+ACK packets
+ TCPHeader *tcp = (TCPHeader *)m_l4;
+ if (! tcp->getSynFlag())
+ return false;
+
+ if (! tcp->getAckFlag()) {
+ first = true;
+ } else {
+ first = false;
+ }
+ return true;
} else {
- first = false;
+ if ((m_ipv4->getId() & 0x8000) != 0) {
+ first = true;
+ return true;
+ } else {
+ return false;
+ }
}
- return true;
}
public:
diff --git a/src/nat_check.cpp b/src/nat_check.cpp
index f3dd93d1..6d92145e 100755
--- a/src/nat_check.cpp
+++ b/src/nat_check.cpp
@@ -18,7 +18,7 @@ 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 for testing devices implementing NAT.
For each flow, we need to learn the NAT translation in order to send server responses.
Algorithm is as described below:
@@ -26,7 +26,8 @@ We send first packet from client, and look at it on other side to see how it was
the server flow with the appropriate change. To keep track of which flow the packet belongs to, we attach to the
first packet of each flow, flow id and thread id (thread handling the flow).
Information attaching method can be chosen be using --learn-mode option.
-The information is attached either in special IP option, or in ACK number of first SYN packet.
+The information is attached either in special IP option, or in ACK number of first SYN packet if protocol is TCP
+and in IP_ID of first flow packet if it is UDP.
*/
#include <stdint.h>
@@ -34,7 +35,6 @@ The information is attached either in special IP option, or in ACK number of fir
#include "nat_check.h"
#include "bp_sim.h"
-
void CGenNodeNatInfo::dump(FILE *fd){
fprintf(fd," msg_type : %d \n",m_msg_type);
@@ -113,7 +113,7 @@ void CNatRxManager::handle_aging(){
}
void CNatRxManager::flush_node(CNatPerThreadInfo * thread_info){
- // try send
+ // try send
int cnt=0;
while (true) {
if ( thread_info->m_ring->Enqueue((CGenNode*)thread_info->m_cur_nat_msg) == 0 ){
@@ -136,7 +136,12 @@ void CNatRxManager::flush_node(CNatPerThreadInfo * thread_info){
void CNatRxManager::get_info_from_tcp_ack(uint32_t tcp_ack, uint32_t &fid, uint8_t &thread_info) {
thread_info = (uint8_t) tcp_ack;
- fid = (tcp_ack >> 8) & NAT_FLOW_ID_MASK;
+ fid = (tcp_ack >> 8) & NAT_FLOW_ID_MASK_TCP_ACK;
+}
+
+void CNatRxManager::get_info_from_ip_id(uint16_t ip_id, uint32_t &fid, uint8_t &thread_info) {
+ thread_info = ((uint8_t) ip_id) & 0x3f;
+ fid = (ip_id >> 6) & NAT_FLOW_ID_MASK_IP_ID;
}
/*
@@ -156,37 +161,50 @@ void CNatRxManager::handle_packet_ipv4(CNatOption *option, IPHeader *ipv4, bool
uint32_t fid=0;
uint32_t tcp_seq;
- /* Extract info from the packet ! */
+
uint32_t ext_ip = ipv4->getSourceIp();
uint8_t proto = ipv4->getProtocol();
- /* must be TCP/UDP this is the only supported proto */
- if (!( (proto==6) || (proto==17) )){
+ TCPHeader *tcp = (TCPHeader *) (((char *)ipv4)+ ipv4->getHeaderLength());
+ UDPHeader *udp = (UDPHeader *) (((char *)ipv4)+ ipv4->getHeaderLength());;
+ uint16_t ext_port;
+
+ switch(proto) {
+ case IPPROTO_TCP:
+ ext_port = tcp->getSourcePort();
+ tcp_seq = tcp->getSeqNumber();
+ break;
+ case IPPROTO_UDP:
+ ext_port = udp->getSourcePort();
+ tcp_seq = 0;
+ break;
+ default:
m_stats.m_err_no_valid_proto++;
return;
}
- /* we support only TCP/UDP so take the source port , post IP header */
- TCPHeader *tcp = (TCPHeader *) (((char *)ipv4)+ ipv4->getHeaderLength());
- uint16_t ext_port = tcp->getSourcePort();
-
- tcp_seq = tcp->getSeqNumber();
if (option) {
- thread_info = get_thread_info(option->get_thread_id());
- fid = option->get_fid();
+ thread_info = get_thread_info(option->get_thread_id());
+ fid = option->get_fid();
} else {
uint8_t thread_id;
if (is_first) {
- uint32_t tcp_ack = tcp->getAckNumber();
- get_info_from_tcp_ack(tcp_ack, fid, thread_id);
- thread_info = get_thread_info(thread_id);
- if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP_ACK)) {
- uint32_t dst_ip = ipv4->getDestIp();
- uint16_t dst_port = tcp->getDestPort();
- uint64_t map_key = (dst_ip << 16) + dst_port;
- double time_stamp = now_sec();
- m_ft.insert(map_key, tcp_ack, time_stamp);
- m_ft.clear_old(time_stamp - 1);
+ if (proto == IPPROTO_TCP) {
+ uint32_t tcp_ack = tcp->getAckNumber();
+ get_info_from_tcp_ack(tcp_ack, fid, thread_id);
+ thread_info = get_thread_info(thread_id);
+ if (CGlobalInfo::is_learn_mode(CParserOption::LEARN_MODE_TCP_ACK)) {
+ uint32_t dst_ip = ipv4->getDestIp();
+ uint16_t dst_port = tcp->getDestPort();
+ uint64_t map_key = (dst_ip << 16) + dst_port;
+ double time_stamp = now_sec();
+ m_ft.insert(map_key, tcp_ack, time_stamp);
+ m_ft.clear_old(time_stamp - 1);
+ }
+ } else {
+ uint16_t ip_id = ipv4->getId();
+ get_info_from_ip_id(ip_id, fid, thread_id);
+ thread_info = get_thread_info(thread_id);
}
} else {
uint32_t val;
@@ -232,7 +250,7 @@ void CNatRxManager::handle_packet_ipv4(CNatOption *option, IPHeader *ipv4, bool
}
msg->m_tcp_seq = tcp_seq;
msg->m_fid = fid;
- msg->m_pad = 0xee;
+ msg->m_pad = 0xee;
if ( node->is_full() ){
flush_node(thread_info);
diff --git a/src/nat_check.h b/src/nat_check.h
index 538cf888..2af0a936 100755
--- a/src/nat_check.h
+++ b/src/nat_check.h
@@ -33,7 +33,8 @@ limitations under the License.
// 2msec timeout
#define MAX_TIME_MSG_IN_QUEUE_SEC ( 0.002 )
-#define NAT_FLOW_ID_MASK 0x00ffffff
+#define NAT_FLOW_ID_MASK_TCP_ACK 0x00ffffff
+#define NAT_FLOW_ID_MASK_IP_ID 0x000001ff
class CNatOption {
public:
@@ -78,8 +79,9 @@ public:
return (u.m_data[2]);
}
+ // Used when doing NAT using IP option
void set_fid(uint32_t fid) {
- u.m_data_uint32[1] = fid & NAT_FLOW_ID_MASK;
+ u.m_data_uint32[1] = fid & NAT_FLOW_ID_MASK_TCP_ACK;
}
uint32_t get_fid() {
@@ -225,9 +227,14 @@ public:
void Dump(FILE *fd);
void DumpShort(FILE *fd);
static inline uint32_t calc_tcp_ack_val(uint32_t fid, uint8_t thread_id) {
- return ((fid & NAT_FLOW_ID_MASK) << 8) | thread_id;
+ return ((fid & NAT_FLOW_ID_MASK_TCP_ACK) << 8) | thread_id;
+ }
+ static inline uint16_t calc_ip_id_val(uint32_t fid, uint8_t thread_id) {
+ // MSB bit == 1 signals this is latency packet
+ return ((fid & NAT_FLOW_ID_MASK_IP_ID) << 6) | (thread_id & 0x3f) | 0x8000;
}
void get_info_from_tcp_ack(uint32_t tcp_ack, uint32_t &fid, uint8_t &thread_id);
+ void get_info_from_ip_id(uint16_t ip_id, uint32_t &fid, uint8_t &thread_id);
private:
CNatPerThreadInfo * get_thread_info(uint8_t thread_id);
void flush_node(CNatPerThreadInfo * thread_info);