From b5192f487fd4e06ca5dd0f4b16e6653431628aa5 Mon Sep 17 00:00:00 2001 From: Brijitha1609 Date: Sun, 1 Dec 2024 22:23:04 -0600 Subject: [PATCH 1/2] Added HTTP parser example using DPDK --- examples/http-parser/Makefile | 19 ++++++ examples/http-parser/main | Bin 0 -> 34184 bytes examples/http-parser/main.c | 105 ++++++++++++++++++++++++++++++ examples/http-parser/meson.build | 7 ++ examples/http-parser/test-http.js | 45 +++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 examples/http-parser/Makefile create mode 100755 examples/http-parser/main create mode 100644 examples/http-parser/main.c create mode 100644 examples/http-parser/meson.build create mode 100644 examples/http-parser/test-http.js diff --git a/examples/http-parser/Makefile b/examples/http-parser/Makefile new file mode 100644 index 00000000000..1c67a176c01 --- /dev/null +++ b/examples/http-parser/Makefile @@ -0,0 +1,19 @@ +# Define compiler and flags +CC = gcc +CFLAGS += -O3 -g +LDFLAGS += -L$(RTE_LIBRTE_PMD) -lrte_pmd + +# Define the executable +EXE = http-parser + +# Source file +SRC = main.c + +# Build target +all: $(EXE) + +$(EXE): $(SRC) + $(CC) $(CFLAGS) -o $@ $(SRC) $(LDFLAGS) + +clean: + rm -f $(EXE) diff --git a/examples/http-parser/main b/examples/http-parser/main new file mode 100755 index 0000000000000000000000000000000000000000..bebf075b4724a8e60f6a5ed09c3dc2329e9caaf2 GIT binary patch literal 34184 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 YG556n=9@nq?R#SJAI6@0xz~a99}<@Nl>h($ literal 0 HcmV?d00001 diff --git a/examples/http-parser/main.c b/examples/http-parser/main.c new file mode 100644 index 00000000000..7efcb4a01dd --- /dev/null +++ b/examples/http-parser/main.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include +#include +#include // Correct header for macOS + +// Function to handle the captured packet +void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) { + // Ethernet header + struct ether_header *eth_header = (struct ether_header*) packet; + + // Check if the packet is an IP packet (Ethernet Type is 0x0800 for IP) + if (ntohs(eth_header->ether_type) != ETHERTYPE_IP) { + printf("Not an IP packet\n"); + return; + } + + // IP header + struct ip *ip_header = (struct ip*)(packet + sizeof(struct ether_header)); + + // Check if the packet is a TCP packet (IP protocol number 6 for TCP) + if (ip_header->ip_p != IPPROTO_TCP) { + printf("Not a TCP packet\n"); + return; + } + + // TCP header + struct tcphdr *tcp_header = (struct tcphdr*)(packet + sizeof(struct ether_header) + sizeof(struct ip)); + + // Source and destination IP addresses + char src_ip[INET_ADDRSTRLEN]; + char dst_ip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(ip_header->ip_dst), dst_ip, INET_ADDRSTRLEN); + + // Source and destination TCP ports + uint16_t src_port = ntohs(tcp_header->th_sport); + uint16_t dst_port = ntohs(tcp_header->th_dport); + + // Display basic info about the packet + printf("Captured packet from IP: %s to IP: %s\n", src_ip, dst_ip); + printf("TCP Src Port: %d, Dst Port: %d\n", src_port, dst_port); + + // If it's an HTTP packet (we assume port 80 for HTTP) + if (dst_port == 80 || src_port == 80) { + printf("This is an HTTP packet!\n"); + + // Optionally, parse the TCP payload for HTTP content + const u_char *http_payload = packet + sizeof(struct ether_header) + sizeof(struct ip) + sizeof(struct tcphdr); + int payload_len = header->len - (http_payload - packet); + + // Try to print first few bytes of the HTTP message (for example) + printf("HTTP Payload (First 50 bytes):\n"); + for (int i = 0; i < 50 && i < payload_len; i++) { + printf("%c", http_payload[i]); + } + printf("\n\n"); + } +} + +// Main function +int main(int argc, char *argv[]) { + pcap_if_t *alldevs; + pcap_if_t *device; + pcap_t *handle; + char errbuf[PCAP_ERRBUF_SIZE]; + + // Get the list of all devices + if (pcap_findalldevs(&alldevs, errbuf) == -1) { + fprintf(stderr, "Error finding devices: %s\n", errbuf); + return 1; + } + + // Choose the first device for simplicity + device = alldevs; + printf("Using device: %s\n", device->name); + + // Open the device for capturing + handle = pcap_open_live(device->name, BUFSIZ, 1, 1000, errbuf); + if (handle == NULL) { + fprintf(stderr, "Couldn't open device %s: %s\n", device->name, errbuf); + return 2; + } + + // Set a filter to capture only TCP packets on port 80 or 443 (HTTP/HTTPS) + struct bpf_program fp; + if (pcap_compile(handle, &fp, "tcp port 80 or tcp port 443", 0, PCAP_NETMASK_UNKNOWN) == -1) { + fprintf(stderr, "Could not parse filter\n"); + return 2; + } + if (pcap_setfilter(handle, &fp) == -1) { + fprintf(stderr, "Could not install filter\n"); + return 2; + } + + // Start capturing packets (capturing 10 packets for demonstration) + pcap_loop(handle, 10, packet_handler, NULL); + + // Cleanup + pcap_close(handle); + pcap_freealldevs(alldevs); + return 0; +} diff --git a/examples/http-parser/meson.build b/examples/http-parser/meson.build new file mode 100644 index 00000000000..b1609c8dd0a --- /dev/null +++ b/examples/http-parser/meson.build @@ -0,0 +1,7 @@ +project('http-parser', 'c') + +# Find DPDK library +rte_lib = cc.find_library('rte_pmd', dirs: '/usr/local/lib') + +# Define the executable +executable('http-parser', 'main.c', dependencies: rte_lib) diff --git a/examples/http-parser/test-http.js b/examples/http-parser/test-http.js new file mode 100644 index 00000000000..ddff8b885bb --- /dev/null +++ b/examples/http-parser/test-http.js @@ -0,0 +1,45 @@ +const http = require('http'); +const https = require('https'); +const url = require('url'); + +// Create an HTTP server to send test HTTP requests +const sendHttpRequest = (hostname, port, path, method) => { + const options = { + hostname: hostname, + port: port, + path: path, + method: method, + headers: { + 'User-Agent': 'Node.js HTTP Test Client', + 'Content-Type': 'application/json' + } + }; + + const req = http.request(options, (res) => { + console.log(`HTTP Response: ${res.statusCode} ${res.statusMessage}`); + res.on('data', (chunk) => { + console.log(`Body: ${chunk}`); + }); + }); + + req.on('error', (error) => { + console.error(`Error: ${error}`); + }); + + req.end(); +}; + +// Test HTTP requests (adjust the IP and port based on your setup) +const testUrl = 'localhost'; // DPDK application is listening on localhost +const testPort = 80; // Standard HTTP port + +const testRequests = [ + { method: 'GET', path: '/' }, + { method: 'POST', path: '/test' }, + { method: 'GET', path: '/about' }, +]; + +// Send test HTTP requests +testRequests.forEach(({ method, path }) => { + sendHttpRequest(testUrl, testPort, path, method); +}); From bfa923ca14bb1c1f469f1bcf175d88e41c626140 Mon Sep 17 00:00:00 2001 From: Brijitha1609 Date: Sun, 1 Dec 2024 23:28:17 -0600 Subject: [PATCH 2/2] added Readme.md file --- examples/http-parser/README.md | 112 +++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 examples/http-parser/README.md diff --git a/examples/http-parser/README.md b/examples/http-parser/README.md new file mode 100644 index 00000000000..d77ee553b36 --- /dev/null +++ b/examples/http-parser/README.md @@ -0,0 +1,112 @@ +# HTTP Message Parser Example Using DPDK + +This example demonstrates how to use the **DPDK (Data Plane Development Kit)** packet processing API to parse HTTP messages from network packets. The HTTP parser identifies the request type (e.g., GET, POST), extracts headers, and prints the payload from captured packets. + +## Overview + +The goal of this project is to create a working example that utilizes **DPDK**'s packet processing capabilities to capture and parse HTTP messages from network traffic. + +### Key Features: +- Capture network packets using **libpcap**. +- Parse HTTP messages including the method (GET, POST), headers, and payload. +- Use DPDK's packet processing API to efficiently handle network traffic. + +## Prerequisites + +Before you begin, ensure you have the following installed: + +- **DPDK**: A high-performance packet processing library. +- **libpcap**: A library used for capturing network packets. +- **gcc**: A compiler for building C programs. +- **Make**: A tool for managing the build process. + +## Setup Instructions + +### Step 1: Install DPDK + +To use DPDK, you need to set up the environment and install DPDK on your system. + +#### On Linux: + +Follow the official DPDK setup instructions: +[DPDK Installation Guide](https://doc.dpdk.org/guides/linux_gsg/index.html) + +#### On macOS: + +You can use a **Docker** container to run DPDK if it is not supported natively on macOS. + +1. **Clone the Docker repository** and build the DPDK environment. + +2. **Run the Docker container** with DPDK: + ```bash + docker run --rm -it --privileged dpdk-docker + ``` + +### Step 2: Install libpcap + +You will need `libpcap` to capture network packets. + +#### On Ubuntu/Debian-based systems: +```bash +sudo apt-get install libpcap-dev +``` + +#### On macOS (using Homebrew): +```bash +brew install libpcap +``` + +### Step 3: Clone the Repository + +Clone the repository containing the HTTP parser example: + +```bash +git clone https://github.com/Brijitha1609/dpdk.git +cd dpdk +``` + +### Step 4: Build the Project + +1. **Install dependencies** (on Linux-based systems): + ```bash + sudo apt-get update + sudo apt-get install build-essential libnuma-dev meson ninja-build + ``` + +2. **Compile the program**: + ```bash + make + ``` + + Alternatively, if you are using `meson`: + ```bash + meson build + ninja -C build + ``` + +### Step 5: Run the HTTP Parser + +1. **Prepare your network interface** to capture packets (you may need root privileges). + +2. **Run the HTTP parser**: + ```bash + sudo ./main + ``` + + The program will start capturing network packets from the network interface (default `en0` in the code) and parse HTTP messages from the captured packets. + + Example output: + ``` + Using device: en0 + HTTP Method: GET + Headers: + Host: example.com + User-Agent: curl/7.64.1 + Payload: + ``` + +## Troubleshooting + +- **Permission Issues**: Ensure you have permission to capture packets on the network interface. You may need to run the program as `sudo` or grant your user the necessary permissions. +- **DPDK Environment Errors**: Ensure that the environment variables (`RTE_SDK`, `RTE_TARGET`) are correctly configured. Follow the DPDK setup guide for more details. +