Design an IP filter using CIDR rules
Company: Databricks
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates understanding of IP addressing and CIDR notation, bit-level conversion between prefixes and integer ranges, and the design of scalable data structures and algorithms for prefix/range queries, rule priority handling, and rule-set operations (allow/deny semantics).
Part 1: Dynamic IPv4 firewall with CIDR matching
Constraints
- 1 <= len(commands) <= 200000
- 0 <= priority <= 10^9
- All IP addresses are valid IPv4 addresses and all CIDR prefixes satisfy 0 <= p <= 32
- REMOVE on a non-existent or already removed rule does nothing
Examples
Input: ("priority", ["ADD 10.0.0.0/8 allow 5", "ADD 10.1.0.0/16 deny 10", "QUERY 10.1.2.3", "ADD 10.1.2.0/24 deny 1", "QUERY 10.1.2.3", "REMOVE 3", "QUERY 10.1.2.3"])
Expected Output: ["allow", "deny", "allow"]
Explanation: In priority mode, the smallest priority wins among all matching prefixes. After removing rule 3, the /8 allow rule wins again.
Input: ("lpm", ["ADD 0.0.0.0/0 deny 100", "ADD 192.168.1.0/24 allow 50", "ADD 192.168.1.128/25 deny 1", "QUERY 192.168.1.10", "QUERY 192.168.1.200", "QUERY 8.8.8.8"])
Expected Output: ["allow", "deny", "deny"]
Explanation: In longest-prefix-match mode, the deepest matching prefix wins before priority is considered.
Input: ("priority", ["QUERY 1.1.1.1", "REMOVE 1", "ADD 255.255.255.255/32 allow 7", "QUERY 255.255.255.255", "QUERY 255.255.255.254"])
Expected Output: ["none", "allow", "none"]
Explanation: Edge case: querying with no active rules returns none. A /32 rule matches exactly one address.
Input: ("priority", ["ADD 1.1.1.0/24 deny 3", "ADD 1.1.1.0/24 allow 3", "QUERY 1.1.1.4", "REMOVE 1", "QUERY 1.1.1.4"])
Expected Output: ["deny", "allow"]
Explanation: When both priority and prefix length tie, the smaller rule id wins.
Hints
- A binary trie over the 32 bits of an IPv4 address lets you inspect every matching prefix on one root-to-leaf path.
- For removals, lazy deletion works well: mark a rule inactive, and discard it later when it reaches the top of a heap.
Part 2: CIDR block overlap and coverage queries
Constraints
- 1 <= len(commands) <= 20000
- All addresses are valid IPv4 CIDR blocks with 0 <= p <= 32
- REMOVE on a non-existent or already removed rule does nothing
- The intended solution supports fast overlap and coverage queries; CONFLICTS may spend O(A) time scanning active rules to enumerate matching ids
Examples
Input: ["ADD 10.0.0.0/25 allow", "ADD 10.0.0.128/25 allow", "COVERED_ALLOW 10.0.0.0/24", "OVERLAP 10.0.1.0/24", "ADD 10.0.0.64/26 deny", "CONFLICTS 10.0.0.0/24", "COVERED_DENY 10.0.0.64/26", "REMOVE 3", "CONFLICTS 10.0.0.0/24"]
Expected Output: ["YES", "NO", "[1, 2, 3]", "YES", "[]"]
Explanation: Two adjacent /25 allow rules together cover the full /24. After adding a deny block inside that range, the overlapping rules on the /24 contain both actions, so they conflict.
Input: ["ADD 0.0.0.0/1 deny", "ADD 128.0.0.0/1 deny", "COVERED_DENY 0.0.0.0/0", "OVERLAP 192.168.1.0/24", "CONFLICTS 192.168.1.0/24"]
Expected Output: ["YES", "YES", "[]"]
Explanation: The two /1 deny rules partition the whole IPv4 space, so together they cover /0. There is overlap with the query block, but no allow rule, so no conflict.
Input: ["OVERLAP 1.2.3.0/24", "COVERED_ALLOW 1.2.3.0/24", "CONFLICTS 1.2.3.0/24"]
Expected Output: ["NO", "NO", "[]"]
Explanation: Edge case: with no rules, there is no overlap, no coverage, and no conflict.
Input: ["ADD 255.255.255.255/32 allow", "COVERED_ALLOW 255.255.255.255/32", "OVERLAP 255.255.255.254/31", "REMOVE 1", "OVERLAP 255.255.255.255/32"]
Expected Output: ["YES", "YES", "NO"]
Explanation: A /32 rule covers exactly one address. The /31 query overlaps it before removal and does not overlap after removal.
Input: ["ADD 192.168.1.0/25 allow", "COVERED_ALLOW 192.168.1.0/24"]
Expected Output: ["NO"]
Explanation: A single /25 covers only half of the /24, so full coverage fails.
Hints
- Turn each CIDR block into an integer interval [start, end]. Then overlap becomes a range problem.
- Because all commands are known before processing starts, coordinate compression plus a range-add segment tree can maintain coverage counts over elementary IP segments.