@@ -1098,18 +1098,6 @@ static bpf_filter_func_t bpf_jit_compile(struct bpf_insn *prog, u_int nins,
10981098/* Note: unmatched packets are sent to gate 0 */
10991099#define SNAPLEN 0xffff
11001100
1101- static int compare_filter (const void *filter1, const void *filter2) {
1102- struct filter *f1 = (struct filter *)filter1;
1103- struct filter *f2 = (struct filter *)filter2;
1104-
1105- if (f1->priority > f2->priority )
1106- return -1 ;
1107- else if (f1->priority < f2->priority )
1108- return 1 ;
1109- else
1110- return 0 ;
1111- }
1112-
11131101const Commands BPF ::cmds = {
11141102 {" add" , " BPFArg" , MODULE_CMD_FUNC (&BPF ::CommandAdd), 0 },
11151103 {" clear" , " EmptyArg" , MODULE_CMD_FUNC (&BPF ::CommandClear), 0 }};
@@ -1119,61 +1107,55 @@ CommandResponse BPF::Init(const bess::pb::BPFArg &arg) {
11191107}
11201108
11211109void BPF::DeInit () {
1122- for (int i = 0 ; i < n_filters_; i++ ) {
1110+ for (auto &filter: filters_ ) {
11231111#ifdef __x86_64
1124- munmap (reinterpret_cast <void *>(filters_[i] .func ), filters_[i] .mmap_size );
1112+ munmap (reinterpret_cast <void *>(filter .func ), filter .mmap_size );
11251113#else
1126- pcap_freecode (&(filters_[i] .il_code ) );
1114+ pcap_freecode (&filter .il_code );
11271115#endif
1128- free (filters_[i].exp );
11291116 }
11301117
1131- n_filters_ = 0 ;
1118+ filters_. clear () ;
11321119}
11331120
11341121CommandResponse BPF::CommandAdd (const bess::pb::BPFArg &arg) {
1135- if (n_filters_ + arg.filters_size () > MAX_FILTERS ) {
1136- return CommandFailure (EINVAL , " Too many filters" );
1137- }
1138-
1139- struct filter *filter = &filters_[n_filters_];
1140-
11411122 for (const auto &f : arg.filters ()) {
1142- const char *exp = f.filter ().c_str ();
1143- int64_t gate = f.gate ();
1144- if (gate < 0 || gate >= MAX_GATES ) {
1123+ if (f.gate () < 0 || f.gate () >= MAX_GATES ) {
11451124 return CommandFailure (EINVAL , " Invalid gate" );
11461125 }
1147- filter->priority = f.priority ();
1148- filter->gate = f.gate ();
1149- filter->exp = strdup (exp);
1150- #ifdef __x86_64
1151- struct bpf_program il_code;
1126+
1127+ Filter filter;
1128+ filter.priority = f.priority ();
1129+ filter.gate = f.gate ();
1130+ filter.exp = f.filter ();
1131+
1132+ struct bpf_program il;
11521133 if (pcap_compile_nopcap (SNAPLEN , DLT_EN10MB , // Ethernet
1153- &il_code, exp, 1 , // optimize (IL only)
1134+ &il, filter.exp .c_str (),
1135+ 1 , // optimize (IL only)
11541136 PCAP_NETMASK_UNKNOWN ) == -1 ) {
11551137 return CommandFailure (EINVAL , " BPF compilation error" );
11561138 }
1157- filter-> func =
1158- bpf_jit_compile (il_code. bf_insns , il_code. bf_len , &filter-> mmap_size );
1159- pcap_freecode (&il_code );
1160- if (!filter-> func ) {
1161- free ( filter-> exp );
1139+
1140+ # ifdef __x86_64
1141+ filter. func = bpf_jit_compile (il. bf_insns , il. bf_len , &filter. mmap_size );
1142+ pcap_freecode (&il);
1143+ if (! filter. func ) {
11621144 return CommandFailure (ENOMEM , " BPF JIT compilation error" );
11631145 }
11641146#else
1165- if (pcap_compile_nopcap (SNAPLEN , DLT_EN10MB , // Ethernet
1166- &(filter->il_code ), exp, 1 , // optimize (IL only)
1167- PCAP_NETMASK_UNKNOWN ) == -1 ) {
1168- return CommandFailure (EINVAL , " BPF compilation error" );
1169- }
1147+ filter.il_code = il;
11701148#endif
1171- n_filters_++;
1172- qsort (filters_, n_filters_, sizeof (struct filter ), &compare_filter);
11731149
1174- filter++ ;
1150+ filters_. push_back ( filter) ;
11751151 }
11761152
1153+ std::sort (filters_.begin (), filters_.end (),
1154+ [](const Filter &a, const Filter &b) {
1155+ // descending order of priority number
1156+ return b.priority < a.priority ;
1157+ });
1158+
11771159 return CommandSuccess ();
11781160}
11791161
@@ -1182,8 +1164,19 @@ CommandResponse BPF::CommandClear(const bess::pb::EmptyArg &) {
11821164 return CommandSuccess ();
11831165}
11841166
1185- inline void BPF::process_batch_1filter (bess::PacketBatch *batch) {
1186- struct filter *filter = &filters_[0 ];
1167+ inline bool BPF::Match (const Filter &filter, u_char *pkt, u_int wirelen,
1168+ u_int buflen) {
1169+ #ifdef __x86_64
1170+ int ret = filter.func (pkt, wirelen, buflen);
1171+ #else
1172+ int ret = bpf_filter (filter.il_code .bf_insns , pkt, wirelen, buflen);
1173+ #endif
1174+
1175+ return ret != 0 ;
1176+ }
1177+
1178+ void BPF::ProcessBatch1Filter (bess::PacketBatch *batch) {
1179+ const Filter &filter = filters_[0 ];
11871180
11881181 bess::PacketBatch out_batches[2 ];
11891182 bess::Packet **ptrs[2 ];
@@ -1195,75 +1188,47 @@ inline void BPF::process_batch_1filter(bess::PacketBatch *batch) {
11951188
11961189 for (int i = 0 ; i < cnt; i++) {
11971190 bess::Packet *pkt = batch->pkts ()[i];
1198- int ret;
1199- int idx;
1200-
1201- #ifdef __x86_64
1202- ret = filter->func (pkt->head_data <uint8_t *>(), pkt->total_len (),
1203- pkt->head_len ());
1204- #else
1205- ret = bpf_filter (filter->il_code .bf_insns , pkt->head_data <uint8_t *>(),
1206- pkt->total_len (), pkt->head_len ());
12071191
1208- if (ret != 0 ) {
1209- ret = 1 ;
1192+ if (Match (filter, pkt->head_data <u_char *>(), pkt->total_len (),
1193+ pkt->head_len ())) {
1194+ *(ptrs[1 ]++) = pkt;
1195+ } else {
1196+ *(ptrs[0 ]++) = pkt;
12101197 }
1211- #endif
1212-
1213- idx = ret & 1 ;
1214- *(ptrs[idx]++) = pkt;
12151198 }
12161199
12171200 out_batches[0 ].set_cnt (ptrs[0 ] - out_batches[0 ].pkts ());
12181201 out_batches[1 ].set_cnt (ptrs[1 ] - out_batches[1 ].pkts ());
12191202
1220- if (out_batches[0 ].cnt ())
1221- RunChooseModule (0 , &out_batches[0 ]);
1222-
1223- /* matched packets */
1224- if (out_batches[1 ].cnt ())
1225- RunChooseModule (filter->gate , &out_batches[1 ]);
1203+ RunChooseModule (0 , &out_batches[0 ]);
1204+ RunChooseModule (filter.gate , &out_batches[1 ]); // matched packets
12261205}
12271206
12281207void BPF::ProcessBatch (bess::PacketBatch *batch) {
12291208 gate_idx_t out_gates[bess::PacketBatch::kMaxBurst ];
1230- int n_filters = n_filters_;
1231- int cnt;
1209+ int n_filters = filters_.size ();
12321210
12331211 if (n_filters == 0 ) {
12341212 RunNextModule (batch);
12351213 return ;
1236- }
1237-
1238- if (n_filters == 1 ) {
1239- process_batch_1filter (batch);
1214+ } else if (n_filters == 1 ) {
1215+ ProcessBatch1Filter (batch);
12401216 return ;
12411217 }
12421218
1243- cnt = batch->cnt ();
1244-
1245- /* slow version for general cases */
1246- for (int i = 0 ; i < cnt; i++) {
1219+ // slow version for general cases
1220+ for (int i = 0 ; i < batch->cnt (); i++) {
1221+ gate_idx_t gate = 0 ; // default gate for unmatched pkts
12471222 bess::Packet *pkt = batch->pkts ()[i];
1248- struct filter *filter = &filters_[0 ];
1249- gate_idx_t gate = 0 ; /* default gate for unmatched pkts */
12501223
1251- for ( int j = 0 ; j < n_filters; j++, filter++) {
1252- # ifdef __x86_64
1253- if (filter-> func ( pkt->head_data <uint8_t *>(), pkt->total_len (),
1254- pkt->head_len ()) != 0 ) {
1255- gate = filter-> gate ;
1224+ // high priority filters are checked first
1225+ for ( const Filter &filter : filters_) {
1226+ if (Match (filter, pkt->head_data <uint8_t *>(), pkt->total_len (),
1227+ pkt->head_len ())) {
1228+ gate = filter. gate ;
12561229 break ;
12571230 }
1258- #else
1259- if (bpf_filter (filter->il_code .bf_insns , pkt->head_data <uint8_t *>(),
1260- pkt->total_len (), pkt->head_len ())) {
1261- gate = filter->gate ;
1262- break ;
1263- }
1264- #endif
12651231 }
1266-
12671232 out_gates[i] = gate;
12681233 }
12691234
0 commit comments