00001 //--------------------------------------------------------------------------
00002 // Copyright (C) 2016-2017 Cisco and/or its affiliates. All rights reserved.
00003 //
00004 // This program is free software; you can redistribute it and/or modify it
00005 // under the terms of the GNU General Public License Version 2 as published
00006 // by the Free Software Foundation. You may not use, modify or distribute
00007 // this program under any other version of the GNU General Public License.
00008 //
00009 // This program is distributed in the hope that it will be useful, but
00010 // WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program; if not, write to the Free Software Foundation, Inc.,
00016 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017 //--------------------------------------------------------------------------
00018
00019 // regex_offload.cc author Russ Combs <rucombs@cisco.com>
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024
00025 #include "regex_offload.h"
00026
00027 #include <assert.h>
00028
00029 #include <atomic>
00030 #include <chrono>
00031 #include <condition_variable>
00032 #include <mutex>
00033 #include <vector>
00034 #include <thread>
00035
00036 #include "main/snort_config.h"
00037 #include "fp_detect.h"
00038 #include "ips_context.h"
00039
00040 struct RegexRequest
00041 {
00042 Packet* packet = nullptr;
00043
00044 std::thread* thread;
00045 std::mutex mutex;
00046 std::condition_variable cond;
00047
00048 std::atomic<bool> offload { false };
00049
00050 unsigned id = 0;
00051 bool go = true;
00052 };
00053
00054 //--------------------------------------------------------------------------
00055 // regex offload implementation
00056 //--------------------------------------------------------------------------
00057
00058 RegexOffload::RegexOffload(unsigned max)
00059 {
00060 for ( unsigned i = 0; i < max; ++i )
00061 {
00062 RegexRequest* req = new RegexRequest;
00063 req->thread = new std::thread(worker, req);
00064 idle.push_back(req);
00065 }
00066 }
00067
00068 RegexOffload::~RegexOffload()
00069 {
00070 assert(busy.empty());
00071
00072 for ( auto* req : idle )
00073 {
00074 req->thread->join();
00075 delete req->thread;
00076 delete req;
00077 }
00078 }
00079
00080 void RegexOffload::stop()
00081 {
00082 assert(busy.empty());
00083
00084 for ( auto* req : idle )
00085 {
00086 std::unique_lock<std::mutex> lock(req->mutex);
00087 req->go = false;
00088 req->cond.notify_one();
00089 }
00090 }
00091
00092 void RegexOffload::worker(RegexRequest* req)
00093 {
00094 while ( true )
00095 {
00096 {
00097 std::unique_lock<std::mutex> lock(req->mutex);
00098 req->cond.wait_for(lock, std::chrono::seconds(1));
00099
00100 if ( !req->go )
00101 break;
00102
00103 if ( !req->offload )
00104 continue;
00105 }
00106
00107 assert(req->packet);
00108 assert(req->packet->flow->is_offloaded());
00109
00110 snort_conf = req->packet->context->conf; // FIXIT-H reload issue
00111 fp_offload(req->packet);
00112
00113 req->offload = false;
00114 }
00115 }
00116
00117 void RegexOffload::put(unsigned id, Packet* p)
00118 {
00119 assert(p);
00120 assert(!idle.empty());
00121
00122 RegexRequest* req = idle.front();
00123
00124 idle.pop_front(); // FIXIT-H use splice to move instead
00125 busy.push_back(req);
00126
00127 std::unique_lock<std::mutex> lock(req->mutex);
00128
00129 req->id = id;
00130 req->packet = p;
00131 req->offload = true;
00132
00133 req->cond.notify_one();
00134 }
00135
00136 bool RegexOffload::get(unsigned& id)
00137 {
00138 assert(!busy.empty());
00139 RegexRequest* req = busy.front(); // FIXIT-H onload any order
00140
00141 if ( req->offload )
00142 return false;
00143
00144 id = req->id;
00145 req->packet = nullptr;
00146
00147 busy.pop_front(); // FIXIT-H use splice to move instead
00148 idle.push_back(req);
00149
00150 return true;
00151 }
00152
00153 bool RegexOffload::on_hold(Flow* f)
00154 {
00155 for ( auto* req : busy )
00156 {
00157 if ( req->packet->flow == f )
00158 return true;
00159 }
00160 return false;
00161 }
00162
END OF CODE