# ONVM-IPS / Hyperscan
{%hackmd theme-dark %}
## DPDK
* GitHub-[DPDK](https://github.com/DPDK/dpdk)
* GitHub-[Pktgen-DPDK](https://github.com/pktgen/Pktgen-DPDK)

## OpenNetVM
* GitHub-[openNetVM](https://github.com/sdnfv/openNetVM)

## Hyperscan
* GitHub-[hyperscan](https://github.com/intel/hyperscan)

**Figure 1:** Hyperscan compilation process

**Figure 2:** Hyperscan run-time

**Figure 3:** Data scattered in different units in time order
## Snort3
* GitHub-[snort3](https://github.com/snort3/snort3)

## ONVM-IPS / Hyperscan
### 運行流程

* IPS運行架構如上圖所示
* 首先由 `onvm_nflib` 等 `function` 進行初始化,透過 `DPDK_init` 進行 `DPDK EAL` 環境的建構並執行 `onvm_signal` 與 `manager` 建立連線,這裡的連線指的是由 `manger` 指派的 `core`、`mempool` 等資源的共享。

### 規則解析
* 接著由 `databasesFromFile` 接手,讀取 `Snort Rules` 並將其解析、儲存於對應的結構體當中。

* 如下圖所示,使用右側的 `unordered_map`,將原規則中的變數置換為實體 `IP` 位址,並於載入完成後進行規則的編譯,將 `protocol`、`srcAddr`、`srcPort`、`dstAddr`、`dstPort`,部分相同的規則編譯為對應的字元樹資料庫。

* 編譯完成後,所有 `Snort Rules` 與編譯完成的 `DB` 將會存在如下圖所示的全域變數結構體當中,並等待後續建構時的調用。

:::info
/* ACTION */
`ACTION_ALERT` 0x00
`ACTION_LOG` 0x01
`ACTION_DROP` 0x02
`ACTION_REJECT` 0x03
`ACTION_SDROP` 0x04
/* PROTOCOL */
`IP_PROTOCOL_ICMP` 0x01
`IP_PROTOCOL_OTHER` 0xFF
:::
### Flow建構(nf_setup)
* 接著進入 `nf_setup` 的部分,因為這裡我們採用的 `scaling` 方法是 `Run-to-Completion`,因此每個 `child thread` 都必須根據 `parent` 儲存的全域變數 `RuleHashMap`,建構自己的 `Flow` 解析器。

* 以 `Tcp_parser` 為例
1. 當 `tcp` 封包進入 `parser`,首先以封包內 `srcAddr`、`srcPort`、`dstAddr`、`dstPort`,建構 `FlowTuple` 結構,並檢查 `flow_map`。
2. 若 `key` 不存在則解析規則並記錄於 `flow_map` 中。
3. 將 `flow_map` 中 `value` 與 `steams` 內對應的狀態取出
4. 走訪對應的 `db` 並於匹配時呼叫對應的 `callback fucntion`
:::info
`ProtocolHashMp` *tcp_rules;
`vector<unordered_map<FlowTuple, size_t, FlowTupleHash>>` stream_map;
`hs_scratch_t` **scratch;
`vector<vector<hs_stream_t *>>` streams;
`unordered_map<FlowTuple, vector<int>, FlowTupleHash>` flow_map;
:::

```cpp
const FlowTuple header(ipv4, tcp->src_port, tcp->dst_port);
if (flow_map.find(header) == flow_map.end()) {
int index = 0;
for (it = tcp_rules->begin(); it != tcp_rules->end(); ++it, ++index) {
if (parseRule(it->first, header)) {
flow_map[header].push_back(index);
}
}
}
```
---

```cpp
for (auto &index : flow_map.at(header)) {
it = next(tcp_rules->begin(), index);
stream_map[index].insert(make_pair(header, stream_map[index].size()));
err = hs_scan_stream(streams[index][stream_map[index].size()], payload, length, 0, *scratch, onMatch,
this);
if (err != HS_SUCCESS) {
cerr << "ERROR: Unable to scan tcp packet. Exiting." << endl;
exit(-1);
}
}
```
* 如下圖所示,偵測到對應特徵的封包時,於 log 檔內紀錄其狀態與輸出封包內容。

## Ref
[NFA/DFA](https://www.itread01.com/exhkf.html)