From patchwork Wed Jan 7 16:47:23 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 426311 X-Patchwork-Delegate: shemminger@vyatta.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id C571414007F for ; Thu, 8 Jan 2015 03:47:34 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754561AbbAGQr3 (ORCPT ); Wed, 7 Jan 2015 11:47:29 -0500 Received: from mail-we0-f171.google.com ([74.125.82.171]:42561 "EHLO mail-we0-f171.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754314AbbAGQr1 (ORCPT ); Wed, 7 Jan 2015 11:47:27 -0500 Received: by mail-we0-f171.google.com with SMTP id u56so1540841wes.2 for ; Wed, 07 Jan 2015 08:47:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=3SmFkhsDhDvM1wIEOHUV2hD3OXiON6zpwiwvrbYsaU8=; b=cax3XonIwqDKpA7lpx+0k4E4iKM95EusKndj2aJHP3kNw7qMJsaxa3Rvy5afscGLDn 2jtPOylmboXguSvM7EqAaS80Yt6CmSsc4WPWBWh3T6MiZOx1STF+R5BUYWthFZGKzqCA 57PNL8XVL1XeiRZpVA9TvEYovsG62GdMsc1yrrG9luYxrNGWpV5YWlvdP2mmnr17hhKa HESBVe1bhNaTp45CmfxuQy5RpmpT2IWglJdYcny82pTv8A5xFcQs/hBT+fPo8IqF+2GI 4xVBR4uVl/XSiAWKM6ZGN8liIMlMghELBI9+kxL6PMkqkyuU/y7CKd1lE20AWSXNHwVL WTPg== X-Gm-Message-State: ALoCoQn3fd5NZgJyzRTV8zU9+W1DjrWp75Lp3WHr2r8FPs4hfmZ2/aLfB6BaASbZuxze7kipNOzK X-Received: by 10.194.5.37 with SMTP id p5mr8592047wjp.20.1420649246265; Wed, 07 Jan 2015 08:47:26 -0800 (PST) Received: from localhost (ip-94-113-122-192.net.upcbroadband.cz. [94.113.122.192]) by mx.google.com with ESMTPSA id js5sm18495947wid.11.2015.01.07.08.47.25 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 07 Jan 2015 08:47:25 -0800 (PST) From: Jiri Pirko To: netdev@vger.kernel.org Cc: davem@davemloft.net, jhs@mojatatu.com, stephen@networkplumber.org Subject: [patch iproute2 1/2] tc: push bpf common code into separate file Date: Wed, 7 Jan 2015 17:47:23 +0100 Message-Id: <1420649244-9574-1-git-send-email-jiri@resnulli.us> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1420649035-9522-1-git-send-email-jiri@resnulli.us> References: <1420649035-9522-1-git-send-email-jiri@resnulli.us> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Signed-off-by: Jiri Pirko --- tc/Makefile | 2 +- tc/f_bpf.c | 136 +++++-------------------------------------------------- tc/tc_bpf.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tc/tc_bpf.h | 28 ++++++++++++ 4 files changed, 186 insertions(+), 126 deletions(-) create mode 100644 tc/tc_bpf.c create mode 100644 tc/tc_bpf.h diff --git a/tc/Makefile b/tc/Makefile index 830c97d..45304a1 100644 --- a/tc/Makefile +++ b/tc/Makefile @@ -1,5 +1,5 @@ TCOBJ= tc.o tc_qdisc.o tc_class.o tc_filter.o tc_util.o \ - tc_monitor.o m_police.o m_estimator.o m_action.o \ + tc_monitor.o tc_bpf.o m_police.o m_estimator.o m_action.o \ m_ematch.o emp_ematch.yacc.o emp_ematch.lex.o include ../Config diff --git a/tc/f_bpf.c b/tc/f_bpf.c index 48635a7..e2af94e 100644 --- a/tc/f_bpf.c +++ b/tc/f_bpf.c @@ -26,6 +26,7 @@ #include "utils.h" #include "tc_util.h" +#include "tc_bpf.h" static void explain(void) { @@ -44,130 +45,6 @@ static void explain(void) fprintf(stderr, "NOTE: CLASSID is parsed as hexadecimal input.\n"); } -static int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, - char **bpf_string, bool *need_release, - const char separator) -{ - char sp; - - if (from_file) { - size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,"); - char *tmp_string; - FILE *fp; - - tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len; - tmp_string = malloc(tmp_len); - if (tmp_string == NULL) - return -ENOMEM; - - memset(tmp_string, 0, tmp_len); - - fp = fopen(arg, "r"); - if (fp == NULL) { - perror("Cannot fopen"); - free(tmp_string); - return -ENOENT; - } - - if (!fgets(tmp_string, tmp_len, fp)) { - free(tmp_string); - fclose(fp); - return -EIO; - } - - fclose(fp); - - *need_release = true; - *bpf_string = tmp_string; - } else { - *need_release = false; - *bpf_string = arg; - } - - if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 || - sp != separator) { - if (*need_release) - free(*bpf_string); - return -EINVAL; - } - - return 0; -} - -static int bpf_parse_ops(int argc, char **argv, struct nlmsghdr *n, - bool from_file) -{ - char *bpf_string, *token, separator = ','; - struct sock_filter bpf_ops[BPF_MAXINSNS]; - int ret = 0, i = 0; - bool need_release; - __u16 bpf_len = 0; - - if (argc < 1) - return -EINVAL; - if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string, - &need_release, separator)) - return -EINVAL; - if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) { - ret = -EINVAL; - goto out; - } - - token = bpf_string; - while ((token = strchr(token, separator)) && (++token)[0]) { - if (i >= bpf_len) { - fprintf(stderr, "Real program length exceeds encoded " - "length parameter!\n"); - ret = -EINVAL; - goto out; - } - - if (sscanf(token, "%hu %hhu %hhu %u,", - &bpf_ops[i].code, &bpf_ops[i].jt, - &bpf_ops[i].jf, &bpf_ops[i].k) != 4) { - fprintf(stderr, "Error at instruction %d!\n", i); - ret = -EINVAL; - goto out; - } - - i++; - } - - if (i != bpf_len) { - fprintf(stderr, "Parsed program length is less than encoded" - "length parameter!\n"); - ret = -EINVAL; - goto out; - } - - addattr_l(n, MAX_MSG, TCA_BPF_OPS_LEN, &bpf_len, sizeof(bpf_len)); - addattr_l(n, MAX_MSG, TCA_BPF_OPS, &bpf_ops, - bpf_len * sizeof(struct sock_filter)); -out: - if (need_release) - free(bpf_string); - - return ret; -} - -static void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len) -{ - struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops); - int i; - - if (len == 0) - return; - - fprintf(f, "bytecode \'%u,", len); - - for (i = 0; i < len - 1; i++) - fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt, - ops[i].jf, ops[i].k); - - fprintf(f, "%hu %hhu %hhu %u\'\n", ops[i].code, ops[i].jt, - ops[i].jf, ops[i].k); -} - static int bpf_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) { @@ -195,6 +72,10 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle, while (argc > 0) { if (matches(*argv, "run") == 0) { bool from_file; + struct sock_filter bpf_ops[BPF_MAXINSNS]; + __u16 bpf_len; + int ret; + NEXT_ARG(); if (strcmp(*argv, "bytecode-file") == 0) { from_file = true; @@ -206,10 +87,15 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle, return -1; } NEXT_ARG(); - if (bpf_parse_ops(argc, argv, n, from_file)) { + ret = bpf_parse_ops(argc, argv, bpf_ops, from_file); + if (ret < 0) { fprintf(stderr, "Illegal \"bytecode\"\n"); return -1; } + bpf_len = ret; + addattr16(n, MAX_MSG, TCA_BPF_OPS_LEN, bpf_len); + addattr_l(n, MAX_MSG, TCA_BPF_OPS, &bpf_ops, + bpf_len * sizeof(struct sock_filter)); } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { unsigned handle; diff --git a/tc/tc_bpf.c b/tc/tc_bpf.c new file mode 100644 index 0000000..c6901d6 --- /dev/null +++ b/tc/tc_bpf.c @@ -0,0 +1,146 @@ +/* + * tc_bpf.c BPF common code + * + * This program is free software; you can distribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Daniel Borkmann + * Jiri Pirko + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "utils.h" +#include "tc_util.h" +#include "tc_bpf.h" + +int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, + char **bpf_string, bool *need_release, + const char separator) +{ + char sp; + + if (from_file) { + size_t tmp_len, op_len = sizeof("65535 255 255 4294967295,"); + char *tmp_string; + FILE *fp; + + tmp_len = sizeof("4096,") + BPF_MAXINSNS * op_len; + tmp_string = malloc(tmp_len); + if (tmp_string == NULL) + return -ENOMEM; + + memset(tmp_string, 0, tmp_len); + + fp = fopen(arg, "r"); + if (fp == NULL) { + perror("Cannot fopen"); + free(tmp_string); + return -ENOENT; + } + + if (!fgets(tmp_string, tmp_len, fp)) { + free(tmp_string); + fclose(fp); + return -EIO; + } + + fclose(fp); + + *need_release = true; + *bpf_string = tmp_string; + } else { + *need_release = false; + *bpf_string = arg; + } + + if (sscanf(*bpf_string, "%hu%c", bpf_len, &sp) != 2 || + sp != separator) { + if (*need_release) + free(*bpf_string); + return -EINVAL; + } + + return 0; +} + +int bpf_parse_ops(int argc, char **argv, struct sock_filter *bpf_ops, + bool from_file) +{ + char *bpf_string, *token, separator = ','; + int ret = 0, i = 0; + bool need_release; + __u16 bpf_len = 0; + + if (argc < 1) + return -EINVAL; + if (bpf_parse_string(argv[0], from_file, &bpf_len, &bpf_string, + &need_release, separator)) + return -EINVAL; + if (bpf_len == 0 || bpf_len > BPF_MAXINSNS) { + ret = -EINVAL; + goto out; + } + + token = bpf_string; + while ((token = strchr(token, separator)) && (++token)[0]) { + if (i >= bpf_len) { + fprintf(stderr, "Real program length exceeds encoded " + "length parameter!\n"); + ret = -EINVAL; + goto out; + } + + if (sscanf(token, "%hu %hhu %hhu %u,", + &bpf_ops[i].code, &bpf_ops[i].jt, + &bpf_ops[i].jf, &bpf_ops[i].k) != 4) { + fprintf(stderr, "Error at instruction %d!\n", i); + ret = -EINVAL; + goto out; + } + + i++; + } + + if (i != bpf_len) { + fprintf(stderr, "Parsed program length is less than encoded" + "length parameter!\n"); + ret = -EINVAL; + goto out; + } + ret = bpf_len; + +out: + if (need_release) + free(bpf_string); + + return ret; +} + +void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len) +{ + struct sock_filter *ops = (struct sock_filter *) RTA_DATA(bpf_ops); + int i; + + if (len == 0) + return; + + fprintf(f, "bytecode \'%u,", len); + + for (i = 0; i < len - 1; i++) + fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt, + ops[i].jf, ops[i].k); + + fprintf(f, "%hu %hhu %hhu %u\'\n", ops[i].code, ops[i].jt, + ops[i].jf, ops[i].k); +} diff --git a/tc/tc_bpf.h b/tc/tc_bpf.h new file mode 100644 index 0000000..08cca92 --- /dev/null +++ b/tc/tc_bpf.h @@ -0,0 +1,28 @@ +/* + * tc_bpf.h BPF common code + * + * This program is free software; you can distribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Daniel Borkmann + * Jiri Pirko + */ + +#ifndef _TC_BPF_H_ +#define _TC_BPF_H_ 1 + +#include +#include +#include +#include + +int bpf_parse_string(char *arg, bool from_file, __u16 *bpf_len, + char **bpf_string, bool *need_release, + const char separator); +int bpf_parse_ops(int argc, char **argv, struct sock_filter *bpf_ops, + bool from_file); +void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len); + +#endif